image_preprocess.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. 图像预处理工具
  5. 用于提高 OCR 识别准确率
  6. """
  7. import cv2
  8. import numpy as np
  9. def preprocess_id_card_image(image_path, output_path=None):
  10. """
  11. 预处理身份证图片以提高 OCR 识别率
  12. 参数:
  13. image_path: 输入图片路径
  14. output_path: 输出图片路径(可选,如果提供则保存预处理后的图片)
  15. 返回:
  16. 预处理后的图片(numpy array)
  17. """
  18. # 读取图片
  19. img = cv2.imread(image_path)
  20. if img is None:
  21. raise ValueError(f"无法读取图片: {image_path}")
  22. # 1. 转为灰度图
  23. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  24. # 2. 降噪
  25. denoised = cv2.fastNlMeansDenoising(gray, None, 10, 7, 21)
  26. # 3. 自适应二值化
  27. binary = cv2.adaptiveThreshold(
  28. denoised, 255,
  29. cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
  30. cv2.THRESH_BINARY,
  31. 11, 2
  32. )
  33. # 4. 形态学操作去除噪点
  34. kernel = np.ones((2, 2), np.uint8)
  35. morph = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)
  36. # 5. 锐化(可选)
  37. kernel_sharpen = np.array([
  38. [-1, -1, -1],
  39. [-1, 9, -1],
  40. [-1, -1, -1]
  41. ])
  42. sharpened = cv2.filter2D(morph, -1, kernel_sharpen)
  43. # 保存预处理后的图片
  44. if output_path:
  45. cv2.imwrite(output_path, sharpened)
  46. return sharpened
  47. def enhance_image_quality(image_path):
  48. """
  49. 增强图片质量(对比度、亮度等)
  50. 参数:
  51. image_path: 输入图片路径
  52. 返回:
  53. 增强后的图片(numpy array)
  54. """
  55. img = cv2.imread(image_path)
  56. if img is None:
  57. raise ValueError(f"无法读取图片: {image_path}")
  58. # 转换到 LAB 色彩空间
  59. lab = cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
  60. l, a, b = cv2.split(lab)
  61. # 对 L 通道进行直方图均衡化
  62. clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
  63. cl = clahe.apply(l)
  64. # 合并通道
  65. enhanced_lab = cv2.merge((cl, a, b))
  66. enhanced = cv2.cvtColor(enhanced_lab, cv2.COLOR_LAB2BGR)
  67. return enhanced
  68. def auto_rotate_image(image_path):
  69. """
  70. 自动旋转图片使文字方向正确
  71. 参数:
  72. image_path: 输入图片路径
  73. 返回:
  74. 旋转后的图片(numpy array)
  75. """
  76. img = cv2.imread(image_path)
  77. if img is None:
  78. raise ValueError(f"无法读取图片: {image_path}")
  79. # 转为灰度图
  80. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  81. # 边缘检测
  82. edges = cv2.Canny(gray, 50, 150, apertureSize=3)
  83. # 霍夫变换检测直线
  84. lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)
  85. if lines is not None:
  86. # 计算平均角度
  87. angles = []
  88. for rho, theta in lines[:, 0]:
  89. angle = np.rad2deg(theta)
  90. angles.append(angle)
  91. # 获取主要角度
  92. median_angle = np.median(angles)
  93. # 旋转图片
  94. if abs(median_angle - 90) < 45:
  95. rotation_angle = median_angle - 90
  96. else:
  97. rotation_angle = median_angle
  98. # 执行旋转
  99. (h, w) = img.shape[:2]
  100. center = (w // 2, h // 2)
  101. M = cv2.getRotationMatrix2D(center, rotation_angle, 1.0)
  102. rotated = cv2.warpAffine(
  103. img, M, (w, h),
  104. flags=cv2.INTER_CUBIC,
  105. borderMode=cv2.BORDER_REPLICATE
  106. )
  107. return rotated
  108. return img
  109. def resize_for_ocr(image_path, target_width=1500):
  110. """
  111. 调整图片尺寸以适合 OCR
  112. 参数:
  113. image_path: 输入图片路径
  114. target_width: 目标宽度(像素)
  115. 返回:
  116. 调整大小后的图片(numpy array)
  117. """
  118. img = cv2.imread(image_path)
  119. if img is None:
  120. raise ValueError(f"无法读取图片: {image_path}")
  121. # 获取原始尺寸
  122. h, w = img.shape[:2]
  123. # 如果宽度小于目标宽度,则放大
  124. if w < target_width:
  125. ratio = target_width / w
  126. new_width = target_width
  127. new_height = int(h * ratio)
  128. resized = cv2.resize(
  129. img, (new_width, new_height),
  130. interpolation=cv2.INTER_CUBIC
  131. )
  132. return resized
  133. # 如果宽度大于目标宽度,则缩小
  134. elif w > target_width * 1.5:
  135. ratio = target_width / w
  136. new_width = target_width
  137. new_height = int(h * ratio)
  138. resized = cv2.resize(
  139. img, (new_width, new_height),
  140. interpolation=cv2.INTER_AREA
  141. )
  142. return resized
  143. return img
  144. # 示例用法
  145. if __name__ == "__main__":
  146. import sys
  147. if len(sys.argv) < 2:
  148. print("使用方法: python image_preprocess.py <图片路径>")
  149. sys.exit(1)
  150. image_path = sys.argv[1]
  151. # 预处理
  152. processed = preprocess_id_card_image(image_path, "processed.jpg")
  153. print("预处理完成,保存为 processed.jpg")
  154. # 增强
  155. enhanced = enhance_image_quality(image_path)
  156. cv2.imwrite("enhanced.jpg", enhanced)
  157. print("质量增强完成,保存为 enhanced.jpg")
  158. # 调整大小
  159. resized = resize_for_ocr(image_path)
  160. cv2.imwrite("resized.jpg", resized)
  161. print("尺寸调整完成,保存为 resized.jpg")