Общий подсчет объектов Python OpenCV

#python #opencv #computer-vision #object-detection #counting

#python #opencv #компьютерное зрение #обнаружение объектов #подсчет

Вопрос:

Я пытаюсь создать общий алгоритм подсчета объектов, используя python и OpenCV (открытый, чтобы попробовать другие методы), однако, похоже, я не могу хорошо рассчитывать различные объекты и не знаю, как приспособиться к этому

https://imgur.com/a/yAkRxWH вот несколько примеров тестовых изображений.

Это для ускорения подсчета запасов небольших объектов.

** РЕДАКТИРОВАТЬ Это мой текущий код (простой детектор больших двоичных объектов)

 # Standard imports
import cv2
import numpy as np;

# Read image
im = cv2.imread("./images/screw_simple.jpg", cv2.IMREAD_GRAYSCALE)
im = cv2.resize(im, (1440, 880))

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 10 #10
params.maxThreshold = 200 #200

# Filter by Area.
params.filterByArea = True # True
params.minArea = 500 #1500

# Filter by Circularity
params.filterByCircularity = True #True
params.minCircularity = 0.1 #0.1

# Filter by Convexity
params.filterByConvexity = True #True
params.minConvexity = 0.0 #0.87

# Filter by Inertia
params.filterByInertia = True #True
params.minInertiaRatio = 0.0 #0.01

# Create a detector with the parameters
ver = (cv2.__version__).split('.')
if int(ver[0]) < 3:
    detector = cv2.SimpleBlobDetector(params)
else:
    detector = cv2.SimpleBlobDetector_create(params)

# Detect blobs.
keypoints = detector.detect(im)

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures
# the size of the circle corresponds to the size of blob
total_count = 0
for i in keypoints:
    total_count = total_count   1


im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show blobs
cv2.imshow("Keypoints", im_with_keypoints)
cv2.waitKey(0)

print(total_count)
  

Вот результаты, которые я получаю: https://imgur.com/a/id6OlIA

Как я могу улучшить этот алгоритм, чтобы получить лучшее обнаружение для общего варианта использования объектов без необходимости изменять параметры каждый раз для каждого объекта?

Комментарии:

1. Покажите ваш код ваш текущий и ожидаемый результат.

Ответ №1:

Вы можете попробовать использовать подход OpenCV, вы могли бы использовать SimpleBlobDetector

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

Это то, что делает детектор (подробнее см. Здесь):

  1. Пороговое значение: преобразование исходных изображений в несколько двоичных изображений путем порогового значения исходного изображения с пороговыми значениями, начинающимися с минимального порога. Эти пороговые значения увеличиваются на thresholdStep until maxThreshold . Итак, первый порог равен minThreshold , второй равен minThreshold thresholdStep , третий равен minThreshold 2 x thresholdStep и так далее.
  2. Группировка: в каждом двоичном изображении соединенные белые пиксели группируются вместе. Давайте назовем эти двоичные двоичные объекты.
  3. Слияние: вычисляются центры двоичных двоичных объектов в двоичных изображениях, и двоичные объекты, расположенные ближе, чем minDistBetweenBlobs объединяются.

  4. Вычисление центра и радиуса: вычисляются и возвращаются центры и радиусы новых объединенных больших двоичных объектов.

Найдите код ниже изображения.

Выходное изображение

 # Standard imports
import cv2
import numpy as np

# Read image
im = cv2.imread("petri.png", cv2.IMREAD_COLOR)

# Setup SimpleBlobDetector parameters.
params = cv2.SimpleBlobDetector_Params()

# Change thresholds
params.minThreshold = 0
params.maxThreshold = 255

# Set edge gradient
params.thresholdStep = 5

# Filter by Area.
params.filterByArea = True
params.minArea = 10

# Set up the detector with default parameters.
detector = cv2.SimpleBlobDetector_create(params)

# Detect blobs.
keypoints = detector.detect(im)

# Draw detected blobs as red circles.
# cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS ensures the size of the circle corresponds to the size of blob
im_with_keypoints = cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255),
                                      cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# Show keypoints
cv2.imshow("Keypoints", im_with_keypoints)
cv2.waitKey(0)
  

Комментарии:

1. Спасибо за рекомендацию — Похоже, я уже использовал тот же алгоритм для обнаружения больших двоичных объектов и надеялся изменить его, чтобы обеспечить более точное обнаружение для широкого набора объектов без индивидуальной настройки каждый раз

2. @Jack смотрите мой второй ответ

Ответ №2:

Для лучшей читаемости я бы предпочел включить это во второй ответ: вы могли бы использовать подход сегментации, например, алгоритм водораздела

Любое изображение в оттенках серого можно рассматривать как топографическую поверхность, где высокая интенсивность обозначает вершины и холмы, а низкая интенсивность обозначает долины. Вы начинаете заполнять все изолированные долины (локальные минимумы) водой разного цвета (метками). По мере подъема воды, в зависимости от пиков (градиентов) поблизости, вода из разных долин, очевидно, разного цвета, начнет сливаться. Чтобы избежать этого, вы строите барьеры в местах, где сливается вода. Вы продолжаете работу по заполнению водой и строительству барьеров, пока все вершины не окажутся под водой. Затем созданные вами барьеры дают вам результат сегментации. Это «философия» водораздела.

Исходное изображение
Сегментированное изображение