python opencv-обнаружение blob или обнаружение круга
у меня возникли проблемы с обнаружением областей круга. Я попробовал это с помощью функции HoughCircles из opencv. Однако, хотя изображения довольно похожи, параметры для funtion должны быть разными, чтобы обнаружить цирли.
другой подход, который я пробовал, состоял в том, чтобы перебирать каждый пиксель и проверять, является ли текущий пиксель белым. Если это так, проверьте, есть ли объект blob в области (расстояние до центра blob меньше порога). Если есть, добавьте пиксель в blob, если нет, то создайте новый blob. Это также не сработало должным образом.
есть ли у кого-нибудь идея, как я могу сделать эту работу (обнаружение 90%)? Я прикрепил изображение и другое изображение, где я отметил кругами. Спасибо!
обновление: Спасибо за помощь до сих пор! Это код, в котором я получаю контуры и фильтрую их по площадь:
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_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)
большое спасибо, ребята! :)
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()