Обидва ваші зображення містять багато рядків, які не мають нічого спільного з знаком, який ви шукаєте. І деякі з цих ліній довші / мають вищий контраст, ніж лінії, які ви насправді хочете, тому, я думаю, виявити лінії ребер (наприклад, за допомогою перетворення Hough або шляхом підсумовування контрастів по горизонталі / вертикалі) не вийде.
Але: Знак, який ви шукаєте, має інші характеристики, які слід легше виявити:
- Там фон знаків має (майже) постійну яскравість
- Він займає відносно велику площу зображення
- Це біля центру зображення
Отже, ви шукаєте велику пов’язану зону з низьким контрастом. Я зламав алгоритм підтвердження концепції в Mathematica. (Я не є експертом OpenCV, але зазначу відповідну функцію OpenCV, коли я їх знаю.)
По-перше, я використовую гауссові похідні фільтри, щоб виявити величину градієнта на кожному пікселі. Газовий похідний фільтр має широку діафрагму (в цьому випадку 11x11 пікселів), тому він дуже нечутливий до шуму. Потім я нормалізую градієнтне зображення на значення = 1, тому я можу використовувати однакові пороги для обох зразків.
src = Import["http://www.freeimagehosting.net/uploads/720da20080.jpg"];
pixels = ImageData[ColorConvert[src, "Grayscale"]];
gradient = Sqrt[GaussianFilter[pixels, 5, {1, 0}]^2 + GaussianFilter[pixels, 5, {0, 1}]^2];
gradient = gradient/Mean[Flatten[gradient]];
Реалізація OpenCV: Ви можете використовувати sepFilter2D
для фактичної фільтрації, але, мабуть, вам доведеться самостійно обчислити значення ядра фільтра .
Результат виглядає приблизно так:
У цьому зображенні фон знаків темний, а межі знаків - яскраві. Тож я можу бінарнізувати це зображення і шукати темно пов'язані компоненти.
binaryBorders = Binarize[Image[gradient], 0.2];
sign = DeleteBorderComponents@ColorNegate[binaryBorders];
largestComponent = SortBy[ComponentMeasurements[sign, {"Area", "ConvexVertices"}][[All, 2]], First][[-1, 2]];
Реалізація OpenCV: Порог повинен бути простим, але я думаю, що OpenCV не містить підключеного аналізу компонентів - для цього можна використовувати або заливку, або cvBlobsLib .
Тепер просто знайдіть найбільшу крапку біля центру зображення і знайдіть опуклий корпус (я просто використав найбільшу крапку, яка не підключена до фону, але це може бути недостатньо для кожного зображення).
Результати: