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

如何用OpenCV检测并提取手写框中的图表?

解决方案

针对框线不闭合导致无法提取图表的问题,可以通过以下优化步骤解决:

1. 替换固定阈值为自适应阈值

固定阈值127无法适配图像局部明暗差异,改用自适应阈值能更好保留框线细节:

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 基于高斯加权的自适应阈值,参数可根据图像微调
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)

2. 升级形态学闭操作

原5x5的核尺寸太小,无法闭合较大间隙,改用更大的矩形核并增加迭代次数:

# 增大核尺寸到15x15,适配框线间隙
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 15))
# 多次闭操作强化闭合效果
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

3. 筛选并提取目标轮廓

通过面积过滤干扰轮廓,再用轮廓近似定位矩形框,最终裁剪图表:

contours, hierarchy = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

target_contours = []
for cnt in contours:
    # 过滤小面积干扰轮廓,阈值根据图像尺寸调整
    if cv2.contourArea(cnt) > 5000:
        # 轮廓近似,提取矩形顶点
        epsilon = 0.02 * cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, epsilon, True)
        # 筛选矩形轮廓(4个顶点)
        if len(approx) == 4:
            target_contours.append(approx)

# 逐个裁剪并保存/展示图表
for idx, cnt in enumerate(target_contours):
    x, y, w, h = cv2.boundingRect(cnt)
    chart = image[y:y+h, x:x+w]
    cv2.imwrite(f"chart_{idx}.png", chart)
    plt.imshow(cv2.cvtColor(chart, cv2.COLOR_BGR2RGB))
    plt.show()

完整可运行代码

import cv2
import matplotlib.pyplot as plt

# 加载图像
image = cv2.imread('diagram.jpg')
# 转换为灰度图
gray = cv2.cvtColor(image, 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, (15, 15))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

# 查找外轮廓
contours, hierarchy = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 筛选目标矩形轮廓
target_contours = []
for cnt in contours:
    area = cv2.contourArea(cnt)
    # 面积阈值需根据你的图像实际大小调整
    if area > 5000:
        epsilon = 0.02 * cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, epsilon, True)
        if len(approx) == 4:
            target_contours.append(approx)

# 提取并展示每个图表
for idx, cnt in enumerate(target_contours):
    x, y, w, h = cv2.boundingRect(cnt)
    chart_crop = image[y:y+h, x:x+w]
    cv2.imwrite(f"extracted_chart_{idx+1}.png", chart_crop)
    plt.imshow(cv2.cvtColor(chart_crop, cv2.COLOR_BGR2RGB))
    plt.title(f"提取的图表 {idx+1}")
    plt.axis('off')
    plt.show()

关键优化点说明

  • 自适应阈值:解决图像局部明暗不均导致的框线断裂问题,比固定阈值鲁棒性更强
  • 大尺寸核闭操作:足够大的核才能覆盖框线间隙,多次迭代确保完全闭合
  • 轮廓筛选:通过面积和矩形形状过滤干扰,精准定位需要提取的图表区域

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 03:36:31