检测使用cv2.HoughCircles检测到的圆圈颜色的最佳方法是什么?

时间:2019-07-05 17:29:36

标签: python opencv

我对图像处理和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 个答案:

答案 0 :(得分:1)

我设法通过以下步骤找到每个圆圈的主色: 首先,我用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