You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自动车牌识别(ALPR)系统中如何去除图像黑边优化OCR识别

解决ALPR二值化图像黑边问题的实用方案

嘿,我在做自动车牌识别系统的时候也遇到过几乎一模一样的问题——二值化后的黑边会让OCR把边缘当成字符的一部分,或者直接干扰字符区域的定位。结合你提到的图像质量水平,我给你几个实际测试过有效的解决思路:


方法1:基于行/列像素统计的快速裁剪(最适合你当前的图像情况)

如果黑边是均匀分布在图像四周的,这种方法高效又精准,核心是通过统计白色像素(字符)的分布范围来定位有效区域:

  1. 先读取二值化图像,统计每行的白色像素数量:
    import cv2
    import numpy as np
    
    # 读取二值化图像(0表示灰度模式)
    img = cv2.imread('binary_plate.jpg', 0)
    img_h, img_w = img.shape
    
  2. 筛选出包含字符的行范围:
    # 统计每行的白色像素数
    row_sum = np.sum(img == 255, axis=1)
    # 设置阈值:只保留白色像素数超过图像宽度5%的行(过滤噪声)
    row_threshold = img_w * 0.05
    # 找到第一个和最后一个符合条件的行
    top_row = np.argmax(row_sum > row_threshold)
    bottom_row = img_h - np.argmax(row_sum[::-1] > row_threshold) - 1
    
  3. 同理筛选出包含字符的列范围:
    col_sum = np.sum(img == 255, axis=0)
    col_threshold = img_h * 0.05
    left_col = np.argmax(col_sum > col_threshold)
    right_col = img_w - np.argmax(col_sum[::-1] > col_threshold) - 1
    
  4. 直接裁剪到有效区域:
    clean_plate = img[top_row:bottom_row, left_col:right_col]
    

方法2:基于轮廓检测的字符区域提取

如果黑边和字符边缘有粘连,或者存在局部不规则黑边,可以用轮廓检测筛选出符合字符尺寸的区域:

  1. 先做形态学开操作去除小噪声:
    kernel = np.ones((3,3), np.uint8)
    # 开操作:先腐蚀再膨胀,弱化细黑边+去除噪声点
    cleaned_img = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
    
  2. 提取轮廓并筛选符合字符特征的轮廓:
    contours, _ = cv2.findContours(cleaned_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    valid_contours = []
    # 车牌字符高度一般占图像高度的60%-95%,根据实际情况调整
    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        if h > img_h * 0.6 and h < img_h * 0.95:
            valid_contours.append(cnt)
    
  3. 生成掩码并提取干净的字符区域:
    mask = np.zeros_like(cleaned_img)
    cv2.drawContours(mask, valid_contours, -1, 255, thickness=cv2.FILLED)
    # 用掩码过滤黑边
    result = cv2.bitwise_and(cleaned_img, mask)
    # 裁剪到所有有效轮廓的最小外接矩形
    x_min = min([cv2.boundingRect(cnt)[0] for cnt in valid_contours])
    y_min = min([cv2.boundingRect(cnt)[1] for cnt in valid_contours])
    x_max = max([cv2.boundingRect(cnt)[0]+cv2.boundingRect(cnt)[2] for cnt in valid_contours])
    y_max = max([cv2.boundingRect(cnt)[1]+cv2.boundingRect(cnt)[3] for cnt in valid_contours])
    clean_plate = result[y_min:y_max, x_min:x_max]
    

方法3:自适应阈值二次过滤

如果黑边的灰度和字符边缘接近,可以用自适应阈值强化字符和黑边的区分度:

# 自适应高斯阈值:只保留亮度较高的字符区域,过滤弱黑边
adaptive_img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
# 用小核膨胀补全字符缺口
kernel = np.ones((2,2), np.uint8)
clean_plate = cv2.dilate(adaptive_img, kernel, iterations=1)

你可以先试试方法1,它最适配你当前的图像质量;如果黑边有粘连情况,再换方法2调整参数就行。

内容的提问来源于stack exchange,提问作者Luis Ramon Ramirez Rodriguez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:25:27