Обнаружить круги в openCV - PullRequest
       31

Обнаружить круги в openCV

3 голосов
/ 11 марта 2020

У меня проблема с выбором правильных параметров для функции HoughCircles. Я пытаюсь обнаружить круги из видео. Эти круги сделаны мной и имеют почти одинаковое измерение. Проблема в том, что камера в движении.

Когда я меняю maxRadius, он все равно как-то обнаруживает большие круги (см. Рисунок справа). Я также пытался изменить param1, param2, но все равно безуспешно. Left-original picture, Right - after blur and detected circles

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  blurred = cv2.medianBlur(gray, 25)#cv2.bilateralFilter(gray,10,50,50)


  minDist = 100
  param1 = 500
  param2 = 200#smaller value-> more false circles
  minRadius = 5
  maxRadius = 10
  circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, minDist, param1, param2, minRadius, maxRadius)

  if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(blurred,(i[0], i[1]), i[2], (0, 255, 0), 2) 

Может быть, я использую неправильную функцию?

Ответы [ 2 ]

1 голос
/ 12 марта 2020

Вместо необходимости выбирать правильные параметры с помощью cv2.HoughCircles, есть альтернативный подход с использованием контурной фильтрации. Идея состоит в том, чтобы получить двоичное изображение с порогом Оцу , а затем выполнить морфологические операции для выделения эллиптических контуров. Наконец, мы находим контуры и фильтруем, используя формат изображения и область контура . Вот результаты:

enter image description here

import cv2
import numpy as np

# Load image, grayscale, median blur, Otsus threshold
image = cv2.imread('1.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.medianBlur(gray, 11)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

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

# Find contours and filter using contour area and aspect ratio
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:
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.04 * peri, True)
    area = cv2.contourArea(c)
    if len(approx) > 5 and area > 1000 and area < 500000:
        ((x, y), r) = cv2.minEnclosingCircle(c)
        cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('opening', opening)
cv2.imshow('image', image)
cv2.waitKey()     
0 голосов
/ 12 марта 2020

Основная проблема в вашем коде - это 5-й аргумент функции HoughCircles.

Согласно документации список аргументов:

cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles

Это означает, что 5-й аргумент применяется circles (он дает возможность получить вывод по ссылке, вместо использования возвращаемого значения).

Поскольку вы не передаете аргумент circles, вы должны передать именованные аргументы для всех аргументов после 4-го аргумента (например, param1=param1, param2=param2 ....).

Параметр проблемы с настройкой:

  • Уменьшите значение param1. param1 - это более высокий порог, передаваемый Canny.
    В вашем случае значение должно быть около 30.
  • Уменьшите значение param2 Документация не очень понятна, но установка значения около 50 работает.
  • Увеличение значения maxRadius - радиус 10 намного меньше радиуса ваших кругов.

Вот код:

import numpy as np
import cv2

img = cv2.imread('circles.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

blurred = cv2.medianBlur(gray, 25) #cv2.bilateralFilter(gray,10,50,50)

minDist = 100
param1 = 30 #500
param2 = 50 #200 #smaller value-> more false circles
minRadius = 5
maxRadius = 100 #10

# docstring of HoughCircles: HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)

# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат:

enter image description here

...