如何用Python识别图片中复选框的选中状态?
带复选框表格的识别与二维列表转换方案
以下是针对需求的具体实现步骤和代码:
1. 图片预处理(保留表格结构与内容)
先对图片做灰度化和自适应二值化,避免单纯阈值化丢失文本和复选框细节:
import cv2 import numpy as np import pytesseract # 若tesseract未在系统环境变量中,需指定路径 # pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract.exe' # 读取图片 img = cv2.imread('A5wrw.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 自适应二值化,同时保留表格线条和内容 thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
2. 定位表格单元格
通过检测线条和轮廓,划分出每个单元格的位置:
# 检测水平与垂直线条 horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1)) detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2) vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,40)) detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2) # 合并线条得到表格框架 combined = cv2.addWeighted(detect_horizontal, 0.5, detect_vertical, 0.5, 0.0) combined = cv2.threshold(combined, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] # 查找并筛选单元格轮廓 contours, _ = cv2.findContours(combined, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cells = [] for cnt in contours: area = cv2.contourArea(cnt) # 面积阈值根据图片尺寸调整,过滤过小/过大的轮廓 if 1000 < area < 50000: x,y,w,h = cv2.boundingRect(cnt) cells.append((x,y,w,h)) # 按行列排序单元格 cells.sort(key=lambda x: (x[1], x[0])) rows = [] current_row_y = cells[0][1] current_row = [] for cell in cells: x,y,w,h = cell # 行间距阈值根据图片调整,判断是否换行列 if abs(y - current_row_y) > 20: rows.append(current_row) current_row = [cell] current_row_y = y else: current_row.append(cell) rows.append(current_row)
3. 识别单元格内容(复选框+文本)
对每个单元格ROI(感兴趣区域)分别处理复选框状态和文本:
def is_checked(cell_roi): # 通过黑色像素占比判断复选框是否选中(选中的复选框黑色填充占比更高) gray_roi = cv2.cvtColor(cell_roi, cv2.COLOR_BGR2GRAY) _, thresh_roi = cv2.threshold(gray_roi, 127, 255, cv2.THRESH_BINARY_INV) black_pixels = np.sum(thresh_roi == 255) total_pixels = thresh_roi.size # 占比阈值根据复选框大小调整 return black_pixels / total_pixels > 0.1 table_data = [] for row in rows: row_data = [] for (x,y,w,h) in row: cell_roi = img[y:y+h, x:x+w] # 检测复选框状态 checked = is_checked(cell_roi) # 提取单元格文本,psm=6适用于单块文本的识别,chi_sim为中文语言包 text = pytesseract.image_to_string(cell_roi, config='--psm 6 -l chi_sim') text = text.strip() # 去除多余空格和换行 row_data.append({'text': text, 'checked': checked}) table_data.append(row_data)
4. 转换为目标二维列表
整理成(文本,选中状态)的二维结构:
final_table = [[(item['text'], item['checked']) for item in row] for row in table_data] # 打印结果 for row in final_table: print(row)
关键调整提示
- 所有阈值参数(面积、行间距、黑色像素占比)需根据实际图片尺寸调整,可先打印单元格坐标确认定位准确性。
- 若复选框样式特殊(如空心/实心图标),可修改
is_checked函数逻辑,比如通过检测内部轮廓数量判断选中状态。 - 需确保pytesseract已安装中文语言包
chi_sim,否则中文识别会乱码。
内容的提问来源于stack exchange,提问作者bluesky
相关产品推荐
相关产品推荐

