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

如何使用OpenCV识别图表的四个角落?

解决图表四角定位的可行方案

针对你遇到的刻度线干扰、角点检测不准确的问题,这里提供几个实用的解决方案:

方案1:预处理清除刻度线+轮廓近似提取四角

核心思路是先通过形态学操作去除细刻度线,再提取图表外框轮廓并做多边形近似,得到四个角点。

import cv2 as cv
import numpy as np

img = cv.imread("image_path")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 二值化处理
thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]

# 创建结构元素,针对性去除水平/垂直刻度线(可根据刻度粗细调整核大小)
horizontal_kernel = cv.getStructuringElement(cv.MORPH_RECT, (20, 1))
vertical_kernel = cv.getStructuringElement(cv.MORPH_RECT, (1, 20))

# 开运算去除细刻度:先腐蚀后膨胀,保留大轮廓
thresh_no_horizontal = cv.morphologyEx(thresh, cv.MORPH_OPEN, horizontal_kernel, iterations=1)
thresh_clean = cv.morphologyEx(thresh_no_horizontal, cv.MORPH_OPEN, vertical_kernel, iterations=1)

# 提取最外层轮廓,筛选面积最大的(图表外框)
contours, _ = cv.findContours(thresh_clean, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
max_contour = max(contours, key=cv.contourArea)

# Douglas-Peucker算法做轮廓近似,epsilon值控制近似精度
epsilon = 0.02 * cv.arcLength(max_contour, True)
approx_corners = cv.approxPolyDP(max_contour, epsilon, True)

# 绘制检测结果
if len(approx_corners) == 4:
    img_copy = img.copy()
    for corner in np.int0(approx_corners):
        x, y = corner.ravel()
        cv.circle(img_copy, (x, y), 5, (0, 255, 0), -1)
    cv.imshow("Detected Corners", img_copy)
    cv.waitKey(0)
    cv.destroyAllWindows()

方案2:霍夫直线检测+交点计算

通过检测图表的四条边框直线,计算两两直线的交点得到四角,适合边框清晰的图表。

import cv2 as cv
import numpy as np

def calculate_intersection(line1, line2):
    """计算两条直线的交点,返回整数坐标或None"""
    x1, y1, x2, y2 = line1[0]
    x3, y3, x4, y4 = line2[0]
    
    denom = (x1 - x2)*(y3 - y4) - (y1 - y2)*(x3 - x4)
    if denom == 0:
        return None  # 直线平行或重合
    
    t = ((x1 - x3)*(y3 - y4) - (y1 - y3)*(x3 - x4)) / denom
    u = -((x1 - x3)*(y1 - y2) - (y1 - y3)*(x1 - x2)) / denom
    
    if 0 <= t <= 1 and 0 <= u <= 1:
        x = int(x1 + t*(x2 - x1))
        y = int(y1 + t*(y2 - y1))
        return (x, y)
    return None

img = cv.imread("image_path")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# Canny边缘检测
edges = cv.Canny(gray, 50, 150)

# 霍夫直线检测,筛选长度足够的直线
lines = cv.HoughLinesP(edges, 1, np.pi/180, threshold=50, minLineLength=100, maxLineGap=10)

# 分类水平和垂直直线
horizontal_lines = []
vertical_lines = []
for line in lines:
    x1, y1, x2, y2 = line[0]
    angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi
    # 筛选接近水平的直线(角度误差±10°)
    if abs(angle) < 10 or abs(angle - 180) < 10:
        horizontal_lines.append(line)
    # 筛选接近垂直的直线
    elif abs(angle - 90) < 10 or abs(angle - 270) < 10:
        vertical_lines.append(line)

# 取最长的两条水平/垂直直线(图表边框)
horizontal_lines.sort(key=lambda l: np.sqrt((l[0][0]-l[0][2])**2 + (l[0][1]-l[0][3])**2), reverse=True)
vertical_lines.sort(key=lambda l: np.sqrt((l[0][0]-l[0][2])**2 + (l[0][1]-l[0][3])**2), reverse=True)
selected_h = horizontal_lines[:2]
selected_v = vertical_lines[:2]

# 计算所有交点
corners = []
for h_line in selected_h:
    for v_line in selected_v:
        pt = calculate_intersection(h_line, v_line)
        if pt is not None:
            corners.append(pt)

# 绘制结果
img_copy = img.copy()
for corner in corners:
    cv.circle(img_copy, corner, 5, (0, 0, 255), -1)
cv.imshow("Detected Corners", img_copy)
cv.waitKey(0)
cv.destroyAllWindows()

方案3:最小外接矩形提取四角

如果图表存在倾斜,用最小外接矩形直接获取四个顶点,前提是先清除刻度干扰。

import cv2 as cv
import numpy as np

img = cv.imread("image_path")
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV + cv.THRESH_OTSU)[1]

# 闭运算填充小缝隙,强化外框轮廓
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))
thresh_clean = cv.morphologyEx(thresh, cv.MORPH_CLOSE, kernel, iterations=2)

# 提取最大轮廓
contours, _ = cv.findContours(thresh_clean, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
max_contour = max(contours, key=cv.contourArea)

# 计算最小外接矩形,提取四个顶点
rect = cv.minAreaRect(max_contour)
box = cv.boxPoints(rect)
box = np.int0(box)

# 绘制结果
img_copy = img.copy()
for point in box:
    cv.circle(img_copy, tuple(point), 5, (255, 0, 0), -1)
cv.imshow("Detected Corners", img_copy)
cv.waitKey(0)
cv.destroyAllWindows()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 07:10:25