Обнаружение круга — Оценка надежности

Я пишу приложение на C ++ для OpenCV. Приложение в основном анализирует рукописные изображения и распознает символы (не ожидайте буквенно-цифровых символов, это система письма для глухих).

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

Выбор персонажей в форме круга.

Для распознавания символов в форме круга я использую Hough Circle Transform, которая делает свою работу довольно хорошо. Преобразование применяется после применения медианного фильтра для уменьшения шума и порогового значения для преобразования изображения в двоичную форму.

Моя проблема в том, что иногда Hough Circle Transform обнаруживает круги там, где их нет. (см. следующую картину).

Обнаружение сумасшедшего круга.

Теперь я искал некоторую «оценку надежности» для обнаруженных кругов. Но мне мало повезло.
Есть ли способ узнать, относится ли обнаруженный круг к реальному кругу?

Я начинаю думать о некоторых решениях самостоятельно, но, может быть, кто-то придумал что-то умнее, я мог бы:

  • Оцените расстояние Хусдорфа каждой точки обнаруженного круга с реальным символом и используйте его как измерение некоторого вида
  • Используя координаты обнаруженного центра, я мог бы разделить изображение на 4 сектора (см. Изображение ниже) и посмотреть, обнаруживает ли преобразование Хафа Круг в каждом (или большинстве) секторов.

Изображение разрезано на 4 сектора по координатам центра.

Помните: я имею в виду рукописные (т.е. очень грубо нарисованные) символы.

2

Решение

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

Однако существуют более и менее сложные и эффективные способы оценки расстояния.

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

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

0

Другие решения

Я решил проблему разработки функции, основанной на идее @Abhishek.

Вот псевдокод и его реализация на C ++.

checkCircleSectors(imagePoints, circle, circleExpansionFactor, theta, acceptThreshold)

Divide the circle in n sectors, using angle theta (so n = 2*PI /theta)

(Optional) Slightly expand or reduce the radius of the circle by circleExpansionFactor, if needed.

for each point "curPoint" within the image (imagePoints){

if the distance between curPoint and center.circle is lesser/equal to circle.radius{

let "curAngle" be the angle between circle.center and curPoint, calculated using curPoint as origin.
let "curSector" be the sector of circle which contains curAngle
upgrade the ranking of curSector by one.
}
}

if there are more than acceptThreshold sectors whose rank is zero
the circle is not acceptable
else
the circle is acceptable

Заметки:

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

Вот моя реализация концепции на C ++:

boolean ImgCheck::checkCircleSectors(vector<Point> tgtPoints, Point tgtCenter, int tgtRadius, float tgtRadiusExp, int tgtStep, int tgtThreshold){

vector<int> circleData( 360 / tgtStep, 0);
int detectionReliability = 0;

tgtRadius = tgtRadius * tgtRadiusExp;

/* Analyze the sectors.                               */
for(size_t i=0; i<tgtPoints.size(); i++){

Point curCartesianPoint = getCartesianCoordinates(tgtCenter, tgtPoints[i]);

float angleRad = arctangent2(curCartesianPoint);
int   angleDeg = angleRad * (180/M_PI);

if(distance(tgtPoints[i],tgtCenter) <= tgtRadius){
circleData.at(angleDeg / tgtStep) += 1;
}

}

/* Count the postive-ranked sectors.                 */
for(size_t i = 0; i< circleData.size(); i++){
if(circleData[i] > 0)
detectionReliability += 100.0/(360/tgtStep);
}

if(detectionReliability >= tgtThreshold)
return true;
}
return false;
}

Заметки:

Я предпочитаю последние три параметра:

  • tgtRadiusExp = 1,25 (радиус увеличивается на четверть его длины)
  • tgtStep = 5 (тета = 5 градусов -> круг, разделенный на 72 сектора)
  • tgtTreshold = 75 (как минимум 75 ненулевых секторов, необходимых для прохождения теста)

Функция getCartesianCoordinates (исходный код ниже) преобразует координаты OpenCV в декартовы координаты. Требуется два аргумента:

  • Точка tgtOrigin — это координаты openCV точки, которые должны быть
    используется в качестве источника.
  • Точка tgtPoint — это координаты openCV другой точки.

Функция возвращает координаты tgtPoint, преобразованные с использованием tgtOrigin в качестве источника.

Point getCartesianCoordinates(Point tgtOrigin, Point tgtPoint){

Point resPoint = tgtPoint - tgtOrigin;

return Point(resPoint.x, -resPoint.y);
}
0

Потратив некоторое время на ручное кодирование детекторов эллипса, я пошел по тому же пути в отношении обнаружения «эллипсности» (хорошее соответствие — это руководство). В конечном счете, однако, ручное кодирование таких детекторов является хрупким бизнесом, потому что ваш вклад на самом деле не так хорошо определен; вы, вероятно, обнаружите, что читатели-люди успешно распознают множество «кругов», которые не подойдут ни к какому разумному математическому определению «округлости». Поэтому примите, что фактическое рабочее определение вашего персонажа не является уравнением круга.

Я предлагаю вам рассмотреть совершенно другой подход; вместо детекторов ручного кодирования, тренировать их. Это современный подход к распознаванию рукописного текста, и вы можете выбрать популярные проверенные алгоритмы (набор данных MNIST рукописных арабских цифр является популярным эталоном). Вместо кодирования детекторов создайте себе действительно приличный тренировочный набор; вам не нужно будет вручную кодировать детекторы для каждого символа, и вы создадите что-то действительно надежное и хорошо протестированное, которое может справиться с очень небрежным почерком, пятнами, каракулями и т. д. (например, вы можете найти в наборе данных MNIST ).

0
По вопросам рекламы [email protected]