我实现了一些自适应二值化方法,它们使用一个小窗口,并在每个像素处计算阈值。这些方法存在问题:如果我们选择的窗口尺寸太小,我们会得到这个效果(我认为原因是因为窗口尺寸小)
(来源:piccy.info)
左上角有一个原始图像,右上角 - 全局阈值结果。左下 - 将图像划分为某些部分的示例(但我说的是分析图像的像素小环境,例如大小为 10X10 的窗口)。所以你可以在右下角看到这样的算法的结果,我们得到了一个黑色的区域,但它必须是白色的。有人知道如何改进算法来解决这个问题吗?
我实现了一些自适应二值化方法,它们使用一个小窗口,并在每个像素处计算阈值。这些方法存在问题:如果我们选择的窗口尺寸太小,我们会得到这个效果(我认为原因是因为窗口尺寸小)
(来源:piccy.info)
左上角有一个原始图像,右上角 - 全局阈值结果。左下 - 将图像划分为某些部分的示例(但我说的是分析图像的像素小环境,例如大小为 10X10 的窗口)。所以你可以在右下角看到这样的算法的结果,我们得到了一个黑色的区域,但它必须是白色的。有人知道如何改进算法来解决这个问题吗?
在这方面应该有很多研究正在进行,但不幸的是我没有很好的链接可以提供。
一个可能可行但我没有测试过的想法是尝试估计照明变化,然后在阈值化之前将其移除(这是一个比“二值化”更好的术语)。然后问题从自适应阈值转移到找到一个好的照明模型。
如果您对光源有所了解,那么您当然可以从中构建模型。
否则,一个可能有效的快速技巧是对您的图像应用一个非常重的低通滤波器(模糊它),然后将其用作您的照明模型。然后在原始版本和模糊版本之间创建差异图像,并对其进行阈值处理。
编辑:经过快速测试,我的“快速破解”似乎根本不起作用。仔细想想,我也不是很惊讶:)
I = someImage
Ib = blur(I, 'a lot!')
Idiff = I - Idiff
It = threshold(Idiff, 'some global threshold')
编辑 2 有了另一个想法,这取决于您的图像是如何生成的。尝试从图像的前几行估计光照模型:
不幸的是,我在家没有任何好的工具来测试它。
看起来你正在做错误的自适应阈值。您的图像看起来好像您将图像分成小块,为每个块计算阈值并将该阈值应用于整个块。这将解释“盒子”工件。通常,自适应阈值处理意味着分别为每个像素找到一个阈值,并以像素为中心有一个单独的窗口。
另一个建议是为您的照明建立一个全局模型:在您的示例图像中,我很确定您可以使用最小二乘法将平面(在 X/Y/亮度空间中)拟合到图像中,然后将像素分成比该平面(背景)更亮(前景)和更暗的像素。然后,您可以将单独的平面拟合到背景和前景像素,再次使用这些平面之间的平均值作为阈值并迭代地改进分割。这在实践中的效果取决于你的闪电可以用线性模型建模的程度。
如果您尝试分割的实际对象“更薄”(您在评论中谈到了条形码),您可以尝试简单的打开/关闭操作来获取照明模型。(即关闭图像去除前景像素,然后使用[关闭图像+X]作为阈值)。
或者,您可以尝试均值偏移过滤以使前景和背景像素具有相同的亮度。(就个人而言,我会先尝试那个)
你有非常不均匀的照明和相当大的物体(因此,没有通用的简单方法来提取背景和纠正不均匀性)。这基本上意味着您根本不能使用全局阈值,您需要自适应阈值。
您想尝试 Niblack 二值化。Matlab 代码可在此处获得 http://www.uio.no/studier/emner/matnat/ifi/INF3300/h06/undervisningsmateriale/week-36-2006-solution.pdf(第 4 页)。您必须手动调整两个参数:窗口大小(上面代码中的 N)和权重。
尝试使用以下过程应用本地自适应阈值:
局部自适应阈值方法为每个像素选择一个单独的阈值。
我广泛使用这种方法,它适用于具有非均匀背景的图像。