【发布时间】:2021-01-04 02:18:57
【问题描述】:
tesseract OCR 文本识别的最大挑战之一是图像的照明不均匀。 我需要一种算法来判断图像是否包含不均匀的照明。
测试图像
我附上了no illumination image、glare image( white-spotted image)和shadow containing image的图片。
如果我们给算法一个图像,算法应该分为两类,如
- 没有不均匀的照明 - 我们的
no illumination image将属于此类。 - 照明不均匀 - 我们的
glare image( white-spotted image)、shadow containing image将属于此类。
无照明图像 - A 类
不均匀照明图像(眩光图像(白点图像))B类
不均匀照明图像(包含图像的阴影)B 类
初始方法
-
将色彩空间更改为 HSV
-
HSV值通道的直方图分析识别光照不均。
我们可以使用感知亮度来代替前两个步骤 渠道而不是HSV的价值渠道
-
设置一个低阈值以获得小于低阈值的像素数
-
设置高阈值以获取高于高阈值的像素数
-
低像素值百分比和高像素值百分比以检测不均匀闪电情况(百分比的设置阈值也是如此)
但我找不到不均匀照明之间的很大相似之处 图片。我刚刚发现有一些像素值很低并且 一些像素在直方图分析中具有很高的价值。
基本上我的感觉是,如果将一些阈值设置为低阈值并找出有多少像素小于低阈值并设置一些高阈值以找出有多少像素大于该阈值。通过像素数,我们可以得出结论来检测图像中不均匀的闪电条件吗?这里我们需要最终确定两个阈值和像素数的百分比才能得出结论。
def show_hist_v(img_path):
img = cv2.imread(img_path)
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv_img)
histr =cv2.calcHist(v, [0], None, [255],[0,255])
plt.plot(histr)
plt.show()
low_threshold =np.count_nonzero(v < 50)
high_threshold =np.count_nonzero(v >200)
total_pixels = img.shape[0]* img.shape[1]
percenet_low =low_threshold/total_pixels*100
percenet_high =high_threshold/total_pixels*100
print("Total Pixels - {}\n Pixels More than 200 - {} \n Pixels Less than 50 - {} \n Pixels percentage more than 200 - {} \n Pixel spercentage less than 50 - {} \n".format(total_pixels,high_threshold,low_threshold,percenet_low,percenet_high))
return total_pixels,high_threshold,low_threshold,percenet_low,percenet_high
那么有人可以改进我的初始方法或提供比这种方法更好的方法来检测一般情况下图像中的不均匀照明吗?
另外,我尝试了感知亮度而不是值通道,因为值通道采用 (b,g,r) 值的最大值,所以我认为感知亮度是一个不错的选择
def get_perceive_brightness( float_img):
float_img = np.float64(float_img) # unit8 will make overflow
b, g, r = cv2.split(float_img)
float_brightness = np.sqrt(
(0.241 * (r ** 2)) + (0.691 * (g ** 2)) + (0.068 * (b ** 2)))
brightness_channel = np.uint8(np.absolute(float_brightness))
return brightness_channel
def show_hist_v(img_path):
img = cv2.imread(img_path)
v = get_perceive_brightness(img)
histr =cv2.calcHist(v, [0], None, [255],[0,255])
plt.plot(histr)
plt.show()
low_threshold =np.count_nonzero(v < 50)
high_threshold =np.count_nonzero(v >200)
total_pixels = img.shape[0]* img.shape[1]
percenet_low =low_threshold/total_pixels*100
percenet_high =high_threshold/total_pixels*100
print("Total Pixels - {}\n Pixels More than 200 - {} \n Pixels Less than 50 - {} \n Pixels percentage more than 200 - {} \n Pixel spercentage less than 50 - {} \n".format(total_pixels,high_threshold,low_threshold,percenet_low,percenet_high))
return total_pixels,high_threshold,low_threshold,percenet_low,percenet_high
感知亮度通道的直方图分析
正如 Ahmet 建议的那样。
def get_percentage_of_binary_pixels(img=None, img_path=None):
if img is None:
if img_path is not None:
gray_img = cv2.imread(img_path, 0)
else:
return "No img or img_path"
else:
print(img.shape)
if len(img.shape) > 2:
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray_img = img
h, w = gray_img.shape
guassian_blur = cv2.GaussianBlur(gray_img, (5, 5), 0)
thresh_value, otsu_img = cv2.threshold(guassian_blur, 0, 255,
cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imwrite("binary/{}".format(img_path.split('/')[-1]), otsu_img)
black_pixels = np.count_nonzero(otsu_img == 0)
# white_pixels = np.count_nonzero(otsu_img == 255)
black_pixels_percentage = black_pixels / (h * w) * 100
# white_pixels_percentage = white_pixels / (h * w) * 100
return black_pixels_percentage
当我们通过大津二值化获得超过 35% 的黑色像素百分比时,我们可以检测到 80% 左右的不均匀照明图像。当光照发生在图像的小区域时,检测失败。
提前致谢
【问题讨论】:
-
我也尝试过感知亮度而不是价值渠道
-
您的目标是检测或纠正不均匀的照明?
-
请参阅Enhancing dynamic range and normalizing illumination 了解有关此事的一些想法。
-
@rcvaram 它只是基础知识......我将该算法演变为基于网格的插值,其中图像被分成均匀的网格,每个网格都像这样计算 +/- 毛刺之间的一些插值(也可以处理眩光)。 .. 我想我也发布了它,但要找到它需要一些时间,因为我得到了太多答案,而且搜索引擎也不是那么好
-
@rcvaram heh 比平时更快地找到它(通过搜索函数头源代码):) 见 OpenCV for OCR: How to compute thresholding levels for gray image OCR 它的函数
normalize
标签: python algorithm opencv image-processing computer-vision