[关闭]
@StarSky 2017-04-13T12:31:18.000000Z 字数 5255 阅读 2955

文字识别:基于灰度图像 vs 自适应二值化算法优化

工作日记


两条路:对灰度图像的识别,或者对二值化算法的优化。
各有利弊,识别灰度图像现在的思路是根据不同的光照环境/图片压缩噪点,模拟现实环境,增大样本量;图片二值化优化目的则是将不同条件下的图像归一成优质可识别的二值化结果。

灰度图像生成的几个点:
1. 文字数量同字间距的关系
2. 对比度及明暗度[1](区间调整)
3. 光斑/阴影模拟
4. 图片模糊程度(区间调整)
5. 背景图案获取

同样的二值化的过程也就是把上文的几个要点归约的过程。

中间试过几次,调整到最终感觉可以的流程(没加光斑):
1. 获取底纹图片,确定字体(经比较选用华文细黑)
2. 从底纹图中随机选取
3. 区间内随机取值调整底纹图亮度(区间[0.3, 1.0]最佳)
4. 获得调整后图片到评价颜色值[2] [3] [4] [5]
5. 根据上值,计算合适的字体颜色值码(调试得系数0.3最佳)
6. 叠加背景与字体水印[6]
7. 区间内随机取值加高斯模糊[7](区间[0.5, 1.0]最佳)
8. 转换成灰度图并保存

关于步骤1,本来想用两张图片相叠用lighter函数[8]抹去黑色的文字,后来发现不太好使,强行ps了一些底纹图跟已剪切的图片叠取了一些底纹图。
文字的叠加用的加水印的方法能使文字与背景有一点混叠噪点,非常漂亮非常自然,是我想要的东西2333。
然后偶尔发现了一篇文章。。噫。。Python图像压缩和增强手写笔记感觉可以用来优化文字识别原图像的图像质量啊,其实图像压缩与增强是很有意思的。
关于第三点,思路感觉还是可以用两张图片运算去做。

调整效果过程如下:
段培付_0bdeaf75-1ff8-11e7-bf5f-f45c89c42597.jpg-1.6kB
悄夕_0ac4c4e6-1ff8-11e7-b2e1-f45c89c42597.jpg-1.6kB
噫,感觉模拟出来的图像还是跟身份证差太多,字体感觉有问题。
戴熙秋_0b258382-1ff8-11e7-bfe1-f45c89c42597.jpg-1.7kB
段培付_0bdeaf75-1ff8-11e7-bf5f-f45c89c42597.jpg-1.3kB
悄夕_0ac4c4e6-1ff8-11e7-b2e1-f45c89c42597.jpg-1.2kB
调整了背景与字体颜色赋值方案,更改高斯模糊半径为1
test.jpg-1kB
更改高斯模糊半径为0.5(但其实加完模糊之后底纹不太清晰了,不太满意,其实有个思路是选中字体空间,区域高斯模糊,但是。。。字体空间怎么选,搜不到不做了23333)
test.jpg-1.3kB
test2.jpg-1.1kB

身份证灰度图原图:
安德尧_jd_65d32b9de6ef4.jpg-1.5kB
艾博_13354085065_p.jpg-1.3kB

以上就是python模拟“自然环境”下生成身份证姓名部分图片的全部过程,自适应二值化算法可能改篇写了。
就像我之前跟一个朋友说过的,我不太觉得自己是个正规的程序员,需要的东西都是从网上搜索的,离搜索引擎啥都干不了,就是个搜索器合成器23333。嘛,用完代码回头再回忆都用到了了哪些博文也是个有趣的过程23333。
哦对了,组长说我生成的图效果不错23333

再次感谢 google 感谢 lantern

  1. # coding=utf-8
  2. import os
  3. import random
  4. from uuid import uuid1
  5. import ImageFilter
  6. import time
  7. from PIL import Image
  8. import ImageDraw
  9. import ImageEnhance
  10. import ImageFont
  11. import colorsys
  12. from PIL import Image, ImageFilter
  13. class MyGaussianBlur(ImageFilter.Filter):
  14. name = "GaussianBlur"
  15. def __init__(self, radius=2, bounds=None):
  16. self.radius = radius
  17. self.bounds = bounds
  18. def filter(self, image):
  19. if self.bounds:
  20. clips = image.crop(self.bounds).gaussian_blur(self.radius)
  21. image.paste(clips, self.bounds)
  22. return image
  23. else:
  24. return image.gaussian_blur(self.radius)
  25. '''
  26. 添加一个文字水印,png图层合并方式为身份证底纹印姓名
  27. '''
  28. # FONT = ['/Library/Fonts/Lantinghei.ttc',
  29. # '/System/Library/Fonts/STHeiti Light.ttc',
  30. # '/System/Library/Fonts/STHeiti Medium.ttc',
  31. # '/System/Library/Fonts/STHeiti Thin.ttc',
  32. # '/System/Library/Fonts/STHeiti UltraLight.ttc',
  33. # '/Library/Fonts/华文黑体.ttf',
  34. # '/Library/Fonts/华文细黑.ttf',
  35. # '/Library/Fonts/AdobeHeitiStd-Regular.otf',
  36. # ]
  37. FONT = ['/Library/Fonts/华文细黑.ttf']
  38. BACK_IMG = []
  39. def get_back_list(back_dir):
  40. for file_name in os.listdir(back_dir):
  41. file_path = os.path.join(back_dir, file_name)
  42. BACK_IMG.append(file_path)
  43. def text_watermark(back_dir, text, out_dir, out_grey_dir, angle=0):
  44. get_back_list(back_dir)
  45. img = Image.open(random.choice(BACK_IMG))
  46. # opacity = random.uniform(0.6, 1.7) # 原字体亮度调整系数
  47. # 图片亮度调整系数
  48. opacity = random.uniform(0.3, 1.0)
  49. watermark = Image.new('RGBA', img.size)
  50. size = 26
  51. font_path = random.choice(FONT)
  52. n_font = ImageFont.truetype(font_path, size)
  53. n_width, n_height = n_font.getsize(text)
  54. text_box = min(watermark.size[0], watermark.size[1])
  55. while n_width + n_height < text_box:
  56. size += 2
  57. n_font = ImageFont.truetype(FONT, size=size)
  58. n_width, n_height = n_font.getsize(text) # 文字逐渐放大,但是要小于图片的宽高最小值
  59. text_width = 8
  60. text_height = (watermark.size[1] - n_height) / 2
  61. draw = ImageDraw.Draw(watermark, 'RGBA') # 在水印层加画笔
  62. # 调整背景色明暗度
  63. img = ImageEnhance.Brightness(img).enhance(opacity)
  64. # 获得一个更适应背景色的字体色
  65. back_color, text_color = get_dominant_color(img, 0.3)
  66. if len(text) > 2:
  67. draw.text((text_width, text_height),
  68. text, font=n_font, fill=text_color)
  69. else:
  70. # 对双字名的字间距调整
  71. draw.text((text_width, text_height),
  72. text[0], font=n_font, fill=text_color)
  73. draw.text((text_width + 42, text_height),
  74. text[1], font=n_font, fill=text_color)
  75. watermark = watermark.rotate(angle, Image.BICUBIC)
  76. alpha = watermark.split()[3]
  77. # alpha = ImageEnhance.Brightness(alpha).enhance(opacity)
  78. watermark.putalpha(alpha)
  79. # file_name = text + font_path.decode('utf-8').split('/')[-1] + '.jpg'
  80. file_name = text + '_' + str(opacity) + text_color + back_color + '_' + str(uuid1()) + '.jpg'
  81. out_file_path = os.path.join(out_dir, file_name)
  82. # Image.composite(watermark, img, watermark).filter(ImageFilter.BLUR).save(out_file_path, 'JPEG')
  83. Image.composite(watermark, img, watermark).filter(MyGaussianBlur(radius=0.5)).save(out_file_path, 'JPEG')
  84. # img = Image.composite(watermark, img, watermark)
  85. # img.save(out_file_path, 'JPEG')
  86. out_grey_path = os.path.join(out_grey_dir, file_name)
  87. img_to_grey(out_file_path, out_grey_path)
  88. print u"文字水印成功"
  89. def rgb_to_hex(rgb):
  90. return '#%02x%02x%02x' % rgb
  91. def get_dominant_color(image, adaptive):
  92. # 颜色模式转换,以便输出rgb颜色值
  93. image = image.convert('RGBA')
  94. # 生成缩略图,减少计算量
  95. image.thumbnail((200, 200))
  96. max_score = None
  97. dominant_color = None
  98. for count, (r, g, b, a) in image.getcolors(image.size[0] * image.size[1]):
  99. # 跳过纯黑色
  100. if a == 0:
  101. continue
  102. saturation = colorsys.rgb_to_hsv(r / 255.0, g / 255.0, b / 255.0)[1]
  103. y = min(abs(r * 2104 + g * 4130 + b * 802 + 4096 + 131072) >> 13, 235)
  104. y = (y - 16.0) / (235 - 16)
  105. # 忽略高亮色
  106. if y > 0.9:
  107. continue
  108. # Calculate the score, preferring highly saturated colors.
  109. # Add 0.1 to the saturation so we don't completely ignore grayscale
  110. # colors by multiplying the count by zero, but still give them a low
  111. # weight.
  112. score = (saturation + 0.1) * count
  113. if score > max_score:
  114. max_score = score
  115. # adaptive是个环境适应的参数, 暂定的0.3, 先试试看23333
  116. dominant_color = (r, g, b)
  117. dominant_color_adapt = (r * adaptive, g * adaptive, b * adaptive)
  118. return rgb_to_hex(dominant_color), rgb_to_hex(dominant_color_adapt)
  119. def img_to_grey(file_path, grey_path):
  120. im = Image.open(file_path).convert('L')
  121. # im.show()
  122. # time.sleep(5)
  123. im.save(grey_path)
  124. if __name__ == '__main__':
  125. back_dir = '/Users/saber/Documents/Py_test_file/back_for_use'
  126. out_dir = '/Users/saber/Documents/Py_test_file/out_img_dir'
  127. out_grey_path = '/Users/saber/Documents/Py_test_file/out_grey_dir/test.jpg'
  128. img_file = '/Users/saber/Documents/Py_test_file/out_img_dir/华文细黑.ttf.jpg'
  129. # text_watermark(back_dir, u'安鹏鹏', out_dir, out_grey_dir)
  130. # img_to_grey(img_file, out_grey_path)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注