Каков наилучший способ определения цвета кругов, обнаруженных с помощью cv2.HoughCircles? - PullRequest
0 голосов
/ 05 июля 2019

Я довольно новичок в обработке изображений и opencv. Мне нужно определить цвета некоторых шаров. Я начал с обнаружения этих шаров, используя cv2.HoughCircles, но после этого я застрял.

Большинство ответов в Интернете предлагают использовать контуры и сопоставлять их с цветовыми диапазонами или вычислять расстояние до ближайшего цвета. Но я не смог найти способ преобразовать вывод cv2.HoughCircles в контуры (я не уверен, если это возможно)

 while reader.isOpened():
        ret, frame = reader.getCapture()
        if ret:
            workingFrame = imutils.resize(frame, width=600)

            copy = frame.copy()
            grayMask = cv2.cvtColor(copy, cv2.COLOR_BGR2GRAY)

            circlesArr = cv2.HoughCircles(grayMask, cv2.HOUGH_GRADIENT, 1.3, 20, param1=40, param2=30, minRadius=5, maxRadius=20)

            if circlesArr is not None:
                for circle in circlesArr[0, :]:
                    # detect colors             
                    cv2.circle(frame, (circle[0], circle[1]), circle[2], GREEN, 1)
                    cv2.circle(frame, (circle[0], circle[1]), 2, GREEN, 2)

            cv2.imshow("frame", frame)
        else:
            break

        if quitKeyPressed():
            break

Image to be processed

1 Ответ

1 голос
/ 07 июля 2019

Мне удалось найти доминирующий цвет для каждого круга, выполнив следующие шаги: Сначала я обнаружил круги с cv2.HoughCircles:

def detectCirclesWithDp(frame, dp=1):
    blurred = cv2.medianBlur(frame, 25)
    grayMask = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY)
    # cannyMask = cv2.Canny(grayMask, 50, 240)
    return cv2.HoughCircles(grayMask, cv2.HOUGH_GRADIENT, dp, 40, param1=10, param2=30, minRadius=20, maxRadius=70)

Затем для каждого круга я выбрал окружность:

def getROI(frame, x, y, r):
    return frame[int(y-r/2):int(y+r/2), int(x-r/2):int(x+r/2)]

После этого я вычисляю самый доминирующий цвет в регионе, используя kmeans и цветовые маски:

COLOR_NAMES = [RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE, RED_2]

COLOR_RANGES_HSV = {
    "red": [(0, 50, 10), (10, 255, 255)],
    "orange": [(10, 50, 10), (25, 255, 255)],
    "yellow": [(25, 50, 10), (35, 255, 255)],
    "green": [(35, 50, 10), (80, 255, 255)],
    "cyan": [(80, 50, 10), (100, 255, 255)],
    "blue": [(100, 50, 10), (130, 255, 255)],
    "purple": [(130, 50, 10), (170, 255, 255)],
    "red ": [(170, 50, 10), (180, 255, 255)]
}

def getMask(frame, color):
    blurredFrame = cv2.GaussianBlur(frame, (3, 3), 0)
    hsvFrame = cv2.cvtColor(blurredFrame, cv2.COLOR_BGR2HSV)

    colorRange = COLOR_RANGES_HSV[color]
    lower = np.array(colorRange[0])
    upper = np.array(colorRange[1])

    colorMask = cv2.inRange(hsvFrame, lower, upper)
    colorMask = cv2.bitwise_and(blurredFrame, blurredFrame, mask=colorMask)

    return colorMask

def getDominantColor(roi):
    roi = np.float32(roi)

    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
    K = 4
    ret, label, center = cv2.kmeans(roi, K, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

    center = np.uint8(center)
    res = center[label.flatten()]
    res2 = res.reshape(roi.shape)

    pixelsPerColor = []
    for color in COLOR_NAMES:
        mask = getMask(res2, color)
        greyMask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
        count = cv2.countNonZero(greyMask)
        pixelsPerColor.append(count)

    return COLOR_NAMES[pixelsPerColor.index(max(pixelsPerColor))]

Все вместе:

def detect():
    circles = detector.detectCirclesWithDp(imgCopy)
    if circles is not None:
        for circle in circles[0, :]:
            if imageUtils.inFrame(img, circle[0], circle[1]):
                roi = imageUtils.getROI(imgCopy, circle[0], circle[1], circle[2])
                color = colorlabeler.getDominantColor(roi)
                cv2.circle(img, (circle[0], circle[1]), circle[2], colorlabeler.COLORS_RGB["green"], 1)
                cv2.circle(img, (circle[0], circle[1]), 2, colorlabeler.COLORS_RGB["green"], 2)
                cv2.putText(img, color, (int(circle[0] + 40), int(circle[1] + 20)), cv2.FONT_HERSHEY_SIMPLEX, 0.5,
                               colorlabeler.COLORS_RGB["green"])

    while True:
        cv2.imshow("frame", img)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break

    cv2.destroyAllWindows()

И, наконец, результат:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...