OpenCV 4.5.4 を使用して、別の画像内の画像を見つけています。そしてそのための matchTemplate 関数。
タスクは、ロボットが自動生産のためにそれらをマガジンに分類するために、テーブルで「チップ」を見つけることです。テーブルには 1 種類の「チップ」しかありませんが、その半分程度が裏返されているため、ロボットはそれらを 2 つのマガジンに仕分けし、次の生産ステップのために 1 つを裏返します。チップは多く重複するため、1 つのステップですべてのチップを検出する必要はありません。ロボットは検出されたものを整理し、静止位置に戻って新しい写真を作成できます。
シーンの例: シーン
チップの黄金面については、非常にうまく機能しています
テンプレート: object_a
結果: result_obj_a_0_5
しかし、反対側にテンプレートを使用すると、正しい検出がほとんど得られず、一致するしきい値を下げると、オブジェクトの前に金属製のテーブルが誤って検出されます。
テンプレート: 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 関数にまったく慣れていないので、私の質問は、検出率を改善する方法があるということです。どんな助けにも感謝します。