如何摆脱图像中的不均匀照明,这些图像包含通常打印但可能是手写的文本数据?它可以有一些光点,因为在制作图片时会反射光线。我已经看到 Halcon 程序的 segment_characters 函数完美地完成了这项工作,但它不是开源的。我希望将图像转换为在背景和更深色文本区域具有恒定照明的图像。这样二值化将很容易且没有噪音。假定文本比它的背景颜色深。有任何想法吗?
6 回答
严格来说,假设您可以访问图像的像素(您可以在线搜索如何在您的编程语言中完成此操作,因为该主题非常可用),该练习涉及检查像素一次以确定“暗度阈值”。为此,您将每个像素从RGB 转换为 HSL,以获得每个像素的亮度级别分量。在此过程中,您可以计算整个图像的平均亮度,您可以将其用作“暗度阈值”
获得图像平均亮度级别后,您可以再次检查图像像素,如果像素小于暗度阈值,则将其颜色设置为全白 RGB(255,255,255),否则,将其颜色设置为全黑 RGB( 0,0,0)。这会给你一个二进制图像,其中文本应该是黑色的 - 其余的应该是白色的。
当然,关键是找到合适的暗度阈值——所以如果平均方法不能给你很好的结果,你可能不得不想出一种不同的方法来增加这个步骤。这种方法可能涉及分离主要通道红色、绿色、蓝色中的图像,并分别计算每个通道的暗度阈值,然后使用三个通道的激进阈值。
最后,一个更好的方法可能是计算光照水平分布——而不是简单的平均值——然后据此,最大值附近的范围就是你想要保持的。再一次,检查每个像素,如果它的亮度适合波段,则将其设为黑色,否则,将其设为白色。
编辑
对于 HSL 的进一步阅读,我建议从HSL 和 HSV 颜色空间的维基条目开始。
使用局部阈值而不是全局阈值算法。将您的图像(灰度)划分为较小图像的网格(例如 50x50 像素),并对每个图像应用阈值算法。
您是否尝试过使用形态学技术?Closure-by-reconstruction(如Gonzalez、Woods 和 Eddins中所述)可用于创建背景照明级别的灰度表示。您可以通过以下方式或多或少标准化有效照明:
1)计算图像中所有像素的平均强度
2) 使用重构关闭来估计背景光照水平
3)从原始图像中减去(2)的输出
4) 将 (1) 的平均强度添加到 (3) 的输出中的每个像素。
基本上,通过重建关闭的作用是删除所有小于特定尺寸的图像特征,擦除“前景”(您要捕获的文本)并只留下“背景”(照明级别)。从原始图像中减去结果只会留下小尺度偏差(文本)。将原始平均强度添加到这些偏差中只是为了使文本可读,从而使生成的图片看起来像原始图像的光归一化版本。
如果背景特征一般比字母大,可以尝试估计,随后去除背景。
有很多方法可以做到这一点,一种非常简单的方法是在图像上运行中值滤波器。您希望过滤器窗口足够大,以使窗口内的文本很少占像素的三分之一以上,但又足够小,以便有几个窗口适合亮点。此过滤器应生成没有文本但只有背景的图像。从原始图像中减去它,你应该有一个可以用全局阈值分割的图像。
请注意,如果亮点远小于文本,则相反:选择过滤器窗口,使其仅去除光线。
看起来您正在尝试做的是提高局部对比度,同时减弱更大规模的照明变化。我同意其他海报的观点,即通过更好的照明优化图像应该始终是第一步。
之后,这里有两个技巧。
1) 使用 smooth_image() 运算符对原始图像进行高斯卷积。使用相对较大的内核,例如 20-50 像素。然后从原始图像中减去这个模糊的图像。在 sub_image() 运算符中应用比例和偏移量,或使用 equ_histo() 来均衡直方图。
这基本上从原始信息中减去了低空间频率信息,而保留了较高频率信息。
2)您可以尝试使用 highpass_image() 运算符或拉普拉斯运算符之一来提取渐变图像。