0

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 関数にまったく慣れていないので、私の質問は、検出率を改善する方法があるということです。どんな助けにも感謝します。

4

0 に答える 0