間違い探しに関しては、グレースケールにしてから比較し、違いの部分を閾値判定で2値化する方法がWebで紹介されているが、色の判定に難がある傾向がみられた。


そこで、それぞれの画像をR、G、Bに分けてから、RとR、GとG、BとBを比較し、違いの部分を閾値判定で2値化してから合成する方法を検討した。

R、G、Bそれぞれの2値化は簡単に出来たが、統合に手間取った。AIに質問しても、まともな答えが返ってこない。

Rに統合したいのに、RGB画像にしてからGBを消してRのみにする答えしか返らない。

RGB別の画像を表示しても、きちんとできており、全く問題無いのに統合ができない。

# RGB別の画像を表示する関数
def display_images3(title, binary_r, binary_g, binary_b):
    ut_now = datetime.datetime.now()
    print(ut_now, 'RGB別の画像を表示')
    # 画像を表示用にリサイズ
    resized_image_r = cv2.resize(binary_r, (600, 600))
    resized_image_g = cv2.resize(binary_g, (600, 600))
    resized_image_b = cv2.resize(binary_b, (600, 600))
    # 結果表示用のウィンドウを作成
    layout = [
        [sg.Text(title)],
        [sg.Image(data=cv2.imencode('.png', resized_image_r)[1].tobytes()),
         sg.Image(data=cv2.imencode('.png', resized_image_g)[1].tobytes()),
         sg.Image(data=cv2.imencode('.png', resized_image_b)[1].tobytes())]
    ]

    # ウィンドウを表示
    window = sg.Window('Color Differences with Opening', layout)

    while True:
        event, values = window.read()
        if event == sg.WIN_CLOSED:
            break

    window.close()


結局何が悪かったかと言えば、2値化しているのに、色情報を持っていると勘違いしていたということ。

単なる白黒画像が3つあると考えれば、足し算をすれば合成できることに気づかなかった!

ぼけ始め?

def compare_images(common_a, common_b, threshold=30):
    # 画像を読み込む
    image1 = common_a
    image2 = common_b

    # RGBチャンネルを分割
    ut_now = datetime.datetime.now()
    print(ut_now, 'RGBチャンネルを分割')
    r1, g1, b1 = cv2.split(image1)
    r2, g2, b2 = cv2.split(image2)

    # それぞれのチャンネルで差分を計算
    ut_now = datetime.datetime.now()
    print(ut_now, 'それぞれのチャンネルで差分を計算')
    diff_r = cv2.absdiff(r1, r2)
    diff_g = cv2.absdiff(g1, g2)
    diff_b = cv2.absdiff(b1, b2)

    # 閾値を適用して二値化
    ut_now = datetime.datetime.now()
    print(ut_now, '閾値を適用して二値化')
    _, binary_r = cv2.threshold(diff_r, threshold, 255, cv2.THRESH_BINARY)
    _, binary_g = cv2.threshold(diff_g, threshold, 255, cv2.THRESH_BINARY)
    _, binary_b = cv2.threshold(diff_b, threshold, 255, cv2.THRESH_BINARY)

    # display_images3('RGBをそれぞれ二値化', binary_r, binary_g, binary_b)

    # RGBをRに合成して差分が大きい部分のみを抽出
    ut_now = datetime.datetime.now()
    print(ut_now, 'RGBをRに合成して差分が大きい部分のみを抽出')
    binary_r = binary_b + binary_g + binary_r
    diff_combined = cv2.merge([binary_r, np.zeros_like(binary_g), np.zeros_like(binary_b)])

ここからは早く、違いの部分を四角で囲み表示するパターンと、統合された2値化画像を表示するパターンを並べて表示できるようになった。

    # 差分がある領域を赤い四角で囲む
    ut_now = datetime.datetime.now()
    print(ut_now, '差分がある領域を30ドット大きい赤い四角で囲む')
    for contour in contours:
        if cv2.contourArea(contour) > 5:  # 小さな変更を無視する
            x, y, w, h = cv2.boundingRect(contour)
            # 画像の境界を超えないように調整
            x = max(0, x - 15)
            y = max(0, y - 15)
            xw = min(image1.shape[1], x + w + 30)
            yh = min(image1.shape[0], y + h + 30)
            # 四角を30ドット大きく描画
            cv2.rectangle(image1, (x, y), (xw, yh), (0, 0, 255), 3)


小さな画像を拡大してから変形した画像でマッチングしていると、細かな誤検出が多く出ることもあるが、実際は3264x2448の撮影画像を微妙にマッチングすることを想定しているため、特に問題ないと判断し、検査プログラム作成に進むことにした。



コメント

このブログの人気の投稿