我正在使用 OpenCV 4.5.4 在另一个图像中定位图像。为此, matchTemplate 函数。
任务是在桌子上找到“芯片”,让机器人将它们分类到杂志中以进行自动化生产。桌子上只有一种“芯片”,但大约有一半是翻转的,因此机器人会将它们分类到 2 个杂志中,然后翻转其中一个以进行下一个生产步骤。并非所有芯片都必须在一个步骤中检测到,因为它们重叠很多。机器人可以整理出检测到的照片,然后回到静止位置拍摄新照片。
示例场景: 场景
对于芯片的黄金面来说,它运作良好
模板:object_a
但是当我使用另一侧的模板时,我得到的正确检测很少,当降低匹配阈值时,它会在物体之前错误地检测到金属台。
模板:object_b
结果阈值 0.5:result_obj_b_0_5
结果阈值 0.4:result_obj_b_0_4
两个模板都是从场景图像中剪切出来的,只是旋转以获得正确的检测框。
我的代码:
import cv2
import numpy as np
def rotate_image(image, angle):
image_center = tuple(np.array(image.shape[1::-1]) / 2)
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
return result
def draw_box(img, pt0, pt1, pt2, pt3, color=(0,255,0), thickness=2):
cv2.line(img, (int(pt0[0]), int(pt0[1])), (int(pt1[0]), int(pt1[1])), color, thickness)
cv2.line(img, (int(pt1[0]), int(pt1[1])), (int(pt2[0]), int(pt2[1])), color, thickness)
cv2.line(img, (int(pt2[0]), int(pt2[1])), (int(pt3[0]), int(pt3[1])), color, thickness)
cv2.line(img, (int(pt3[0]), int(pt3[1])), (int(pt0[0]), int(pt0[1])), color, thickness)
def rotated_coord(rotation_center, angle, points):
M = cv2.getRotationMatrix2D(rotation_center, angle, 1.0)
points = np.array(points)
ones = np.ones(shape=(len(points),1))
points_ones = np.concatenate((points,ones), axis=1)
transformed_pts = M.dot(points_ones.T).T
return transformed_pts
scene = cv2.imread('scene.png')
template = cv2.imread('object_b.png')
result = scene.copy()
h, w, c = template.shape
step = 5
for i in range(step,360+step,step):
step_img = rotate_image(scene, i)
res = cv2.matchTemplate(step_img,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.5
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
pt0, pt1, pt2, pt3 = pt, (pt[0], pt[1] +h), (pt[0] + w, pt[1] + h), (pt[0] + w, pt[1])
draw_box(step_img, pt0, pt1, pt2, pt3)
pt0, pt1, pt2, pt3 = rotated_coord(tuple(np.array(scene.shape[1::-1]) / 2), -i, [pt0, pt1, pt2, pt3])
draw_box(result, pt0, pt1, pt2, pt3)
cv2.imshow('Result',np.hstack((step_img, result)))
cv2.waitKey(1)
cv2.waitKey()
上面的代码只是演示问题的一个工作示例。我改进了代码以过滤重复检测并显示找到的框的旋转轴。
示例提炼结果
由于我对 matchTemplate 函数很不熟悉,我的问题是有没有办法提高检测率。我感谢任何帮助。