Грешни аргументи в метода HoughCircles от Emgu CV

Опитвам се да напиша приложение, което открива монети в изображението. Намерих част от кода, който използва HoughCircles на Emgu CV. Не мога обаче да задам параметрите така, че да връщам всяка монета (кръгчета). Имате ли опит с този проблем? Благодаря за съвета.

Това е код:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;

namespace INZO_Sem_Pr3_ST28605
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        Bitmap bitmap = new Bitmap(pictureBox1.Image);

        //Load the image from file
        Image<Bgr, Byte> img = new Image<Bgr, byte>(bitmap);

        //Get and sharpen gray image (don't remember where I found this code; prob here on SO)
        Image<Gray, Byte> graySoft = img.Convert<Gray, Byte>().PyrDown().PyrUp();
        Image<Gray, Byte> gray = graySoft.SmoothGaussian(3);
        gray = gray.AddWeighted(graySoft, 1.5, -0.5, 0);

        Image<Gray, Byte> bin = gray.ThresholdBinary(new Gray(70), new Gray(255));

        Gray cannyThreshold = new Gray(200);
        Gray cannyThresholdLinking = new Gray(100);
        Gray circleAccumulatorThreshold = new Gray(1000);

        Image<Gray, Byte> cannyEdges = bin.Canny(cannyThreshold.Intensity, cannyThresholdLinking.Intensity);

        pictureBox1.Image = cannyEdges.ToBitmap();

        //Circles
        CircleF[] circles = cannyEdges.HoughCircles(
            cannyThreshold,
            circleAccumulatorThreshold,
            1.0, //Resolution of the accumulator used to detect centers of the circles
            cannyEdges.Height / 8, //min distance 
            0, //min radius
            2000 //max radius
            )[0]; //Get the circles from the first channel

        //draw circles (on original image)
        foreach (CircleF circle in circles)
            img.Draw(circle, new Bgr(Color.Brown), 2);
    }
}
}

Прочетох повече обяснения какво означават тези аргументи, но не мога да задам добри стойности. Това е резултат след откриване на край на употреба: въведете описание на изображението тук


person avalagne    schedule 27.12.2013    source източник


Отговори (1)


Нека поговорим малко за трансформацията на Hough. В най-простата си форма трансформацията на Hough се използва за откриване на линии. Това се прави, като се вземе всеки „настроен“ пиксел в изображение и се определят всички възможни линии, които пресичат тази точка. Самият набор от решения е уравнение за линия. След това, като се имат предвид всички тези уравнения на линиите, вие решавате пресечните точки между тях и местоположението на най-често срещаното пресичане представлява решение за линия, която е най-разпространена.

В действителност това се прави чрез изчертаване на подмножество от всяка линия на решение в изображение, така че когато зададете целеви пиксел, добавяте 1 към него. След това сканирате изображението и намирате пиксела с най-ярък цвят и това е най-разпространената линия. (и в действителност работите в полярни координати, но това е друга история)

За кръгове работи по подобен начин, но тук ставаме подли. Ние фиксираме радиус за окръжности, които търсим, и за всеки „настроен“ пиксел в изображението решаваме за всички окръжности, които биха могли да пресичат тази точка (което само по себе си е уравнението за окръжност). След това намирате всички пресечни точки на тези кръгове и най-често срещаната пресечна точка е най-разпространеният кръг с фиксирания радиус в изображението.

В действителност това се прави чрез начертаване на всеки кръг от решение върху изображение по точно същия начин като примера с линия и „най-ярката“ точка в изображението е центърът на най-разпространения кръг в изображението. И реална реалност, OpenCV използва градиентен тест, за да намали изчисленията.

Сега моето мнение за това е, че в документация, обаждането първо ще изпълни откриване на Canny Edge. Изглежда, че изпълнявате HoughCircles на изображение, което вече е било разпознато. недей така

След това нека да разгледаме прага на акумулатора. Това основно означава да се запазят всички кръгове, за които има n или повече посещения. Като го зададете на 1000, вие казвате, че трябва да имате поне 1000 комплекта решения за всеки кръг. Това е лудост. Трябва да използвате някакъв процент от обиколката на кръга с най-малък радиус, който очаквате да намерите. Колкото по-близо сте до 100%, толкова по-непрекъснат трябва да бъде кръгът.

Аргументът dp се използва, за да се определи колко голямо трябва да бъде пространството за решение. Колкото повече dp доближава 0, толкова повече памет ще е необходима). Колкото dp расте, толкова по-малко точен е резултатът. Не бих използвал нищо повече от 2, освен ако изходното ми изображение не е огромно.

Минималното разстояние позволява кръговете да се припокриват и с колко.

Минималният и максималния радиус правят точно това, което пише на кутията, но преминаването от 0 до 1000 е странно. 0 е по подразбиране за „не знам“, но мисля, че би било по-добре с нещо като 6 или 7 (кръг с диаметър 12 пиксела е почти толкова малък, колкото може да изобрази прилично изглеждащ кръг). Тогава максимумът ще бъде това, което смятате за разумно за вашия проблемен домейн - например 100?

Ако искате повече подробности, написах статья преди известно време за начини за внедряване и създаване Хаф се трансформира по-бързо.

person plinth    schedule 27.12.2013
comment
Благодаря много за изчерпателния отговор. Английският ми не е в допълнителното ниво, така че прочетох малко няколко пъти, за да го разбера правилно. Благодаря ви отново, ще споделя резултатите, когато се възползвам от тази възможност. - person avalagne; 28.12.2013
comment
Промених аргументите си, както описахте. По същия начин избягвам многократно внедряване на Canny edge detection. Но нямам никакви кръгове в полето CircleF. Аргументи сега: Image‹Gray, Byte› bin = gray.ThresholdBinary(new Gray(70), new Gray(255)); Gray cannyThreshold = new Gray(200); Gray cannyThresholdLinking = new Gray(100); Сив кръгAccumulatorThreshold = нов сив (50); CircleF[] кръгове = bin.HoughCircles( cannyThreshold, circleAccumulatorThreshold, 1.0, //Центрове на разделителна способност на кръговете 10, //минимално разстояние 6, //минимален радиус 100 //максимален радиус)[0]; - person avalagne; 28.12.2013