You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python OpenCV+imutils阅卷程序:无法识别整张试卷仅检测单个矩形

解决试卷轮廓检测与俯视图变换问题

你的问题核心是试卷边框较弱时,当前预处理流程没能有效提取整张试卷的轮廓,导致程序优先识别了内部面积较大的题目区域。可以通过优化预处理步骤、调整轮廓筛选逻辑来实现整张试卷的四顶点检测,具体方案如下:

关键改进点

  • 替换Canny边缘检测为自适应阈值二值化:更适合处理光照不均、边框较弱的场景,能突出试卷的整体轮廓。
  • 添加形态学闭操作:填充边缘间隙,强化试卷边框的连通性。
  • 增加轮廓面积过滤:排除面积远小于试卷的小轮廓,避免干扰。
  • 微调多边形近似的精度参数:适配弱边框的轮廓特征。

修改后的完整代码

# Import libraries
import cv2
import numpy as np
import imutils
from imutils import contours
from imutils.perspective import four_point_transform

# 读取并预处理图像
image = cv2.imread("test4.jpg")
# 缩放图像(可选,根据实际分辨率调整,便于处理)
image = imutils.resize(image, height=800)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 用自适应阈值替代Canny,更适合弱边框场景
thresh = cv2.adaptiveThreshold(
    gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2
)

# 形态学闭操作:填充边框间隙,强化连通性
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# 查找轮廓
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
docCnt = None

# 筛选轮廓:优先找面积足够大的四边形
if len(cnts) > 0:
    # 按面积降序排序
    cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
    # 获取图像面积,设置最小面积阈值(比如图像的30%,可根据实际调整)
    image_area = image.shape[0] * image.shape[1]
    min_area = image_area * 0.3
    
    for c in cnts:
        # 计算轮廓周长
        peri = cv2.arcLength(c, True)
        # 调整近似精度(0.03*peri比0.02更宽松,适配弱边框)
        approx = cv2.approxPolyDP(c, 0.03 * peri, True)
        # 筛选条件:四边形+面积足够大
        if len(approx) == 4 and cv2.contourArea(c) > min_area:
            docCnt = approx
            break

# 执行透视变换(先判断是否找到有效轮廓)
if docCnt is not None:
    paper = four_point_transform(image, docCnt.reshape(4, 2))
    warped = four_point_transform(gray, docCnt.reshape(4, 2))
    
    # 绘制试卷轮廓
    cv2.drawContours(image, [docCnt], -1, (0, 255, 0), 3)
    cv2.imwrite("Contours.jpg", image)
    
    # 显示结果
    cv2.imshow("Original with Contour", image)
    cv2.imshow("Top-Down View", paper)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
else:
    print("未检测到试卷轮廓,请调整预处理参数或检查图像")

代码解释

  1. 自适应阈值:通过cv2.adaptiveThreshold根据局部区域的光照情况生成二值图像,能有效保留弱边框,避免Canny阈值固定导致的边缘丢失。
  2. 形态学闭操作:用矩形核填充边框的细小间隙,让试卷的轮廓更连贯,便于轮廓检测。
  3. 面积过滤:设置最小面积阈值为图像面积的30%,直接排除内部题目区域这类小轮廓,确保优先处理试卷本身。
  4. 多边形近似精度调整:将0.02 * peri改为0.03 * peri,降低近似精度要求,更容易把弱边框的轮廓拟合为四边形。

如果试卷边框极不明显,还可以尝试以下额外优化:

  • 调整自适应阈值的blockSize(比如改为15)和C值(比如改为3),适配不同光照。
  • 在形态学操作后添加一次膨胀操作,进一步强化边框。
  • 尝试先对图像做灰度直方图均衡化(cv2.equalizeHist(gray)),提升对比度后再做预处理。

内容的提问来源于stack exchange,提问作者mranonymous7122

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:56:04