繁体   English   中英

Python opencv,基于颜色/形状的检测

[英]Python opencv, color/shape based detection

我正在尝试根据它们的形状和颜色检测图片中的某些对象。

这是原始图像,我想找到两个粉红色的杯子(以绿色突出显示)

在此处输入图像描述

我正在使用颜色蒙版来隔离两个杯子,结果非常好,如您在此处看到的:

在此处输入图像描述

问题是可能还有其他具有类似 colors 的对象也被检测到,例如右下角的红色椅子。

我可以更好地调整颜色蒙版的参数……例如,我可以更具体地隔离颜色,使用膨胀/侵蚀来减少噪音。 但是仅仅依靠colors并不理想,而且容易出错。 例如,如果我只是稍微转动一下椅子,它上面的灯光就会改变,我又会听到噪音。

为了让一切变得更健壮,我一直在尝试通过使用 cv2.approxPolyDP 的形状来进一步 select 杯子,但我经常无法将杯子与嘈杂的区域分开。 由颜色掩码识别的杯子形状通常不是很精确,因此近似多边形最多可以由 10 段组成,这使得将其与噪声区分开来是无用的。

这是我正在使用的代码:

import cv2
import numpy as np 


def main():
    cap = cv2.VideoCapture(0)
    cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)

    cv2.namedWindow("Color selection")
    cv2.createTrackbar("Low_H", "Color selection", 114, 255, nothing)
    cv2.createTrackbar("Low_S", "Color selection", 76, 255, nothing)
    cv2.createTrackbar("Low_V", "Color selection", 145, 255, nothing)
    cv2.createTrackbar("Up_H", "Color selection", 170, 255, nothing)
    cv2.createTrackbar("Up_S", "Color selection", 255, 255, nothing)
    cv2.createTrackbar("Up_V", "Color selection", 255, 255, nothing)
    cv2.createTrackbar("N_erosion", "Color selection", 4, 50, nothing)
    cv2.createTrackbar("epsilon", "Color selection", 2, 20, nothing)
    cv2.createTrackbar("Area_min", "Color selection", 52, 500, nothing)
    cv2.createTrackbar("Area_max", "Color selection", 1800, 4000, nothing)


    while True:
        ret, frame = cap.read()
        frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
        frame_hsv_blur = cv2.GaussianBlur(frame_hsv, (7, 7), 0)

        ## parameters selection
        l_h = cv2.getTrackbarPos("Low_H", "Color selection")
        l_s = cv2.getTrackbarPos("Low_S", "Color selection")
        l_v = cv2.getTrackbarPos("Low_V", "Color selection")
        u_h = cv2.getTrackbarPos("Up_H", "Color selection")
        u_s = cv2.getTrackbarPos("Up_S", "Color selection")
        u_v = cv2.getTrackbarPos("Up_V", "Color selection")
        N_erode = cv2.getTrackbarPos("N_erosion", "Color selection")
        eps = cv2.getTrackbarPos("epsilon", "Color selection")/100
        area_min = cv2.getTrackbarPos("Area_min", "Color selection")
        area_max = cv2.getTrackbarPos("Area_max", "Color selection")
        N_erode = N_erode if N_erode>0 else 1

        lower_values = np.array([l_h, l_s, l_v])
        upper_values = np.array([u_h, u_s, u_v])
        mask = cv2.inRange(frame_hsv_blur, lower_values, upper_values)
        kernel = np.ones((N_erode,N_erode), np.uint8)
        mask = cv2.erode(mask, kernel)

        ## find contours in image based on color mask
        contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        for contour in contours:
            area = cv2.contourArea(contour)
            perimeter = cv2.arcLength(contour, True)
            approx = cv2.approxPolyDP(contour, eps*perimeter, True)
            x,y,w,h = cv2.boundingRect(contour)
            if (area_min < area < area_max) and (2<len(approx)):
                x_0 = int(x+w/2)
                y_0 = int(y+h/2)
                frame = cv2.putText(frame, str(len(approx)), (x,y), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255,0,0), thickness=3)
                frame = cv2.circle(frame, (x_0, y_0), 10, (255,255,50), -1)

        cv2.imshow("tracking", frame)
        cv2.imshow("mask", mask)


        key = cv2.waitKey(1)
        if key == ord('q'):
            break
        elif key == ord('s'):
            cv2.imwrite("saved_image.jpg", frame)

    cv2.destroyAllWindows()
    cap.release()


def nothing(x):
    pass


if __name__ == '__main__':
    main()

所以,我的主要问题是关于形状检测 我想知道我是否可以尝试一种不同的方法来更好地利用我正在寻找一个非常具体的形状这一事实,也许使用 cv2.approxPolyDP 以外的其他东西。 有什么建议么?

我检查了你的照片。 这是我在 5 分钟内能做的最好的事情。 多练习一点,就会出现更好的结果。

import cv2
import numpy as np 
from google.colab.patches import cv2_imshow


img = cv2.imread("/content/JSjbB.png")
cv2_imshow(img)
img_output = img
cv2_imshow(img_output)
frame_hsv = cv2.cvtColor(img_output, cv2.COLOR_BGR2HSV)
frame_hsv_blur = cv2.GaussianBlur(frame_hsv, (7, 7), 0)
#print(frame_hsv_blur)
lower_values = np.array([130, 100,0])
upper_values = np.array([170,255, 255])
mask = cv2.inRange(frame_hsv_blur, lower_values, upper_values)
cv2_imshow(mask)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(mask,kernel,iterations = 3)
dilation = cv2.dilate(erosion,kernel,iterations = 3)
cv2_imshow(dilation)

结果是这样的:

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM