照明不均匀的图像
如何消除包含文本数据(通常是打印但可能是手写)的图像中的不均匀照明?由于拍摄时光线反射,它可能会有一些光点。 我已经看到 Halcon 程序的segment_characters 函数完美地完成了这项工作, 但它不是开源的。 我希望将图像转换为背景照明恒定且文本区域颜色更深的图像。这样二值化就会很容易并且没有噪音。 假定文本颜色比背景颜色深。 有什么想法吗?
How to get rid of uneven illumination from images, that contain text data, usually printed but may be handwritten? It can have some spots of lights because the light reflected while making picture.
I've seen the Halcon program's segment_characters function that is doing this work perfectly,
but it is not open source.
I wish to convert an image to the image that has a constant illumination at background and more dark colored regions of text. So that binarization will be easy and without noise.
The text is assumed to be dark colored than it's background.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
严格来说,假设您可以访问图像的像素(您可以在线搜索如何用您的编程语言完成此操作,因为该主题有大量可用),该练习涉及检查像素一次以确定“暗度阈值”。为此,您将每个像素从 RGB 转换为 HSL,以便获取每个像素的亮度级别分量。在此过程中,您可以计算整个图像的平均亮度,可以将其用作“暗度阈值”
一旦获得图像平均亮度级别,您可以再次检查图像像素,如果如果像素小于暗度阈值,则将其颜色设置为全白 RGB(255,255,255),否则将其颜色设置为全黑 RGB(0,0,0)。这将为您提供一个二值图像,其中文本应为黑色 - 其余部分应为白色。
当然,关键是找到合适的黑暗阈值 - 因此,如果平均方法不能给您带来好的结果,您可能必须想出一种不同的方法来增强该步骤。这种方法可能涉及分离主要通道红色、绿色、蓝色中的图像,并分别计算每个通道的黑暗阈值,然后使用这三个通道的激进阈值。
最后,更好的方法可能是计算亮度级别分布 - 与简单的平均值相反 - 然后从中,最大值周围的范围就是您想要保留的范围。再次检查每个像素,如果其亮度适合条带,则将其设为黑色,否则将其设为白色。
编辑
要进一步阅读有关 HSL 的内容,我建议从 关于 HSL 和 HSV 的 Wiky 条目开始色彩空间。
Strictly speaking, assuming you have access to the image's pixels (you can search online for how to accomplish this in your programming language as the topic is abundantly available), the exercise involves going over the pixels once to determine a "darkness threshold". In order to do this you convert each pixel from RGB to HSL in order to get the lightness level component for each pixel. During this process you calculate an average lightness for the whole image which you can use as your "darkness threshold"
Once you have the image average lightness level, you can go over the image pixels once more and if a pixel is less than the darkness threshold, set it's color to full white RGB(255,255,255), otherwise, set it's color to full black RGB (0,0,0). This will give you a binary image with in which the text should be black - the rest should be white.
Of course, the key is in finding the appropriate darkness threshold - so if the average method doesn't give you good results you may have to come up with a different method to augment that step. Such a method could involve separating the image in the primary channels Red, Green, Blue and computing the darkness threshold for each channel separately and then using the aggressive threshold of the three..
And lastly, a better approach may be to compute the light levels distribution - as opposed to simply the average - and then from that, the range around the maximum is what you want to keep. Again, go over each pixel and if it's lightness fits the band make it black, otherwise, make it white.
EDIT
For further reading about HSL I recommend starting with the Wiky entry on HSL and HSV Color spaces.
您是否尝试过使用形态学技术? Closure-by-reconstruction(如 Gonzalez、Woods 和 Eddins 中介绍的)可以用于创建背景照明级别的灰度表示。您可以通过以下方式或多或少地标准化有效照明:
1) 计算图像中所有像素的平均强度
2) 使用重建闭包来估计背景照明水平
3) 从 (2) 的输出中减去 (2) 的输出原始图像
4) 将 (1) 的平均强度添加到 (3) 输出中的每个像素。
基本上,重建闭合的作用是删除所有小于特定尺寸的图像特征,擦除“前景”(要捕获的文本)并仅留下“背景”(照明级别)。从原始图像中减去结果仅留下小范围的偏差(文本)。将原始平均强度添加到这些偏差中只是为了使文本可读,以便生成的图片看起来像原始图像的光归一化版本。
Have you tried using morphological techniques? Closure-by-reconstruction (as presented in Gonzalez, Woods and Eddins) can be used to create a grayscale representation of background illumination levels. You can more-or-less standardize the effective illumination by:
1) Calculating the mean intensity of all the pixels in the image
2) Using closure-by-reconstruction to estimate background illumination levels
3) Subtract the output of (2) from the original image
4) Adding the mean intensity from (1) to every pixel in the output of (3).
Basically what closure-by-reconstruction does is remove all image features that are smaller than a certain size, erasing the "foreground" (the text you want to capture) and leaving only the "background" (illumination levels) behind. Subtracting the result from the original image leaves behind only small-scale deviations (the text). Adding the original average intensity to those deviations is simply to make the text readable, so that the resulting picture looks like a light-normalized version of the original image.
使用局部阈值代替全局阈值算法。
将图像(灰度)划分为较小图像的网格(例如 50x50 像素),并对每个单独的图像应用阈值算法。
Use Local-Thresholding instead of the global thresholding algorithm.
Divide your image(grayscale) in to a grid of smaller images (say 50x50 px) and apply the thresholding algorithm on each individual image.
如果背景特征通常比字母大,您可以尝试估计并随后删除背景。
有很多方法可以做到这一点,一种非常简单的方法是在图像上运行中值滤波器。您希望过滤器窗口足够大,以便窗口内的文本很少占像素的三分之一以上,但又足够小,以便有多个窗口适合亮点。此过滤器应该生成没有文本但仅具有背景的图像。从原始图像中减去它,您应该得到一个可以使用全局阈值分割的图像。
请注意,如果亮点比文本小得多,则执行相反的操作:选择滤镜窗口,使其仅去除光线。
If the background features are generally larger than the letters, you can try to estimate and subsequently remove the background.
There are many ways to do that, a very simple one would be to run a median filter on your image. You want the filter window to be large enough that text inside the window rarely makes up more than a third of the pixels, but small enough that there are several windows that fit into the bright spots. This filter should result in an image without text, but with background only. Subtract that from the original, and you should have an image that can be segmented with a global threshold.
Note that if the bright spots are much smaller than the text, you do the inverse: choose the filter window such that it removes the light only.
您需要尝试的第一件事是改变照明,使用顶灯或其他可以给您带来更漫射和均匀光线的灯光。
如果这不可能,您可以尝试此问题或这个。您想要实现某种类型的“自适应阈值”,这会将局部阈值应用于图像的各个部分,以便对比度的变化不会那么明显。
此处解释了一种简单但有效的方法。该算法的简单概要如下:
The first thing you need to try and do it change the lighting, use a dome light or some other light that will give you a more diffuse and even light.
If that's not possible, you can try some of the ideas in this question or this one. You want to implement some type of "adaptive threshold", this will apply a local threshold to individual parts of the image so that the change in contrast won't be as noticable.
There is also a simple but effective method explained here. The simple outline of the alrithm is the following:
看来您想要做的是提高局部对比度,同时减弱较大范围的照明变化。我同意其他海报的观点,即通过更好的照明来优化图像始终应该是第一步。
之后,这里有两个技巧。
1)使用 smooth_image() 运算符对原始图像进行高斯卷积。使用相对较大的内核,例如 20-50px。然后从原始图像中减去该模糊图像。在 sub_image() 运算符中应用缩放和偏移,或使用 equ_histo() 来均衡直方图。
这基本上从原始数据中减去了低空间频率信息,而完整地保留了较高频率的信息。
2)您可以尝试使用 highpass_image() 运算符或拉普拉斯运算符之一来提取渐变图像。
It seems like what you're trying to do is improve local contrast while attenuating larger scale lighting variations. I'll agree with other posters that optimizing the image through better lighting should always be the first move.
After that, here are two tricks.
1) Use smooth_image() operator to convolve a gaussian on your original image. Use a relaitively large kernel, like 20-50px. Then subtract this blurred image from your original image. Apply scale and offset within sub_image() operator, or use equ_histo() to equalize histogram.
This basically subtracts the low spatial frequency information from the original, leaving the higher frequency information intact.
2) You could try highpass_image() operator, or one of the laplacian operators to extract a gradiant image.