如何从一张图片中提取出所有跟另一张给定图片类似的物体, 给出python代码
时间: 2023-12-28 12:05:42 浏览: 219
这个问题可以使用计算机视觉中的目标检测技术来解决。常见的目标检测算法有基于深度学习的SSD、YOLO、Faster R-CNN等。这里以Faster R-CNN为例,给出Python代码实现。
首先,需要安装一些必要的Python库,包括tensorflow、keras、matplotlib等。
```python
pip install tensorflow keras matplotlib
```
然后,需要下载Faster R-CNN模型和预训练权重。这里使用Keras提供的frcnn模块,可以直接从GitHub上下载。
```python
git clone https://github.com/yhenon/keras-frcnn.git
```
接着,需要定义一些辅助函数,用于读取图片、将目标框转换为坐标等操作。
```python
import cv2
import numpy as np
def format_img_size(img, C):
"""调整输入图片的大小"""
img_min_side = float(C.im_size)
(height,width,_) = img.shape
if width <= height:
ratio = img_min_side/width
new_height = int(ratio * height)
new_width = int(img_min_side)
else:
ratio = img_min_side/height
new_width = int(ratio * width)
new_height = int(img_min_side)
img = cv2.resize(img, (new_width, new_height), interpolation=cv2.INTER_CUBIC)
return img, ratio
def format_img_channels(img, C):
"""将输入图片的通道数调整为3"""
img = np.transpose(img, (2, 0, 1))
img = np.expand_dims(img, axis=0)
img = img[:,:,:,:3]
img = img.astype(np.float32)
img[:, :, :, 0] -= C.img_channel_mean[0]
img[:, :, :, 1] -= C.img_channel_mean[1]
img[:, :, :, 2] -= C.img_channel_mean[2]
img /= C.img_scaling_factor
return img
def get_real_coordinates(ratio, x1, y1, x2, y2):
"""将目标框的坐标还原到原始图片上"""
real_x1 = int(round(x1 // ratio))
real_y1 = int(round(y1 // ratio))
real_x2 = int(round(x2 // ratio))
real_y2 = int(round(y2 // ratio))
return (real_x1, real_y1, real_x2 ,real_y2)
```
最后,使用Faster R-CNN模型检测图片中的物体,并输出与给定图片相似的物体。
```python
from keras import backend as K
from keras_frcnn import config, data_generators
from keras_frcnn import roi_helpers
from keras_frcnn import roi_helpers
from keras_frcnn.models import rpn, classifier
from keras_frcnn.utils import simple_parser
from keras_frcnn.visualize import draw_boxes
def detect_similar_objects(img_path, given_img_path, overlap_thresh=0.5):
# 加载配置
config_output_filename = "config.pickle"
with open(config_output_filename, 'rb') as f_in:
C = pickle.load(f_in)
# 加载模型
model_path = "model_frcnn.hdf5"
model_rpn, model_classifier_only, model_classifier = rpn.rpn_model(C, num_classes=len(C.class_mapping))
model_rpn.load_weights(model_path, by_name=True)
model_classifier.load_weights(model_path, by_name=True)
# 读取图片
img = cv2.imread(img_path)
given_img = cv2.imread(given_img_path)
# 调整图片大小和通道数
X, ratio = format_img_size(img, C)
X = format_img_channels(X, C)
# 在图片上进行目标检测
_, _, _, rpn_out = model_rpn.predict(X)
rois = roi_helpers.rpn_to_roi(rpn_out[0], rpn_out[1], C, K.image_dim_ordering(), overlap_thresh=overlap_thresh)
rois = np.expand_dims(rois, axis=0)
_, _, _, _, _, probs = model_classifier.predict([X, rois])
# 输出与给定图片相似的物体
similar_objs = []
for i in range(probs.shape[1]):
class_idx = np.argmax(probs[0,i,:])
if C.class_mapping[class_idx] == "bg":
continue
cls_name = C.class_mapping[class_idx]
if cls_name not in similar_objs:
img_box = rois[0, i, :]
(x1, y1, x2, y2) = get_real_coordinates(ratio, img_box[0], img_box[1], img_box[2], img_box[3])
obj = img[y1:y2, x1:x2, :]
obj_gray = cv2.cvtColor(obj, cv2.COLOR_BGR2GRAY)
given_gray = cv2.cvtColor(given_img, cv2.COLOR_BGR2GRAY)
if obj_gray.shape == given_gray.shape:
diff = cv2.absdiff(obj_gray, given_gray)
if np.sum(diff) == 0:
similar_objs.append(cls_name)
return similar_objs
```
使用示例:
```python
img_path = "test.jpg"
given_img_path = "given.jpg"
similar_objs = detect_similar_objects(img_path, given_img_path)
print(similar_objs)
```
输出结果为与给定图片相似的物体名称列表。
阅读全文