【问题标题】:Detect different color blob opencv检测不同颜色的blob opencv
【发布时间】:2017-03-21 10:12:28
【问题描述】:

我是 opencv 新手,对于一个学校项目,我需要用相机检测红色和绿色圆圈,所以我使用了 blobdetection,但它检测到我这两种颜色,我认为我的面具不好,每种颜色都与特定操作相关联。

目前我的代码很好地检测到同一页面上的红色和绿色圆圈,但我希望它只检测白色页面上的红色圆圈。

感谢您的帮助

# Standard imports
import cv2
import numpy as np;

    # Read image
im = cv2.VideoCapture(0)

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 100;
params.maxThreshold = 200;

# Filter by Area.
params.filterByArea = True
params.minArea = 200
params.maxArea = 20000

# Filter by Circularity
params.filterByCircularity = True
params.minCircularity = 0.1

# Filter by Convexity
params.filterByConvexity = True
params.minConvexity = 0.1

# Filter by Inertia
params.filterByInertia = True
params.minInertiaRatio = 0.1


blueLower = (0,85,170)  #100,130,50
blueUpper = (140,110,255) #200,200,130


while(1):

    ret, frame=im.read()

    mask = cv2.inRange(frame, blueLower, blueUpper)
    mask = cv2.erode(mask, None, iterations=0)
    mask = cv2.dilate(mask, None, iterations=0)
    frame = cv2.bitwise_and(frame,frame,mask = mask)

# Set up the detector with default parameters.
    detector = cv2.SimpleBlobDetector_create(params)

# Detect blobs.
    keypoints = detector.detect(mask)

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob
    im_with_keypoints = cv2.drawKeypoints(mask, keypoints, np.array([]), (0,0,255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)


# Display the resulting frame

    frame = cv2.bitwise_and(frame,im_with_keypoints,mask = mask)

    cv2.imshow('frame',frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
im.release()
cv2.destroyAllWindows()

编辑 1: 代码更新

现在我遇到了一个问题,我的整个圆圈都没有被检测到。

No Blob Detection

第二版

# Standard imports
import cv2
import numpy as np;

# Read image
im = cv2.VideoCapture(0)

while(1):
        ret, frame=im.read()


        lower = (130,150,80)  #130,150,80
        upper = (250,250,120) #250,250,120
        mask = cv2.inRange(frame, lower, upper)
        lower, contours, upper = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        blob = max(contours, key=lambda el: cv2.contourArea(el))
        M = cv2.moments(blob)
        center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
        canvas = im.copy()
        cv2.circle(canvas, center, 2, (0,0,255), -1)

        cv2.imshow('frame',frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
                break
im.release()
cv2.destroyAllWindows()

【问题讨论】:

    标签: python opencv


    【解决方案1】:

    您需要计算出您的绿色的 BGR 数字是多少(假设是 [0, 255, 0]),然后创建一个遮罩,忽略绿色周围容差之外的任何颜色:

    mask = cv2.inRange(image, lower, upper)
    

    看看this教程一步一步。

    玩弄下层和上层以获得正确的行为。然后就可以在遮罩中找到轮廓了:

    _, contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, 
                                                        cv2.CHAIN_APPROX_NONE)
    

    然后通过contours列表找到最大的一个(过滤掉任何可能的噪音):

    blob = max(contours, key=lambda el: cv2.contourArea(el))
    

    这就是你的最后一个“blob”。您可以通过以下方式找到中心:

    M = cv2.moments(blob)
    center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
    

    您可以将此中心绘制到图像的副本上,以进行检查:

    canvas = im.copy()
    cv2.circle(canvas, center, 2, (0,0,255), -1)
    

    显然,这是假设图像中只有一个绿色球,没有其他绿色球。但这是一个开始。

    编辑 - 回复第二个帖子

    我认为以下应该可行。我还没有测试过,但您至少应该能够对显示的画布和蒙版进行更多调试:

    # Standard imports
    import cv2
    import numpy as np;
    
    # Read image
    cam = cv2.VideoCapture(0)
    
    while(1):
            ret, frame = cam.read()
    
            if not ret:
                break
    
            canvas = frame.copy()
    
    
            lower = (130,150,80)  #130,150,80
            upper = (250,250,120) #250,250,120
            mask = cv2.inRange(frame, lower, upper)
            try:
                # NB: using _ as the variable name for two of the outputs, as they're not used
                _, contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
                blob = max(contours, key=lambda el: cv2.contourArea(el))
                M = cv2.moments(blob)
                center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
    
                cv2.circle(canvas, center, 2, (0,0,255), -1)
    
            except (ValueError, ZeroDivisionError):
                pass
    
            cv2.imshow('frame',frame)
            cv2.imshow('canvas',canvas)
            cv2.imshow('mask',mask)
    
            if cv2.waitKey(1) & 0xFF == ord('q'):
                    break
    im.release()
    cv2.destroyAllWindows()
    

    【讨论】:

    • 谢谢,我的面具现在好多了,我有一个漂亮的圆圈,但是有一个嘈杂的灰色背景但是我无法使用 cv2.bitwise_and,而且我的 SimpleBlobDetector 没有工作有了我现在得到的红色圆圈,我需要反转遮罩/颜色吗?非常感谢
    • 在框架图像上创建一个蒙版,然后 bitwise_and 你的蒙版与框架一起得到你的蒙版框架。然后运行你的 BlobDetector。
    • 我的颜色圈很好,但它们没有被检测为斑点,因为我认为它们不是空的。我用这个learnopencv.com/blob-detection-using-opencv-python-c 但它对我不起作用
    • 我没有使用过 SimpleBlobDetector。您可以自己完成并获得更多控制权。使用a, contours, b = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)找到你的球周围的轮廓,然后你可以得到它的质心并用它来跟踪。
    • 编辑的答案更详细
    【解决方案2】:

    如果您想按颜色进行过滤,您应该使用 HSV 颜色空间以获得更好的效果。

    ret, frame=im.read()
    

    frame= cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 将此添加到您的代码中

    mask = cv2.inRange(frame, blueLower, blueUpper)
    

    【讨论】:

    • 过滤器没问题,但 SimpleBlobDetector 不适用于整圈
    • SimpleBlobDetector 有时无法正常工作,请检查此以了解基于轮廓的检测-> github.com/mribrahim/Blob-Detection。您可以轻松地为 python 编写相同的代码。另外,如果你使用 python,我建议你使用 skimage 分割,它提供了更多关于 blob 的属性。
    猜你喜欢
    • 2019-11-21
    • 2014-03-15
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2018-04-22
    • 1970-01-01
    • 2016-10-17
    相关资源
    最近更新 更多