Оба ваших изображения содержат много строк, которые не имеют ничего общего со знаком, который вы ищете. И некоторые из этих линий длиннее / имеют более высокую контрастность, чем линии, которые вы на самом деле хотите, поэтому я думаю, что обнаружение краевых линий (например, с помощью грубого преобразования или суммирования контрастов по горизонтали / вертикали) не будет работать.
Но: у знака, который вы ищете, есть другие характеристики, которые должно быть легче обнаружить:
- Там знак фона имеет (почти) постоянную яркость
- Занимает относительно большую площадь изображения
- Это недалеко от центра изображения
Итак, вы ищете большую соединенную область с низким контрастом. Я взломал алгоритм проверки концепции в 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 .
Теперь просто найдите самый большой шарик рядом с центром изображения и найдите выпуклый корпус (я просто использовал самый большой шарик, который не связан с фоном, но этого может быть недостаточно для каждого изображения).
Результаты: