【OpenCV】ツムを判別する方法2

アプリ開発

前回 ツムを判別する方法に、ハフ変換を使って円を検出しました。

今回はハフ変換で見つけたツムを、識別してグループ化していきます。

処理

import cv2
import numpy
import math


def main():

    img = cv2.imread('IMG_0941.png')
    img = img[300: 900, 0: 554]

    circles = GetHoughCircles(img)
    averaging = GetAveraging(img, circles)

    # 描画
    for item in averaging:
        cv2.circle(img, (item['x'], item['y']), item['radius'],
                   (item['blue'], item['green'], item['red']), thickness=-1)
        cv2.putText(img, str(item['index']), (item['x']-10, item['y']+12),
                    cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), thickness=2)

    cv2.imshow('detected circles', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


def GetHoughCircles(img):
    cimg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    circles = cv2.HoughCircles(cimg, cv2.HOUGH_GRADIENT, 1.2,
                               30, param1=100, param2=40, minRadius=20, maxRadius=54)
    circles = numpy.uint16(numpy.around(circles))
    return circles


def GetAveraging(img, circles):
    average = []

    for i in circles[0, :]:
        # img[top : bottom, left : right]
        imgcrop = img[i[1]-2: i[1]+2, i[0]-2: i[0]+2]
        imgblur = cv2.blur(imgcrop, (10, 10))

        b = math.floor(imgblur.T[0].flatten().mean() * 0.1) * 10
        g = math.floor(imgblur.T[1].flatten().mean() * 0.1) * 10
        r = math.floor(imgblur.T[2].flatten().mean() * 0.1) * 10

        average.append({"blue": b, "green": g, "red": r,
                       'x': i[0], 'y': i[1], 'radius': i[2]})

    SetGrouping(average)

    return average


def SetGrouping(averaging):

    group = []
    for average in averaging:
        isOK = False
        idx = 0

        # 初回
        if len(group) <= 0:
            average['index'] = idx
            group.append(average)

        for item in group:

            if item['blue'] - 10 <= average['blue'] and average['blue'] <= item['blue'] + 10 and \
                    item['green'] - 10 <= average['green'] and average['green'] <= item['green'] + 10 and \
                    item['red'] - 10 <= average['red'] and average['red'] <= item['red'] + 10:

                isOK = True
                average['index'] = item['index']
                break

        if not isOK:
            idx = len(group)
            average['index'] = idx
            group.append(average)

    return


if __name__ == '__main__':
    main()

使った機能

画像のぼかし (平滑化)

cv2.blur() を使ってツムにぼかしを入れてから、円の中心の色を取得しています。精度を上げたかったので、下一桁を切り捨ててからグループ化処理をしました。

グループ化処理では、ある程度似た色を1つのグループとするようにしています。まったく同じ色ってのは、難しかったのでここは調整が必要ですね。

終わりに

後は、最短経路をつなぐアルゴリズムですかね。

タイトルとURLをコピーしました