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

Python OpenCV检测二值图像方块角度:C++转写及方案咨询

Python实现二值图像方块角度提取方案

现存问题

  • 无法将参考的C++ OpenCV实现逻辑正确转换为Python版本
  • 需要除轮廓检测外的其他可行实现方案(如Blob检测类方法)参考

参考材料

待检测示例图像

待检测方块二值图

参考C++ OpenCV实现代码

cv::Mat input = cv::imread("../inputData/rectangles.png");

cv::Mat gray;
cv::cvtColor(input,gray,CV_BGR2GRAY);

// 图像存在压缩伪影,先做阈值处理
int threshold = 200;
cv::Mat mask = gray > threshold;

cv::imshow("mask", mask);

// 提取轮廓
std::vector<std::vector<cv::Point> > contours;
cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

for(int i=0; i<contours.size(); ++i)
{
    // 对轮廓拟合最小外接旋转矩形
    cv::RotatedRect rotatedRect = cv::minAreaRect(contours[i]);

    // 读取矩形顶点和角度
    cv::Point2f rect_points[4]; 
    rotatedRect.points( rect_points );

    float  angle = rotatedRect.angle; // 角度值

    // 读取旋转矩形中心点
    cv::Point2f center = rotatedRect.center; // 中心点坐标

    // 绘制旋转矩形边框
    for(unsigned int j=0; j<4; ++j)
        cv::line(input, rect_points[j], rect_points[(j+1)%4], cv::Scalar(0,255,0));

    // 绘制中心点并标注角度
    std::stringstream ss;   ss << angle; // 浮点角度转字符串
    cv::circle(input, center, 5, cv::Scalar(0,255,0)); // 绘制中心点
    cv::putText(input, ss.str(), center + cv::Point2f(-25,25), 
    cv::FONT_HERSHEY_COMPLEX_SMALL,1, cv::Scalar(255,0,255)); // 标注角度文本
}

当前存在错误的Python实现代码

contours_yellow, hierarchy = cv2.findContours(mask_yellow, cv2.RETR_TREE, 
cv2.CHAIN_APPROX_SIMPLE)

yellow_contours = cv2.drawContours(mask_yellow, contours_yellow, -1, (0,255,0), 3)

angle = 0

for contour in yellow_contours :
{
    # 对轮廓拟合外接矩形
    RotatedRect = minAreaRect(contours_yellow[value])

    # 读取顶点和角度
    point2f rect_points[4]
    rotatedRect.points(rect_points)

    angle = rotatedRect.angle; # 角度值


}

    print (angle)

对应C++逻辑的正确Python实现

原有Python代码的核心问题:

  • 错误遍历drawContours返回的绘制后图像矩阵,而非检测到的轮廓列表
  • 混用C语法,包括大括号包裹循环体、C风格的静态数组变量声明
  • 存在未定义变量,OpenCV-Python接口调用格式错误
  • 轮廓检索、近似参数和参考C++版本不一致,容易引入噪点轮廓

可直接运行的正确代码:

import cv2
import numpy as np

# 读取图像
input_img = cv2.imread("rectangles.png")
gray = cv2.cvtColor(input_img, cv2.COLOR_BGR2GRAY)

# 阈值处理生成二值mask,阈值可根据实际图像亮度调整
_, mask = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)

# 提取最外层轮廓,参数和C++参考版本对齐
contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

for cnt in contours:
    # 过滤面积过小的噪点轮廓,面积阈值按需调整
    if cv2.contourArea(cnt) < 100:
        continue
    # 拟合最小外接旋转矩形
    rotated_rect = cv2.minAreaRect(cnt)
    # 解包获取矩形中心点、宽高、角度
    center, (w, h), angle = rotated_rect
    # 获取矩形四个顶点坐标,转换为整数方便绘制
    rect_points = cv2.boxPoints(rotated_rect).astype(np.int32)
    
    # 绘制旋转矩形边框
    cv2.drawContours(input_img, [rect_points], 0, (0,255,0), 2)
    # 绘制矩形中心点
    cv2.circle(input_img, (int(center[0]), int(center[1])), 5, (0,255,0), -1)
    # 在中心点旁标注角度值
    cv2.putText(input_img, f"{angle:.1f}", (int(center[0]-25), int(center[1]+25)),
                cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (255,0,255), 1)

# 显示检测结果
cv2.imshow("result", input_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

注意:OpenCVminAreaRect返回的角度范围为[-90, 0),表示矩形相对于水平方向的旋转角度偏移,如果需要转换为0~90度的直观角度,可根据宽高比例换算:当矩形宽度小于高度时,角度取90 + angle即可。

其他可选实现方案

  • Blob检测方案:使用cv2.SimpleBlobDetector配置参数过滤方块类斑点,通过Blob的外接矩形属性计算角度,适合噪点较多、方块大小相对统一的场景,检测稳定性更高。配置时需要开启斑点旋转属性读取,同时设置面积、圆形度阈值过滤非方块目标。
  • 霍夫直线检测方案:对二值图像做边缘检测后用霍夫变换检测方块的四条边,通过直线斜率计算方块倾斜角度,适合边缘清晰、无遮挡的场景,但对边缘断裂、噪点较多的图像鲁棒性不如轮廓拟合方案。
  • 连通域分析方案:使用cv2.connectedComponentsWithStats提取每个连通域的属性,结合外接旋转矩形计算角度,处理速度比轮廓检测更快,适合批量处理大量图像的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 04:01:14