基于Python OpenCV检测图像16位数字图案并实现OCR
针对16位数字检测与OCR的解决方案
1. 检测并裁剪数字所在区域
目标是固定16位连续数字,可结合数字的形态特征和位置分布定位:
步骤与代码示例
- 预处理:通过灰度化、自适应二值化突出数字,压制干扰文字(根据图像实际颜色调整二值化正反)
import cv2 import numpy as np # 读取图像 img = cv2.imread("your_image.jpg") # 灰度化 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化(数字为白色,背景为黑色,适配光照不均场景) thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 开运算去除小干扰点 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2)) thresh_clean = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
- 筛选数字连通域:利用数字的宽高比、面积、同行分布特征过滤干扰
# 获取连通域及统计信息 num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh_clean, 8, cv2.CV_32S) # 筛选符合数字特征的连通域(根据你的图像调整宽高比、面积阈值) digit_stats = [] for i in range(1, num_labels): # 跳过背景(label 0) x, y, w, h, area = stats[i] aspect_ratio = w / h # 假设数字为窄高型,宽高比0.3-0.8,面积大于50(按需调整) if 0.3 < aspect_ratio < 0.8 and area > 50: digit_stats.append((x, y, w, h)) # 按x坐标排序(数字从左到右排列) digit_stats.sort(key=lambda x: x[0]) # 验证是否为完整16位数字(利用固定长度特征) if len(digit_stats) != 16: print("未检测到完整16位数字") else: # 合并得到数字区域边界 x_min = digit_stats[0][0] y_min = min([stat[1] for stat in digit_stats]) x_max = digit_stats[-1][0] + digit_stats[-1][2] y_max = max([stat[1] + stat[3] for stat in digit_stats]) # 裁剪数字区域 digit_region = img[y_min:y_max, x_min:x_max] cv2.imwrite("digit_region.jpg", digit_region)
2. 为数字绘制Contours
基于二值图提取轮廓,过滤后绘制:
步骤与代码示例
# 从清理后的二值图提取轮廓 contours, hierarchy = cv2.findContours(thresh_clean.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 过滤符合数字特征的轮廓 digit_contours = [] for c in contours: x, y, w, h = cv2.boundingRect(c) aspect_ratio = w / h area = cv2.contourArea(c) if 0.3 < aspect_ratio < 0.8 and area > 50: digit_contours.append(c) # 绘制单个数字的轮廓(绿色) cv2.drawContours(img, digit_contours, -1, (0, 255, 0), 2) # 绘制整体数字区域的矩形边框(红色) cv2.rectangle(img, (x_min, y_min), (x_max, y_max), (0, 0, 255), 2) cv2.imwrite("contour_image.jpg", img)
3. 数字识别的分类方法
针对带干扰的16位数字,有两种实用方案:
方案1:传统OCR(Tesseract)+ 针对性预处理
用Tesseract做数字识别,通过参数限制仅识别数字,适配单行连续文本:
import pytesseract # 对裁剪后的数字区域再次预处理 region_gray = cv2.cvtColor(digit_region, cv2.COLOR_BGR2GRAY) region_thresh = cv2.threshold(region_gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] # Tesseract参数:仅识别数字,单行文本模式 custom_config = r'--oem 3 --psm 7 -c tessedit_char_whitelist=0123456789' result = pytesseract.image_to_string(region_thresh, config=custom_config) print("识别结果:", result.strip())
方案2:机器学习分类(KNN/CNN)
如果传统OCR效果不佳,可自定义分类模型:
- KNN:提取数字的HOG特征,用标注好的数字样本训练KNN分类器,对分割后的单个数字逐个识别
- CNN:用简单卷积神经网络(如LeNet-5结构)训练0-9数字识别模型,适合样本量充足的场景,抗干扰能力更强
内容的提问来源于stack exchange,提问作者Arz Master
相关产品推荐
相关产品推荐

