PaddleOCR 数据增强预处理

发布于:2025-08-10 ⋅ 阅读:(23) ⋅ 点赞:(0)

介绍

ocr 检测和识别模型训练完成之后,通过 api 脚本调用测试,发现文字识别的性能很差。

===== 准确率统计 ====================
类别 01: 260/273 = 95.24%
类别 02: 95/270  = 35.19%
类别 03: 280/374 = 74.87%
类别 04: 258/725 = 35.59%
类别 05: 205/343 = 59.77%
类别 06: 55/145  = 37.93%
类别 07: 97/319  = 30.41%
类别 08: 116/147 = 78.91%
类别 09: 94/130  = 72.31%
类别 10: 133/159 = 83.65%

目标类别总体准确率: 1593/2885 = 55.22%

但是用官方的 predict_system,py 脚本调用模型却没问题,准确率很高。立即想到是不是因为我在 api 调用过程中没有做数据增强预处理,于是决定对输入图像做图像增强。

一、对比度和亮度处理

cv2.convertScaleAbs()是 OpenCV 中用于图像对比度和亮度调整的函数,特别适合用于 OCR 预处理阶段增强文本的可读性。函数原型:

cv2.convertScaleAbs(src, alpha=1.0, beta=0.0)
  • 输入​​:
    src:输入图像,NumPy 数组,通常是 uint8 类型。
    alpha:对比度调节系数,乘数。
    beta:亮度调节系数,偏移量。
  • ​​输出​​:
    返回一个 uint8 类型的图像,所有像素值会被裁剪到 [0, 255] 范围内。

二、灰度化 + CLAHE

cv2.cvtColor()是 OpenCV 中用于颜色空间转换的核心函数,cv2.COLOR_BGR2GRAY是其最常用的转换,作用是将 BGR 图像转换成灰度图像。CLAHE 需要在单通道图像上操作,所以可以将灰度化后的灰度图像交给 CLAHE 处理。

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
enhanced = clahe.apply(gray)
image = cv2.cvtColor(enhanced, cv2.COLOR_GRAY2BGR)

cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8)) 创建了一个 CLAHE 对象,clipLimit 为对比度限制阈值,tileGridSize 为图像分块大小。enhanced = clahe.apply(gray) 将图像划分为 8x8 的网格,每个网格独立计算直方图,根据 clipLimit 裁剪并重新分配像素值,双线性插值消除块间边界。最后,image = cv2.cvtColor(enhanced, cv2.COLOR_GRAY2BGR) 转回 BGR 格式。

三、非锐化掩模​ / 高斯模糊

# 非锐化掩模(Unsharp Mask)
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
sharpened = cv2.filter2D(image, -1, kernel)

不同于锐化掩模使用高通滤波,原理是高频分量增强。强化中心像素,弱化周围像素​,核中心值越大锐化越强。适合需要快速强锐化的场景,需注意噪声控制。

# 高斯核锐化
blurred = cv2.GaussianBlur(image, (0,0), 3)
sharpened = cv2.addWeighted(image, 1.5, blurred, -0.5, 0)

原理是用高斯核(σ=3)模糊原图,原图×1.5 - 模糊图×0.5,适合自然图像和精细调整。

四、动态二值化

# 自适应阈值(推荐高斯加权)
binary = cv2.adaptiveThreshold(
    cv2.cvtColor(image, cv2.COLOR_BGR2GRAY),
    255,
    cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
    cv2.THRESH_BINARY_INV,
    blockSize=21,
    C=8
)
image = cv2.cvtColor(binary, cv2.COLOR_GRAY2BGR)

用于处理光照不均图像,相比全局阈值能更好保留弱文本。

五、形态学处理

# 闭运算(先膨胀后腐蚀)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
morphed = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)

​​作用:

  • 连接相邻字符​​:如 “1” 断裂成两个部分时。
  • ​​填充内部空隙​​:如 “8” 中间断裂。
  • 平滑文本边缘​​:去除锯齿状边缘。

六、频域增强

# 傅里叶变换去噪
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
dft = cv2.dft(np.float32(gray), flags=cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

# 创建带阻滤波器(去除特定频率噪声)
rows, cols = gray.shape
crow, ccol = rows//2, cols//2
mask = np.ones((rows, cols, 2), np.uint8)
r = 30  # 阻带半径
center = [crow, ccol]
x, y = np.ogrid[:rows, :cols]
mask_area = (x - center[0])**2 + (y - center[1])**2 <= r*r
mask[mask_area] = 0

# 反变换
f_ishift = np.fft.ifftshift(dft_shift * mask)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])
img_back = cv2.normalize(img_back, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8)

实践

只做了对比度处理就发现效果很好了,image = cv2.convertScaleAbs(image, alpha=1.71, beta=0),发现在 alpha = 1.71 的时候准确率最高。


网站公告

今日签到

点亮在社区的每一天
去签到