Компьютерное зрение: Opencv Подсчет маленьких кругов внутри большого круга

Вот изображение, над которым я работал введите здесь описание изображения

Цель состоит в том, чтобы обнаружить маленькие круги внутри большого.

в настоящее время я преобразовал изображение в оттенки серого и применил порог (cv2.THRESH_OTSU), в результате чего получилось это изображение введите здесь описание изображения

После этого я отфильтровал большие объекты, используя findcontours, применил Morph open с использованием ядра эллиптической формы, которое я нашел в stackoverflow.

Полученное изображение выглядит следующим образом: введите здесь описание изображения

Может ли кто-нибудь указать мне правильный путь, что делать и где я ошибаюсь.

Ниже прикреплен код, над которым я работаю

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold
image = cv2.imread('01.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
#cv2.imwrite('thresh.jpg', thresh)

# Filter out large non-connecting objects
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    #print(area)
    if area < 200 and area > 0:
        cv2.drawContours(thresh,[c],0,0,-1)

# Morph open using elliptical shaped kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

# Find circles 
cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 20 and area < 50:
        ((x, y), r) = cv2.minEnclosingCircle(c)
        cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)

cv2.namedWindow('orig', cv2.WINDOW_NORMAL)
cv2.imshow('orig', thresh)
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', image)
cv2.waitKey()

Благодарю вас!


person harsha    schedule 08.07.2020    source источник
comment
Идея, которая может быть полезной, если вы получите контур самого большого круга, то все контуры внутри него будут для меньших кругов, которые вы хотите. Итак, попробуйте определить самый большой круг.   -  person dewDevil    schedule 08.07.2020
comment
Я думаю, что вы можете пожертвовать несколькими точками против большого круга. Тогда фильтровать капли по размеру несложно.   -  person Yves Daoust    schedule 05.09.2020


Ответы (3)


Вы выбрасываете много полезной информации, преобразовывая свое изображение в оттенки серого.

Почему бы не использовать тот факт, что пятна, которые вы ищете, являются единственными красными/оранжевыми?

Я умножил канал насыщения на красный канал, что дало мне это изображение:

введите здесь описание изображения

Теперь поиск белых пятен становится тривиальным.

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

person Piglet    schedule 08.07.2020
comment
Извините, но я не вижу, какая информация теряется. Изображение имеет по существу два цвета и даже близко к бинарному. - person Yves Daoust; 05.09.2020

Основная проблема в вашем коде - это флаг, который вы используете в функции cv2.findContours().

Для такой задачи, в которой мы должны найти контуры, которые могут появиться внутри другого контура (большого круга), мы не должны использовать флаг cv2.RETR_EXTERNAL, вместо этого используйте cv2.RETR_TREE. Нажмите здесь, чтобы получить подробную информацию..

Кроме того, всегда лучше использовать cv2.CHAIN_APPROX_NONE вместо cv2.CHAIN_APPROX_SIMPLE, если память не является проблемой. Нажмите здесь, чтобы получить подробную информацию.

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

import cv2
import numpy as np

Image = cv2.imread("Adg5.jpg")
GrayImage = cv2.cvtColor(Image, cv2.COLOR_BGR2GRAY)

# Applying Otsu's Thresholding
Retval, ThreshImage = cv2.threshold(GrayImage, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)

# Finding Contours in the image
Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# Taking only those contours which have no child contour.
FinalContours = [Contours[i] for i in range(len(Contours)) if Hierarchy[0][i][2] == -1]

# Drawing contours
Image = cv2.drawContours(Image, FinalContours, -1, (0, 255, 0), 1)

cv2.imshow("Contours", Image)
cv2.waitKey(0)

Результирующее изображение В этом методе много шума в граница тоже приближается, но обнаруживаются и нужные оранжевые точки. Теперь задача убрать граничный шум.

Другой метод, который в значительной степени удаляет граничный шум, похож на подход @Piglet. Здесь я использую изображение HSV для сегментации оранжевых точек, а затем обнаруживаю их, используя описанный выше подход.

import cv2
import numpy as np

Image = cv2.imread("Adg5.jpg")
HSV_Image = cv2.cvtColor(Image, cv2.COLOR_BGR2HSV)

# Extracting orange colour using HSV Image.
ThreshImage = cv2.inRange(HSV_Image, np.array([0, 81, 0]), np.array([41, 255, 255]))

# Finding Contours
Contours, Hierarchy = cv2.findContours(ThreshImage, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# Taking only those contours which have no child contour.
FinalContours = [Contours[i] for i in range(len(Contours)) if Hierarchy[0][i][2] == -1]

# Drawing Contours
Image = cv2.drawContours(Image, FinalContours, -1, (0, 255, 0), 1)

cv2.imshow("Contours", Image)
cv2.waitKey(0)

Результирующее изображение

person Rahul Kedia    schedule 08.07.2020

У меня есть идея, что детет маленькие круги сдвигая окно. когда площадь малого цикла занимала площадь скользящего окна больше 90% (вписанный круг и квадрат) и менее 100% (избегая движения скользящего окна в большем цикле). эта позиция представляет собой маленький круг. самый большой размер раздвижных окон - это самый большой размер маленького цикла. Надеюсь на помощь.

кроме того, к результату Пятачка примените k-средних, где k = 2, вы можете получить бинарное изображение, а затем использовать findcontours для подсчета маленьких кругов.

person Russell-aka    schedule 08.07.2020