#python #opencv
#python #opencv
Вопрос:
Я хочу обнаруживать и подсчитывать объекты внутри изображения, которые касаются, игнорируя при этом то, что можно рассматривать как единый объект. У меня есть базовое изображение, на котором я попытался применить cv2.HoughCircles()
метод, чтобы попытаться идентифицировать некоторые круги. Затем я проанализировал возвращенный массив и попытался использовать cv2.circle()
их для рисования на изображении.
Тем не менее, я, кажется, всегда получаю слишком много возвращаемых кругов cv2.HoughCircles()
и не могу понять, как считать только те объекты, которые соприкасаются.
Это образ, над которым я работал
Мой код до сих пор:
import numpy
import matplotlib.pyplot as pyp
import cv2
segmentet = cv2.imread('photo')
houghCircles = cv2.HoughCircles(segmented, cv2.HOUGH_GRADIENT, 1, 80, param1=450, param2=10, minRadius=30, maxRadius=200)
houghArray = numpy.uint16(houghCircles)[0,:]
for circle in houghArray:
cv2.circle(segmented, (circle[0], circle[1]), circle[2], (0, 250, 0), 3)
И это изображение, которое я получаю, что довольно далеко от того, что я действительно хочу.
Как я могу правильно идентифицировать и подсчитывать указанные объекты?
Комментарии:
1. Это может помочь.
2. @стакан, если я правильно понимаю, в этом примере будут найдены объекты, которые соприкасаются, и разделены на отдельные круги. Что я хочу, так это найти объекты, которые соприкасаются, и пометить / посчитать их, игнорируя те, которые являются отдельными.
3. Найдите все контуры для всех областей. Затем проверьте отношение площади контура к площади выпуклой оболочки. Если коэффициент близок к 1, то это один объект. Если слишком сильно ниже, то это множественные касания объектов. Видишь docs.opencv.org/4.1.1/d3/dc0 /…
Ответ №1:
Вот один из способов в Python OpenCV путем получения областей контуров и области выпуклой оболочки контуров. Возьмите соотношение (area/ convex_hull_area). Если он достаточно мал, то это скопление больших двоичных объектов. В противном случае это изолированный сгусток.
Входные данные:
import cv2
import numpy as np
# read input image
img = cv2.imread('blobs_connected.jpg')
# convert to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold to binary
thresh = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY)[1]
# find contours
#label_img = img.copy()
contour_img = img.copy()
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
index = 1
isolated_count = 0
cluster_count = 0
for cntr in contours:
area = cv2.contourArea(cntr)
convex_hull = cv2.convexHull(cntr)
convex_hull_area = cv2.contourArea(convex_hull)
ratio = area / convex_hull_area
#print(index, area, convex_hull_area, ratio)
#x,y,w,h = cv2.boundingRect(cntr)
#cv2.putText(label_img, str(index), (x,y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (0,0,255), 2)
if ratio < 0.91:
# cluster contours in red
cv2.drawContours(contour_img, [cntr], 0, (0,0,255), 2)
cluster_count = cluster_count 1
else:
# isolated contours in green
cv2.drawContours(contour_img, [cntr], 0, (0,255,0), 2)
isolated_count = isolated_count 1
index = index 1
print('number_clusters:',cluster_count)
print('number_isolated:',isolated_count)
# save result
cv2.imwrite("blobs_connected_result.jpg", contour_img)
# show images
cv2.imshow("thresh", thresh)
#cv2.imshow("label_img", label_img)
cv2.imshow("contour_img", contour_img)
cv2.waitKey(0)
Скопления красного цвета, изолированные капли зеленого цвета:
Текстовая информация:
number_clusters: 4
number_isolated: 81
Комментарии:
1. Большое спасибо! Работает отлично
Ответ №2:
подходите к этому поэтапно.
маркируйте связанные компоненты. два подключенных больших двоичных объекта получают одну и ту же метку, потому что они подключены. пока все идет хорошо.
теперь разделите свои двоичные объекты. используйте watershed (первый комментарий) или любой другой метод, который дает вам результаты. Я не могу полностью предсказать подход водораздела. это может иметь дело с прикосновением к каплям разного размера или может сделать что-то глупое. образец / учебник также предполагает минимальный размер (0,7 * максимальный пик); возможно, подключите что-то абсолютное в пикселях.
затем для каждого разделенного большого двоичного объекта проверьте, на какой метке он находится (для надежности возьмите координаты центра тяжести), и запишите 1 для этой метки (гистограмма).
любая метка, на которой находится более одного разделенного двоичного объекта, будет тем, что вы ищете.