Подтвердить что ты не робот

Запись надежного (определение цвета и размера) обнаружения круга с помощью opencv (на основе преобразования Hough или других функций)

Я написал следующий очень простой код python, чтобы найти круги в изображении:

import cv
import numpy as np

WAITKEY_DELAY_MS = 10
STOP_KEY = 'q'

cv.NamedWindow("image - press 'q' to quit", cv.CV_WINDOW_AUTOSIZE);
cv.NamedWindow("post-process", cv.CV_WINDOW_AUTOSIZE);

key_pressed = False
while key_pressed != STOP_KEY:

    # grab image
    orig = cv.LoadImage('circles3.jpg')

    # create tmp images
    grey_scale = cv.CreateImage(cv.GetSize(orig), 8, 1)
    processed = cv.CreateImage(cv.GetSize(orig), 8, 1)


    cv.Smooth(orig, orig, cv.CV_GAUSSIAN, 3, 3)

    cv.CvtColor(orig, grey_scale, cv.CV_RGB2GRAY)

    # do some processing on the grey scale image
    cv.Erode(grey_scale, processed, None, 10)
    cv.Dilate(processed, processed, None, 10)
    cv.Canny(processed, processed, 5, 70, 3)
    cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15)

    storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

    # these parameters need to be adjusted for every single image
    HIGH = 50
    LOW = 140

    try: 
        # extract circles
        cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, HIGH, LOW)

        for i in range(0, len(np.asarray(storage))):
            print "circle #%d" %i
            Radius = int(np.asarray(storage)[i][0][2])
            x = int(np.asarray(storage)[i][0][0])
            y = int(np.asarray(storage)[i][0][1])
            center = (x, y)

            # green dot on center and red circle around
            cv.Circle(orig, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
            cv.Circle(orig, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

            cv.Circle(processed, center, 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
            cv.Circle(processed, center, Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

    except:
        print "nothing found"
        pass

    # show images
    cv.ShowImage("image - press 'q' to quit", orig)
    cv.ShowImage("post-process", processed)

    cv_key = cv.WaitKey(WAITKEY_DELAY_MS)
    key_pressed = chr(cv_key & 255)

Как видно из следующих двух примеров, "качество поиска круга" варьируется довольно много:

case1:

input1detection1post-processed1

Случай 2:

input2detection2post-processed2

Case1 и Case2 - это в основном одно и то же изображение, но алгоритм обнаруживает разные круги. Если я представляю алгоритму изображение с кругами разного размера, обнаружение круга может даже полностью потерпеть неудачу. Это в основном связано с параметрами HIGH и LOW, которые необходимо настраивать индивидуально для каждого нового изображения.

Поэтому мой вопрос: каковы различные возможности сделать этот алгоритм более надежным? Он должен быть изменен по размеру и цвету, чтобы были обнаружены разные круги с разными цветами и разными размерами. Может быть, использование преобразования Хью не лучший способ сделать что-то? Есть ли более эффективные подходы?

4b9b3361

Ответ 1

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

Быстрый результат

Некоторые образцы изображений (все изображения, кроме ваших, загружаются с flickr.com и лицензируются CC) с обнаруженными кругами (без изменения/настройки любых параметров, точно следующий код используется для извлечения кругов во всех изображениях ): detected blobs in the sample image 1detected blobs in the sample image 2lots of circlesblobs in the flickr image 1

Код (основанный на детекторе MSB Blob)

И вот код:

import cv2
import math
import numpy as np

d_red = cv2.cv.RGB(150, 55, 65)
l_red = cv2.cv.RGB(250, 200, 200)

orig = cv2.imread("c.jpg")
img = orig.copy()
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

detector = cv2.FeatureDetector_create('MSER')
fs = detector.detect(img2)
fs.sort(key = lambda x: -x.size)

def supress(x):
        for f in fs:
                distx = f.pt[0] - x.pt[0]
                disty = f.pt[1] - x.pt[1]
                dist = math.sqrt(distx*distx + disty*disty)
                if (f.size > x.size) and (dist<f.size/2):
                        return True

sfs = [x for x in fs if not supress(x)]

for f in sfs:
        cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), d_red, 2, cv2.CV_AA)
        cv2.circle(img, (int(f.pt[0]), int(f.pt[1])), int(f.size/2), l_red, 1, cv2.CV_AA)

h, w = orig.shape[:2]
vis = np.zeros((h, w*2+5), np.uint8)
vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR)
vis[:h, :w] = orig
vis[:h, w+5:w*2+5] = img

cv2.imshow("image", vis)
cv2.imwrite("c_o.jpg", vis)
cv2.waitKey()
cv2.destroyAllWindows()

Как вы можете видеть, это основан на детекторе bla MSER. Код не препроцирует изображение отдельно от простого сопоставления в оттенки серого. Таким образом, не хватает этих слабых желтых капель в ваших изображениях.

Теория

Вкратце: вы не говорите нам, что знаете о проблеме, кроме того, что даете только два образца изображения без описания их. Здесь я объясняю, почему, по моему скромному мнению, важно иметь больше информации о проблеме, прежде чем спрашивать, какие эффективные методы атаковать проблему.

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

P = {p1, ..., pn} 
P: search space
p1...pn: pixels

Чтобы решить эту проблему поиска, необходимо определить две другие функции:

E(P) : enumerates the search space
V(p) : checks whether the item/pixel has the desirable properties, the items passing the check are added to the output list

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

Мы приближаемся к основному вопросу. Как мы могли бы определить V, а точнее, какие свойства кандидатов должны быть мерами и как решить проблему дихотомии, расщепляя их на желательные и нежелательные. Наиболее распространенный подход - найти некоторые свойства, которые могут быть использованы для определения простых правил принятия решений, основанных на измерении свойств. Это то, что вы делаете с помощью проб и ошибок. Вы программируете классификатор, изучая положительные и отрицательные примеры. Это связано с тем, что методы, которые вы используете, не имеют представления о том, что вы хотите сделать. Вы должны настроить/настроить параметры правила принятия решений и/или препроцитировать данные таким образом, чтобы изменение свойств (желательных кандидатов), используемых методом для проблемы дихотомии, было уменьшено. Вы можете использовать алгоритм машинного обучения, чтобы найти оптимальные значения параметров для данного набора примеров. Для решения этой проблемы существует целый ряд алгоритмов обучения от деревьев решений до генетического программирования. Вы также можете использовать алгоритм обучения, чтобы найти оптимальные значения параметров для нескольких алгоритмов обнаружения круга и посмотреть, какая из них дает лучшую точность. Это берет на себя основную нагрузку на алгоритм обучения, который вам нужен только для сбора образцов изображений.

Другим подходом к повышению надежности, который часто упускается из виду, является использование дополнительной доступной информации. Если вы знаете цвет кругов с практически нулевыми дополнительными усилиями, вы можете значительно улучшить точность детекторов. Если вы знали положение кругов на плоскости и хотели обнаружить отображаемые круги, вы должны помнить, что преобразование между этими двумя наборами позиций описывается двумерной гомографией. А гомографию можно оценить, используя только четыре очка. Тогда вы можете улучшить устойчивость, чтобы иметь твердотельный метод. Значимость знаний, специфичных для домена, часто недооценивается. Посмотрите на это так, в первом подходе мы попытаемся приблизиться к некоторым правилам принятия решений, основанным на ограниченном числе образцов. Во втором подходе мы знаем правила принятия решений и должны только найти способ эффективно использовать их в алгоритме.

Резюме

Подводя итог, есть два подхода к повышению точности/надежности решения:

  • Инструмент на основе: поиск более простого в использовании алгоритма/с меньшим количеством параметров/настройка алгоритма/автоматизация этого процесса с использованием алгоритмов машинного обучения
  • Информационно-ориентированная: используете ли вы всю доступную информацию? В вопросе вы не упоминаете, что знаете о проблеме.

Для этих двух изображений, которыми вы поделились, я бы использовал детектор blob, а не метод HT. Для вычитания фона я бы предложил попытаться оценить цвет фона, так как в двух изображениях он не меняется, а цвет кругов меняется. И большая часть области голая.

Ответ 2

Это отличная проблема моделирования. У меня есть следующие рекомендации/идеи:

  • Затем разделить изображение на RGB.
  • предварительной обработки.
  • Поиск динамических параметров.
  • Добавить ограничения.
  • Убедитесь в том, что вы пытаетесь обнаружить.

Подробнее:

1: Как отмечено в других ответах, преобразование прямо в оттенки серого отбрасывает слишком много информации - любые круги со сходной яркостью на фоне будут потеряны. Гораздо лучше рассмотреть цветные каналы либо изолированно, либо в другом цветовом пространстве. Здесь можно найти два способа: выполнить HoughCircles на каждом предварительно обработанном канале изолированно, затем объединить результаты или обработать каналы, затем объединить их, а затем управлять HoughCircles. В моей попытке ниже я попробовал второй метод, разделив каналы RGB, обработать, а затем объединить. Будьте осторожны при насыщении изображения при объединении, я использую cv.And, чтобы избежать этой проблемы (на этом этапе мои круги всегда черные кольца/диски на белом фоне).

2: Предварительная обработка довольно сложная, и с ней часто лучше всего играть. Я использовал AdaptiveThreshold, который является действительно мощным методом свертки, который может усилить ребра в изображении с помощью пороговых пикселей на основе их локального среднего (аналогичные процессы также происходят в раннем пути визуальной системы млекопитающих). Это также полезно, так как это снижает уровень шума. Я использовал dilate/erode только за один проход. И я сохранил другие параметры, как у вас были. Кажется, что использовать Canny до HoughCircles очень помогает в поиске "заполненных кругов", поэтому, вероятно, лучше всего его удержать. Эта предварительная обработка довольно тяжелая и может привести к ложным срабатываниям с несколько более "блуждающими кругами", но в нашем случае это, возможно, желательно?

3: Как вы отметили, параметр HoughCircles param2 (ваш параметр LOW) необходимо настроить для каждого изображения, чтобы получить оптимальное решение, фактически из документы:

Чем меньше это, тем более ложные круги могут быть обнаружены.

Проблема в том, что сладкое пятно будет отличаться для каждого изображения. Я думаю, что лучший подход здесь состоит в том, чтобы установить условие и выполнить поиск с помощью различных значений param2 до тех пор, пока это условие не будет выполнено. На ваших изображениях отображаются неперекрывающиеся круги, а когда param2 слишком мало, мы обычно получаем множество перекрывающихся кругов. Поэтому я предлагаю выполнить поиск:

максимальное количество неперекрывающихся и не содержащих замкнутых окружностей

Поэтому мы продолжаем вызывать HoughCircles с разными значениями param2, пока это не будет выполнено. Я делаю это в моем примере ниже, просто увеличивая param2, пока не достигнет порогового допущения. Было бы намного быстрее (и довольно легко сделать), если вы выполняете двоичный поиск, чтобы найти, когда это выполняется, но вам нужно быть осторожным с обработкой исключений, поскольку opencv часто выдает ошибки для невинных значений param2 (at по крайней мере, на моей установке). Другое условие, с которым нам было бы очень полезно сопоставлять, было бы количество кругов.

4: Есть ли еще какие-то ограничения, которые мы можем добавить к модели? Чем больше материала мы можем рассказать нашей модели, тем легче сделать задачу обнаружить круги. Например, знаем ли мы:

  • Число кругов. - даже верхняя или нижняя граница полезна.
  • Возможные цвета кругов, фона или "не кругов".
  • Их размеры.
  • Где они могут быть на изображении.

5: Некоторые из блоков в ваших изображениях можно было только назвать кругами! Рассмотрим два "некруглых капли" на втором изображении, мой код не может их найти (хорошо!), Но... если я их "photoshop", чтобы они были более круговыми, мой код может их найти... Возможно, если вы хотите обнаружить вещи, которые не являются кругами, может быть лучше другой подход, например Tim Lukins.

Проблемы

Выполняя тяжелую предварительную обработку AdaptiveThresholding и `Canny ', может быть много искажений в свойствах изображения, что может привести к обнаружению ложных кругов или неправильной отчетности. Например, большой твердый диск после обработки может появиться кольцо, поэтому HughesCircles могут найти внутреннее кольцо. Кроме того, даже документы отмечают, что:

... обычно функция хорошо определяет центры кругов, однако может не найти правильных радиусов.

Если вам требуется более точное обнаружение радиусов, я предлагаю следующий подход (не реализован):

  • На исходном изображении, луч-след от центра окружности, в расширяющемся кресте (4 луча: вверх/вниз/влево/вправо)
  • Сделайте это отдельно в каждом канале RGB
  • Объедините эту информацию для каждого канала для каждого луча разумным способом (т.е. флип, смещение, масштаб и т.д. по мере необходимости).
  • возьмите среднее значение для первых нескольких пикселей на каждом луче, используйте это, чтобы определить, где происходит значительное отклонение луча.
  • Эти 4 точки - это оценки точек на окружности.
  • Используйте эти четыре оценки, чтобы определить более точный радиус и центральное положение (!).
  • Это может быть обобщено с помощью расширяющегося кольца вместо четырех лучей.

Результаты

Код в конце довольно неплохое время, эти примеры были сделаны с кодом, как показано:

Обнаруживает все круги в вашем первом изображении: enter image description here

Как выглядит предварительно обработанное изображение перед тем, как применить фильтр canny (видимы различные цветовые круги): enter image description here

Обнаруживает все, кроме двух (капли) во втором изображении: enter image description here

Изменено второе изображение (капли круглые, а большие овалы сделаны более круговыми, что улучшает обнаружение), все обнаруженные: enter image description here

Хорошо справляется с обнаружением центров в этой картине Кандинского (я не могу найти концентрические кольца из-за граничного условия). enter image description here

код:

import cv
import numpy as np

output = cv.LoadImage('case1.jpg')
orig = cv.LoadImage('case1.jpg')

# create tmp images
rrr=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
ggg=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
bbb=cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
processed = cv.CreateImage((orig.width,orig.height), cv.IPL_DEPTH_8U, 1)
storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)

def channel_processing(channel):
    pass
    cv.AdaptiveThreshold(channel, channel, 255, adaptive_method=cv.CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=cv.CV_THRESH_BINARY, blockSize=55, param1=7)
    #mop up the dirt
    cv.Dilate(channel, channel, None, 1)
    cv.Erode(channel, channel, None, 1)

def inter_centre_distance(x1,y1,x2,y2):
    return ((x1-x2)**2 + (y1-y2)**2)**0.5

def colliding_circles(circles):
    for index1, circle1 in enumerate(circles):
        for circle2 in circles[index1+1:]:
            x1, y1, Radius1 = circle1[0]
            x2, y2, Radius2 = circle2[0]
            #collision or containment:
            if inter_centre_distance(x1,y1,x2,y2) < Radius1 + Radius2:
                return True

def find_circles(processed, storage, LOW):
    try:
        cv.HoughCircles(processed, storage, cv.CV_HOUGH_GRADIENT, 2, 32.0, 30, LOW)#, 0, 100) great to add circle constraint sizes.
    except:
        LOW += 1
        print 'try'
        find_circles(processed, storage, LOW)
    circles = np.asarray(storage)
    print 'number of circles:', len(circles)
    if colliding_circles(circles):
        LOW += 1
        storage = find_circles(processed, storage, LOW)
    print 'c', LOW
    return storage

def draw_circles(storage, output):
    circles = np.asarray(storage)
    print len(circles), 'circles found'
    for circle in circles:
        Radius, x, y = int(circle[0][2]), int(circle[0][0]), int(circle[0][1])
        cv.Circle(output, (x, y), 1, cv.CV_RGB(0, 255, 0), -1, 8, 0)
        cv.Circle(output, (x, y), Radius, cv.CV_RGB(255, 0, 0), 3, 8, 0)

#split image into RGB components
cv.Split(orig,rrr,ggg,bbb,None)
#process each component
channel_processing(rrr)
channel_processing(ggg)
channel_processing(bbb)
#combine images using logical 'And' to avoid saturation
cv.And(rrr, ggg, rrr)
cv.And(rrr, bbb, processed)
cv.ShowImage('before canny', processed)
# cv.SaveImage('case3_processed.jpg',processed)
#use canny, as HoughCircles seems to prefer ring like circles to filled ones.
cv.Canny(processed, processed, 5, 70, 3)
#smooth to reduce noise a bit more
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 7, 7)
cv.ShowImage('processed', processed)
#find circles, with parameter search
storage = find_circles(processed, storage, 100)
draw_circles(storage, output)
# show images
cv.ShowImage("original with circles", output)
cv.SaveImage('case1.jpg',output)

cv.WaitKey(0)

Ответ 3

А, да... старые инварианты цвета/размера для проблемы кругов (AKA преобразование Хафа слишком специфично и не устойчиво)...

В прошлом я больше полагался на структурный и формальный анализ функций OpenCV. Вы можете получить очень хорошее представление о папке "samples" того, что возможно - особенно fitellipse.py и squares.py.

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

enter image description here

Это еще не все:

  • На этапах предварительной обработки требуется немного корректировки для обнаружения более слабых кругов.
  • Вы можете проверить контур далее, чтобы определить, является ли он кругом или нет...

Удачи!

import cv
import numpy as np

# grab image
orig = cv.LoadImage('circles3.jpg')

# create tmp images
grey_scale = cv.CreateImage(cv.GetSize(orig), 8, 1)
processed = cv.CreateImage(cv.GetSize(orig), 8, 1)

cv.Smooth(orig, orig, cv.CV_GAUSSIAN, 3, 3)

cv.CvtColor(orig, grey_scale, cv.CV_RGB2GRAY)

# do some processing on the grey scale image
cv.Erode(grey_scale, processed, None, 10)
cv.Dilate(processed, processed, None, 10)
cv.Canny(processed, processed, 5, 70, 3)
cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15)

#storage = cv.CreateMat(orig.width, 1, cv.CV_32FC3)
storage = cv.CreateMemStorage(0)

contours = cv.FindContours(processed, storage, cv.CV_RETR_EXTERNAL)
# N.B. 'processed' image is modified by this!

#contours = cv.ApproxPoly (contours, storage, cv.CV_POLY_APPROX_DP, 3, 1) 
# If you wanted to reduce the number of points...

cv.DrawContours (orig, contours, cv.RGB(0,255,0), cv.RGB(255,0,0), 2, 3, cv.CV_AA, (0, 0)) 

def contour_iterator(contour):
  while contour:
    yield contour
    contour = contour.h_next()

for c in contour_iterator(contours):
  # Number of points must be more than or equal to 6 for cv.FitEllipse2
  if len(c) >= 6:
    # Copy the contour into an array of (x,y)s
    PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2)

    for (i, (x, y)) in enumerate(c):
      PointArray2D32f[0, i] = (x, y)

    # Fits ellipse to current contour.
    (center, size, angle) = cv.FitEllipse2(PointArray2D32f)

    # Convert ellipse data from float to integer representation.
    center = (cv.Round(center[0]), cv.Round(center[1]))
    size = (cv.Round(size[0] * 0.5), cv.Round(size[1] * 0.5))

    # Draw ellipse
    cv.Ellipse(orig, center, size, angle, 0, 360, cv.RGB(255,0,0), 2,cv.CV_AA, 0)

# show images
cv.ShowImage("image - press 'q' to quit", orig)
#cv.ShowImage("post-process", processed)
cv.WaitKey(-1)

EDIT:

Просто обновите, чтобы сказать, что я считаю, что основная тема для всех этих ответов заключается в том, что существует множество дополнительных предположений и ограничений, которые могут быть применены к тому, что вы хотите распознать как круговое. Мой собственный ответ не делает никаких претензий к этому - ни в низкоуровневой предварительной обработке, ни в высокоуровневой геометрической подгонке. Тот факт, что многие из кругов на самом деле не такие круглые из-за того, как они нарисованы, или неаффинных/проективных преобразований изображения, а также с другими свойствами в том, как они визуализируются/захватываются (цвет, шум, освещение, толщина края) - все результат в любом количестве возможных кругов кандидата только в одном изображении.

Есть гораздо более сложные методы. Но они будут стоить вам. Лично мне нравится идея @fraxel об использовании добавочного порога. Это быстро, надежно и достаточно надежно. Затем вы можете дополнительно проверить конечные контуры (например, использовать моменты Hu) или фитинги с простым анализом отношения оси эллипса. if ((min (размер)/max (размер)) > 0,7).

Как и в случае с Computer Vision, существует напряженность между прагматизмом, принципом и парсономией. Поскольку я люблю рассказывать людям, которые считают, что резюме легко, это не так - на самом деле это классно проблема AI complete. Лучшее, что вы часто можете надеяться за пределами этого, - это то, что работает большую часть времени.

Ответ 4

Просматривая свой код, я заметил следующее:

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

  • Обнаружение кромок после удаления шума (эра/расширение). Это не обязательно; Канни должно позаботиться об этом.

  • Обнаружение крохотных краев. Ваши "открытые" круги имеют два края, внутренний и внешний края. Поскольку они достаточно близки, фильтр Canny gauss может добавить их вместе. Если это не так, у вас будет два края близко друг к другу. То есть перед Canny у вас есть открытые и заполненные круги. Впоследствии у вас есть 0/2 и 1 край, соответственно. Поскольку Hough снова вызывает Canny, в первом случае два ребра могут быть сглажены вместе (в зависимости от начальной ширины), поэтому основной алгоритм Hough может рассматривать открытые и заполненные круги одинаково.

Итак, моя первая рекомендация - изменить отображение оттенков серого. Не используйте интенсивность, но используйте оттенок/насыщенность/значение. Кроме того, используйте дифференциальный подход - вы ищете края. Итак, вычислите преобразование HSV, сгладьте копию, а затем возьмите разницу между оригинальной и сглаженной копией. Это даст вам значения dH, dS, dV (локальная вариация в цветовой гамме, насыщенности, значение) для каждой точки. Квадрат и добавьте, чтобы получить одномерное изображение, с пиками у всех краев (внутри и снаружи).

Моя вторая рекомендация будет местной нормализацией, но я не уверен, что это даже необходимо. Идея состоит в том, что вы не особо заботитесь о точном значении сигнала края, который вы выбрали, он должен быть бинарным в любом случае (край или нет). Таким образом, вы можете нормализовать каждое значение, разделив его на локальный средний (где локальный размер порядка вашего края).

Ответ 5

Преобразование Hough использует "модель" для поиска определенных объектов в (как правило) изображении, обнаруженном краем, как вы, возможно, знаете. В случае HoughCircles эта модель является идеальным кругом. Это означает, что, вероятно, не существует комбинации параметров, которые позволят обнаружить более неуправляемые и эллипсовидные круги на вашем изображении без увеличения количества ложных срабатываний. С другой стороны, благодаря основополагающему механизму голосования, незакрытый идеальный круг или идеальный круг с "вмятиной" могут последовательно отображаться. Поэтому в зависимости от ожидаемого результата вы можете или не захотите использовать этот метод.

Тем не менее, есть несколько вещей, которые я вижу, которые могут помочь вам в этом:

  • HoughCircles вызывает Canny внутренне, поэтому, я думаю, вы можете оставить этот вызов.
  • param1 (который вы вызываете HIGH) обычно инициализируется вокруг значения 200. Он используется как параметр для внутреннего вызова Canny: cv.Canny(processed, cannied, HIGH, HIGH/2). Это может помочь запустить Canny самостоятельно, как это, чтобы увидеть, как настройка HIGH влияет на обрабатываемое изображение с помощью преобразования Hough.
  • param2 (который вы вызываете LOW) обычно инициализируется вокруг значения 100. Это порог голосования для аккумуляторов преобразования Hough. Установка этого значения означает более ложные отрицания, более низкие ложные срабатывания. Я считаю, что это первый, с которым вы хотите начать играть.

Ссылка: http://docs.opencv.org/3.0-beta/modules/imgproc/doc/feature_detection.html#houghcircles

Обновить re: заполненные круги. После того, как вы нашли фигуры круга с преобразованием Hough, вы можете проверить, заполнены ли они путем выборки цвета границы и сравнения его с одной или несколькими точками внутри предполагаемый круг. В качестве альтернативы вы можете сравнить одну или несколько точек внутри предполагаемого круга с заданным цветом фона. Круг заполняется, если первое сравнение выполняется успешно, или в случае альтернативного сравнения, если оно терпит неудачу.

Ответ 6

Хорошо глядя на изображения. Я предлагаю использовать **Active Contours**

  • Активные контуры Хорошая вещь об активных контурах заключается в том, что они почти идеально вписываются в любую форму. Будь то квадраты или треугольник, и в вашем случае они идеальные кандидаты.
  • Если вы можете извлечь центр кругов, это здорово. Активным контурам всегда нужен момент, из которого они могут либо расти, либо уменьшаться, чтобы соответствовать. Не обязательно, чтобы центры всегда были выровнены по центру. Небольшое смещение все равно будет в порядке.
  • И в вашем случае, если вы позволите контурам вырасти из центра наружу, они оставят границы круга.
  • Обратите внимание, что активные контуры, которые растут или сжимаются, используют энергию воздушного шара, что означает, что вы можете установить направление контуров, внутрь или наружу.
  • Вам, вероятно, понадобится использовать градиентное изображение в шкале серого. Но все же вы можете попробовать и цвет. Если это сработает!
  • И если вы не предоставляете центры, забросьте множество активных контуров, сделайте, затем увеличивайте/уменьшайте. Контуры, которые располагаются, сохраняются, неустроенные отброшены. Это подход грубой силы. Будет интенсивный процессор. Но вам потребуется более тщательная работа, чтобы вы оставили правильные контуры и выбрасывали плохие.

Надеюсь, что вы сможете решить эту проблему.