使用OpenCV去除图像背景并为身份证绘制bounding box的实现问题
身份证识别场景代码调整方案
完整可运行代码
import cv2 import numpy as np import matplotlib.pyplot as plt # 读取图像 image = cv2.imread('/content/f6644ae09eb9acfc6a71f01115f917f9.jpg') result = image.copy() gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 阈值分割(原有逻辑保留) thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # 找轮廓(原有逻辑保留) cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) cnts = cnts[0] if len(cnts) == 2 else cnts[1] # 新增:按轮廓面积从大到小排序,取面积最大的轮廓即为身份证区域 cnts = sorted(cnts, key=cv2.contourArea, reverse=True) id_card_cnt = cnts[0] # 新增:计算身份证区域的bounding box并绘制 x, y, w, h = cv2.boundingRect(id_card_cnt) cv2.rectangle(result, (x, y), (x + w, y + h), (0, 0, 255), 2) # 蓝色框,线宽2 # 需求1:裁剪出身份证区域 crop_id_card = result[y:y+h, x:x+w] # 需求1另一种实现:保留原图尺寸,去除背景(背景替换为白色) mask = np.zeros(image.shape[:2], dtype=np.uint8) cv2.drawContours(mask, [id_card_cnt], -1, 255, -1) # 填充身份证区域为白色掩码 id_without_background = np.full_like(image, 255) # 生成纯白背景图 id_without_background[mask == 255] = image[mask == 255] # 只保留身份证区域像素 # 结果显示(注意matplotlib需要转BGR为RGB) plt.subplot(131) plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)) plt.title('带bounding box的原图') plt.axis('off') plt.subplot(132) plt.imshow(cv2.cvtColor(crop_id_card, cv2.COLOR_BGR2RGB)) plt.title('裁剪后的身份证') plt.axis('off') plt.subplot(133) plt.imshow(cv2.cvtColor(id_without_background, cv2.COLOR_BGR2RGB)) plt.title('去除背景的身份证') plt.axis('off') plt.show() # 结果保存 cv2.imwrite('/content/id_with_box.jpg', result) cv2.imwrite('/content/cropped_id.jpg', crop_id_card) cv2.imwrite('/content/id_no_bg.jpg', id_without_background)
核心调整点
- 轮廓筛选:身份证是图像中最大的前景区域,通过面积排序取最大轮廓即可过滤所有噪点,不需要对所有轮廓做填充
- Bounding box绘制:拿到最大轮廓的外接矩形坐标后,直接调用
cv2.rectangle即可绘制外框 - 背景去除提供两种实现:直接裁剪身份证区域,或者通过掩码将非身份证区域替换为纯白,可根据需求选择
- 适配matplotlib显示逻辑,避免颜色通道错乱
内容的提问来源于stack exchange,提问作者Hammad Younas
相关产品推荐
相关产品推荐

