您的两个图像都包含许多与您要查找的符号无关的行。而且其中一些线比您实际想要的线更长/具有更高的对比度,因此我认为检测边缘线(例如,使用霍夫变换或通过水平/垂直汇总对比度)将无法工作。
但是:您正在寻找的标志还有其他特征,应该更容易发现:
- 那里的标志背景具有(几乎)恒定的亮度
- 它占据了图像的较大区域
- 它在图像中心附近
因此,您正在寻找对比度低的大连接区域。我在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不包含连接的组件分析-您可以使用泛洪填充或 Fill cvBlobsLib。
现在,只需找到图像中心附近的最大斑点并找到凸包(我只是使用了未与背景相连的最大斑点,但这可能不足以容纳所有图像)。
结果: