python opencv-обнаружение blob или обнаружение круга

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

другой подход, который я пробовал, состоял в том, чтобы перебирать каждый пиксель и проверять, является ли текущий пиксель белым. Если это так, проверьте, есть ли объект blob в области (расстояние до центра blob меньше порога). Если есть, добавьте пиксель в blob, если нет, то создайте новый blob. Это также не сработало должным образом.

есть ли у кого-нибудь идея, как я могу сделать эту работу (обнаружение 90%)? Я прикрепил изображение и другое изображение, где я отметил кругами. Спасибо!

example

example with arrows

обновление: Спасибо за помощь до сих пор! Это код, в котором я получаю контуры и фильтрую их по площадь:

im = cv2.imread('extract_blue.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
im_gauss = cv2.GaussianBlur(imgray, (5, 5), 0)
ret, thresh = cv2.threshold(im_gauss, 127, 255, 0)
# get contours
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

contours_area = []
# calculate area and filter into new array
for con in contours:
    area = cv2.contourArea(con)
    if 1000 < area < 10000:
        contours_area.append(con)

это работает очень аккуратно. Я нарисовал их на изображении.: contours_filtered_area

это часть, где я фильтровал по круговому, он идет прямо под кодом, где я фильтрую по области:

contours_cirles = []

# check if contour is of circular shape
for con in contours_area:
    perimeter = cv2.arcLength(con, True)
    area = cv2.contourArea(con)
    if perimeter == 0:
        break
    circularity = 4*math.pi*(area/perimeter*perimeter)
    print circularity
    if 0.8 < circularity < 1.2:
        contours_cirles.append(con)

однако новый список "contours_cirles" пуст. Я напечатал "circularity" в цикле, и все значения находятся между 10 000 и 100 000.

обновление #2: После исправления отсутствующих скобок он работает сейчас же!

contours_cirles = []

# check if contour is of circular shape
for con in contours_area:
    perimeter = cv2.arcLength(con, True)
    area = cv2.contourArea(con)
    if perimeter == 0:
        break
    circularity = 4*math.pi*(area/(perimeter*perimeter))
    print circularity
    if 0.7 < circularity < 1.2:
        contours_cirles.append(con)

большое спасибо, ребята! :)

example_done

2 ответов


в качестве отправной точки вы можете начать с:

  • найти все контуры в данном изображении с помощью cv2.findContours()
  • перебрать каждый контур:
    • вычислить площадь, если площадь контура в заданном диапазоне скажем 70 < area < 150. Это отфильтрует некоторые очень маленькие и большие контуры.
    • после фильтрации контуров с порогом площади необходимо проверить количество ребер контура, что можно сделать с помощью: cv2.approxPolyDP(), для круга len (приблизительно) должен быть > 8, но

вы должны попытаться реализовать этот подход и обновить вопрос с кодом, который вы будете писать в дальнейшем.

EDIT: Как предложил @Miki, есть лучший и более чистый способ обнаружения, если геометрическая форма имеет круглую форму с использованием circularity = 4pi (площадь/периметр^2), и решите порог, такой как 0.9, чтобы проверить, является ли форма круглой. Для идеального круга circularity == 1. Вы можете настроить этот порог в соответствии с вашими потребностями.

вы можете ознакомиться arcLength найти периметр контура и contourArea чтобы получить площадь контура, которые необходимы для расчета округлости.


мы могли бы попробовать Hough Transformation слишком, чтобы обнаружить круги на изображении и играть с порогами, чтобы получить желаемый результат (обнаруженные круги в зеленых пограничных линиях с красными точками в качестве центров):

import cv2
import numpy as np

img = cv2.imread('rbv2g.jpg',0)
img = cv2.medianBlur(img,5)
cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)

circles = cv2.HoughCircles(img,cv2.HOUGH_GRADIENT,1,10,
                            param1=50,param2=12,minRadius=0,maxRadius=20)

circles = np.uint16(np.around(circles))
for i in circles[0,:]:
    # draw the outer circle
    cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
    # draw the center of the circle
    cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)

cv2.imshow('detected circles',cimg)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here