首页 > 解决方案 > 如何在圆形对象周围绘制轮廓并使用 OpenCV Python 找到它的 ROI?

问题描述

我试图在图像中存在的圆形对象上绘制轮廓并找到它的面积和质心。但我没能做到,因为轮廓被绘制在整个图像上,如图所示。我只想在圆形白色物体上绘制轮廓,如图所示。

在此处输入图像描述

预期结果:

我只想在图像中显示的这个白色对象上绘制圆形轮廓并显示其质心和面积。OpenCV,忽略其余部分。

下面是附上的代码。

代码:

import cv2
import numpy as np
import imutils

cap = cv2.VideoCapture(0)

cap.set(3,640)
cap.set(4,480)

while True:
    _,frame = cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower_blue = np.array([90,60,0])
    upper_blue = np.array([121,255,255])

    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    cnts = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts= imutils.grab_contours(cnts)

    for c in cnts:
        area = cv2.contourArea(c)
        if area > 1500:
            cv2.drawContours(frame, [c], -1, (0,255,0), 3)
            M = cv2.moments(c)
            cx = int(M["m10"] / M["m00"])
            cy = int(M["m01"] / M["m00"])

            cv2.circle(frame, (cx, cy), 7, (255, 255, 255), -1)
            cv2.putText(frame, "Centre", (cx - 20, cy - 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)

            cv2.imshow("frame", frame)


            print("area is ...", area)
            print("centroid is at ...", cx, cy)

    k=cv2.waitKey(1000)
    if k ==27:
        break
cap.release()
cv2.destroyAllWindows()

任何帮助,将不胜感激。提前致谢。

标签: pythonopencvvideo-capture

解决方案


这可以根据需要以多种方式完成。一种简单的方法可以是:

首先,过滤ROI。所以我们知道三件事,ROI 是白色的,是一个圆圈,我们知道它的大约面积。

对于白色:

def detect_white(img):
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    _, thresh = cv2.threshold(gray, 220, 255, cv2.THRESH_BINARY)
    return thresh

尽管您需要根据需要使用白色检测算法。白色检测的一些好方法是使用阈值(如上),使用 HSL 颜色空间,因为白度密切依赖于亮度(cv2.cvtColor(img, cv2.COLOR_BGR2HLS)等。


所以在下面的代码中,我们首先通过白色过滤掉 ROI,然后通过这些白色轮廓的形状和面积。

image = cv2.imread("path/to/your/image")

white_only = detect_white(image)

contours, hierarchy = cv2.findContours(white_only, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

circles = []

for contour in contours:
    epsilon = 0.01 * cv2.arcLength(contour, True)
    approx = cv2.approxPolyDP(contour, epsilon, True)
    area = cv2.contourArea(contour)
    if len(approx) > 12 and area > 1000 and area < 3000:
        circles.append(contour)

# Now the list circles would have all such
# contours satisfying the above conditions
# If len(circles) != 1 or isn't the circle you
# desire, more filtering is required

cv2.drawContours(image, circles, -1, (0, 255, 0), 3)

选择轮廓取决于面积和顶点(由 返回cv2. approxPolyDP())。

如您的图像所示,白色大圆圈的面积很大,并且非常接近一个圆圈,我检查了它,例如:len(approx) > 12 and area > 1000 and area < 3000:。根据您的情况调整此行并告诉我它是否解决了您的问题。如果没有,我们可以讨论一些更好的方法或使用这个方法来使其更准确。


推荐阅读