Обнаружение и подсчет больших двоичных объектов / связанных объектов с помощью opencv

#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 для этой метки (гистограмма).

любая метка, на которой находится более одного разделенного двоичного объекта, будет тем, что вы ищете.