在做图像处理项目的时候,我遇到一个实际问题:怎么从一张拍下来的答题卡中,自动裁剪出答题区域?
答题区域其实很好识别 —— 通常被四个黑色小角块框住了。所以我写了一个简单的 OpenCV 脚本,试图通过这四个角块来定位并裁剪答题区域。
过程踩了点坑,但最终搞定了。以下是完整代码和我的思路,欢迎参考,也欢迎指正!
实现思路
我的目标是提取这类图像中的答题区:
利用自适应阈值,增强对比度;
通过 cv2.findContours() 找轮廓;
计算每个轮廓的面积和周长,用 面积 / 周长 计算“紧凑度”;
只保留紧凑度合理、形状接近方块的轮廓;
找到四个角块后,用它们的边界矩形裁剪出答题区。
代码如下
import cv2
import numpy as np
from typing import Optional
def extract_answer_area(image_path: str) -> Optional[np.ndarray]:
"""
从图像中提取答题区域(通过四个黑色定位角块定位)
使用紧凑度筛选角块
"""
image = cv2.imread(image_path)
if image is None:
print(f"图像读取失败: {image_path}")
return None
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
thresh = cv2.adaptiveThreshold(
blurred, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 11, 2
)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
rects = []
for cnt in contours:
area = float(cv2.contourArea(cnt))
length = float(cv2.arcLength(cnt, True))
if area <= 0 or length <= 0:
continue
compactness = area / length # 紧凑度
# 只选紧凑度在合理范围内的轮廓,值越大表示越“实心”、越接近方块
if 5.5 < compactness < 7.5:
print(compactness)
approx = cv2.approxPolyDP(cnt, 0.02 * length, True)
if len(approx) == 4:
x, y, w, h = cv2.boundingRect(cnt)
rects.append((x, y, w, h))
print(f"共找到满足条件的角块数量: {len(rects)}")
if len(rects) >= 4:
xs = [x for (x, y, w, h) in rects] + [x + w for (x, y, w, h) in rects]
ys = [y for (x, y, w, h) in rects] + [y + h for (x, y, w, h) in rects]
x_min, x_max = min(xs), max(xs)
y_min, y_max = min(ys), max(ys)
cropped = image[y_min:y_max, x_min:x_max]
return cropped
else:
print("未能识别到4个黑色角块请检查图像质量或参数。")
return None
result = extract_answer_area(r"C:\Users\26950\Desktop\enghish1.jpg")
if result is not None:
cv2.imwrite("answer_area_cropped.jpg", result)
print("答题区已保存到 answer_area_cropped.jpg")
else:
print("答题区提取失败")
切割前:
切割后:
关于“紧凑度”这个指标
我用的是 紧凑度 = 面积 / 周长,这个值可以用来排除线条、框线等细长的干扰物。
我观察到在我的图像中,角块的紧凑度大概集中在 5.5 到 7.5 左右,当然这可能和图像尺寸、拍摄角度有关。
如果你发现自己的图识别不到角块,可以:
打印出所有轮廓的 面积 / 周长 看看;
调整这两个阈值;
也可以加上其他筛选,比如面积范围、是否是矩形等。
补充说明
之后可以把答题卡上的题目按照题型分类后来批改,可以尝试使用ocr或者具有视觉能力的大模型