Как нарисовать контуры вокруг круглого объекта и найти его ROI, используя OpenCV Python? - PullRequest
0 голосов
/ 07 января 2020

Я пытался нарисовать контур поверх круглого объекта, присутствующего на изображении, и найти его площадь и центроид. Но я не смог этого сделать, потому что контур был нарисован по всему изображению, как показано на рисунке. Я хочу нарисовать контур только над круглым белым объектом, как показано на рисунке.

enter image description here

Ожидаемый результат:

Я хочу нарисовать круговой контур только над этим белым объектом, показанным на изображении, и показать его центроид и площадь. 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()

Любая помощь будет принята с благодарностью. Заранее спасибо.

1 Ответ

0 голосов
/ 08 января 2020

Это можно сделать разными способами в зависимости от необходимости. Одним простым способом может быть:

Во-первых, отфильтруйте ROI. Итак, мы знаем 3 вещи, 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) и c.


Так в приведенном ниже коде, сначала мы отфильтровываем область интереса по белому цвету, а затем по форме и площади этих белых контуров.

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:. Настройте эту строку в соответствии с вашим сценарием и скажите, решит ли она вашу проблему. Если этого не произойдет, мы можем обсудить более приятные способы или поиграть с этим, чтобы сделать его более точным.

...