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

车牌字符分割时出现额外轮廓的技术求助

车牌字符分割:解决形态学操作产生的额外轮廓问题

针对车牌字符分割中形态学操作产生额外轮廓(左侧片段、右侧线条)的问题,结合车牌字符的几何特征与结构规则,可通过降噪+特征过滤+结构兜底的组合策略优化处理流程:

改进后的处理代码

import cv2
import numpy as np

# 假设ex_plate是透视变换后的灰度车牌图像
mask = cv2.adaptiveThreshold(
    ex_plate, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 17, 5
)
# 前置高斯模糊:提前过滤局部噪点,减少阈值后的无效轮廓
mask = cv2.GaussianBlur(mask, (3, 3), 0)
mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, np.ones((3, 3)))

# 微调腐蚀核:根据字符宽度调整,避免过度腐蚀有效字符
marker = cv2.erode(mask, cv2.getStructuringElement(cv2.MORPH_RECT, (3, 18)))
obr = open_by_reconstruction(marker, mask)

# 自定义边界清除:只清除边缘5像素内的轮廓,避免误删靠近边缘的首字符
def custom_clear_border(img, border_width=5):
    h, w = img.shape
    img[:border_width, :] = 0
    img[-border_width:, :] = 0
    img[:, :border_width] = 0
    img[:, -border_width:] = 0
    return img

obr = custom_clear_border(obr)
obr = cv2.morphologyEx(obr, cv2.MORPH_CLOSE, np.ones((3, 3)))
obr = hole_filler(obr)

# 核心步骤:轮廓检测+几何特征过滤
contours, _ = cv2.findContours(obr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 根据国内车牌字符特征定义过滤阈值(可根据实际场景调整)
plate_h = obr.shape[0]
min_char_h = int(plate_h * 0.6)
max_char_h = plate_h
min_char_w = int(plate_h * 0.3)
max_char_w = int(plate_h * 0.6)
min_char_area = min_char_h * min_char_w * 0.5

filtered_contours = []
for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt)
    aspect_ratio = w / h
    area = cv2.contourArea(cnt)
    # 过滤不符合字符宽高比、面积、高度的轮廓
    if (min_char_h <= h <= max_char_h and
        min_char_w <= w <= max_char_w and
        0.3 <= aspect_ratio <= 0.6 and
        area >= min_char_area):
        filtered_contours.append(cnt)

# 按x坐标排序,保证字符顺序从左到右
filtered_contours = sorted(filtered_contours, key=lambda c: cv2.boundingRect(c)[0])

# 提取字符ROI,适当扩展边界避免裁剪
char_rois = []
for cnt in filtered_contours:
    x, y, w, h = cv2.boundingRect(cnt)
    roi = obr[max(0, y-2):min(plate_h, y+h+2), max(0, x-2):min(obr.shape[1], x+w+2)]
    char_rois.append(roi)

# 兜底策略:若轮廓数量不符合(如非7个),按固定区域分割
if len(char_rois) != 7:
    plate_w = obr.shape[1]
    seg_w = plate_w // 7
    char_rois = []
    for i in range(7):
        start_x = i * seg_w
        end_x = plate_w if i == 6 else (i+1)*seg_w
        segment = obr[:, start_x:end_x]
        seg_contours, _ = cv2.findContours(segment, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        if seg_contours:
            # 取区域内面积最大的轮廓作为字符
            max_cnt = max(seg_contours, key=cv2.contourArea)
            x, y, w, h = cv2.boundingRect(max_cnt)
            roi = segment[y:y+h, x:x+w]
            char_rois.append(roi)

关键优化点说明

  1. 前置高斯模糊:在阈值处理前加入模糊,直接减少局部噪点产生的无效轮廓,降低后续形态学操作的压力。
  2. 自定义边界清除:替换默认clear_border,只清除边缘少量像素内的轮廓,避免误删车牌首字符。
  3. 几何特征过滤:利用车牌字符固定的宽高比(0.3-0.6)、高度占比(60%-100%车牌高度)、面积阈值,精准过滤左侧小片段和右侧长线条类干扰。
  4. 结构兜底策略:当轮廓检测数量不符合车牌字符数时,强制按水平方向分割7个区域,每个区域取最大轮廓,保证分割结果的完整性。

额外建议

  • 若仍有干扰,可尝试Otsu全局阈值+局部自适应阈值的组合,提升复杂光照下的二值化效果。
  • 加入直方图均衡化(cv2.equalizeHist)增强字符与背景的对比度,降低分割难度。

内容的提问来源于stack exchange,提问作者m.marian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 13:55:23