如何用OpenCV将图像中除车牌字符外的区域置为黑色?
实现图像仅保留车牌字符其余置黑的方案
核心问题拆解
你的需求分为两个关键环节:定位图像中的车牌区域,以及提取车牌内的字符并将其余区域置黑。以下是分步实现方案:
一、车牌区域定位
当前你的代码直接处理裁剪后的车牌,实际需要先从完整图像中定位车牌边界框。这里提供两种可行方案:
1. 传统轮廓检测法(适合规则车牌)
针对国内蓝牌/黄牌这类形状规则的车牌,通过图像预处理+轮廓筛选实现定位:
- 灰度化→边缘检测→形态学闭操作连接边缘
- 筛选宽高比在2.5~4之间的轮廓(符合车牌典型比例)
2. 预训练模型检测(鲁棒性更强)
复杂场景(如倾斜、模糊车牌)建议用YOLOv8、EasyOCR等工具,直接调用预训练的车牌检测模型获取边界框,无需手动调参。
二、完整代码实现
整合车牌定位、字符提取、结果合成的完整流程,复用你提供的预处理逻辑:
import cv2 as opencv import numpy as np # 检测车牌边界框(传统轮廓法) def detect_license_plate(image): gray = opencv.cvtColor(image, opencv.COLOR_BGR2GRAY) edges = opencv.Canny(gray, 50, 150) # 形态学闭操作连接边缘 kernel = opencv.getStructuringElement(opencv.MORPH_RECT, (10, 3)) closed = opencv.morphologyEx(edges, opencv.MORPH_CLOSE, kernel) # 提取外部轮廓 contours, _ = opencv.findContours(closed.copy(), opencv.RETR_EXTERNAL, opencv.CHAIN_APPROX_SIMPLE) # 筛选符合车牌宽高比的轮廓 plate_rect = None for cnt in contours: x, y, w, h = opencv.boundingRect(cnt) aspect_ratio = w / float(h) if 2.5 <= aspect_ratio <= 4: plate_rect = (x, y, w, h) break return plate_rect # 处理车牌区域,生成字符掩码(白色为字符,黑色为背景) def process_plate(plate_img): # 锐化处理 sharpening_kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]]) sharpened = opencv.filter2D(plate_img, -1, sharpening_kernel) # CLAHE增强对比度 lab = opencv.cvtColor(sharpened, opencv.COLOR_BGR2LAB) l, a, b = opencv.split(lab) clahe = opencv.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8)) limg = opencv.merge([clahe.apply(l), a, b]) enhanced = opencv.cvtColor(limg, opencv.COLOR_LAB2BGR) # 灰度化、模糊、二值化 gray = opencv.cvtColor(enhanced, opencv.COLOR_BGR2GRAY) blurred = opencv.GaussianBlur(gray, (3, 3), 0) _, thresholded = opencv.threshold(blurred, 0, 255, opencv.THRESH_BINARY + opencv.THRESH_OTSU) # 形态学清理 morph_kernel = opencv.getStructuringElement(opencv.MORPH_RECT, (3, 3)) opened = opencv.morphologyEx(thresholded, opencv.MORPH_OPEN, morph_kernel, iterations=1) dilate_kernel = opencv.getStructuringElement(opencv.MORPH_RECT, (5, 5)) dilated = opencv.dilate(opened, dilate_kernel, iterations=1) # 反转得到字符掩码 char_mask = opencv.bitwise_not(dilated) return char_mask # 主执行流程 if __name__ == "__main__": original_img = opencv.imread('image.png') if original_img is None: print("图像加载失败,请检查路径") exit() # 定位车牌 plate_rect = detect_license_plate(original_img) if not plate_rect: print("未检测到车牌区域") exit() x, y, w, h = plate_rect # 裁剪并处理车牌 plate_area = original_img[y:y+h, x:x+w] char_mask = process_plate(plate_area) # 创建全黑结果图,仅保留车牌字符为白色 result_img = np.zeros_like(original_img) char_mask_3ch = opencv.cvtColor(char_mask, opencv.COLOR_GRAY2BGR) # 将掩码中白色区域(字符)赋值为白色,其余为黑色 result_img[y:y+h, x:x+w] = np.where(char_mask_3ch == 255, (255,255,255), (0,0,0)) # 展示结果 opencv.imshow('仅保留车牌字符的结果', result_img) opencv.waitKey(0) opencv.destroyAllWindows()
关键逻辑说明
- 车牌定位:通过轮廓筛选得到车牌的x,y,w,h坐标,后续裁剪出该区域
- 字符掩码:经过预处理得到二值掩码,白色部分对应车牌字符
- 结果合成:先创建全黑图像,再将车牌区域内的字符部分替换为白色,其余区域保持黑色
示例图像

内容的提问来源于stack exchange,提问作者user20983853
相关产品推荐
相关产品推荐

