具有指定角度的 OpenCV RotatedRect

2024-02-16

I have the situation that I have a small binary image that has one shape, around which I want to find the best fitting rotated rectangle (not bounding rectangle). I know that there is cv::minAreaRect() that you apply on the result found by cv::findContours(), but this has delivered poor results in my case, because the data is noisy (coming from MS Kinect, see example picture Noise sensitivity where rotation changes due to the input data (contour) being slightly different). What I did instead was to calculate the principal axis using PCA on my binary image (which is less sensitive to noise), which yields angle "a", and now I want to create a RotatedRect around my shape, given the angle of the principal axis, a).

I have an illustration, made with my superb Paint skills! Illustration

那么我的问题是:你们有代码片段或具体建议来解决这个问题吗?恐怕我必须进行多次布雷森汉姆迭代,希望有一个聪明的方法。

顺便说一句,对于那些不太熟悉 openCV 的 RotatedRect 数据结构的人来说:它是由高度、宽度、角度和中心点定义的,假设中心点实际上位于矩形的中心。

Cheers!


好的,我的解决方案: 方法:

  1. PCA,给出旋转矩形中心的角度和第一近似值
  2. 获取二元形状的轮廓,将其旋转到直立位置,获取 X 和 Y 坐标的最小/最大,以获得边界矩形的宽度和高度
  3. 从最大 X (Y) 中减去宽度(高度)的一半,即可得到“直立空间”中的中心点
  4. 通过逆旋转矩阵将该中心点向后旋转

    cv::RotatedRect Utilities::getBoundingRectPCA( cv::Mat& binaryImg ) {
    cv::RotatedRect result;
    
    //1. convert to matrix that contains point coordinates as column vectors
    int count = cv::countNonZero(binaryImg);
    if (count == 0) {
        std::cout << "Utilities::getBoundingRectPCA() encountered 0 pixels in binary image!" << std::endl;
        return cv::RotatedRect();
    }
    
    cv::Mat data(2, count, CV_32FC1);
    int dataColumnIndex = 0;
    for (int row = 0; row < binaryImg.rows; row++) {
        for (int col = 0; col < binaryImg.cols; col++) {
            if (binaryImg.at<unsigned char>(row, col) != 0) {
                data.at<float>(0, dataColumnIndex) = (float) col; //x coordinate
                data.at<float>(1, dataColumnIndex) = (float) (binaryImg.rows - row); //y coordinate, such that y axis goes up
                ++dataColumnIndex;
            }
        }
    }
    
    //2. perform PCA
    const int maxComponents = 1;
    cv::PCA pca(data, cv::Mat() /*mean*/, CV_PCA_DATA_AS_COL, maxComponents);
    //result is contained in pca.eigenvectors (as row vectors)
    //std::cout << pca.eigenvectors << std::endl;
    
    //3. get angle of principal axis
    float dx = pca.eigenvectors.at<float>(0, 0);
    float dy = pca.eigenvectors.at<float>(0, 1);
    float angle = atan2f(dy, dx)  / (float)CV_PI*180.0f;
    
    //find the bounding rectangle with the given angle, by rotating the contour around the mean so that it is up-right
    //easily finding the bounding box then
    cv::Point2f center(pca.mean.at<float>(0,0), binaryImg.rows - pca.mean.at<float>(1,0));
    cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, -angle, 1);
    cv::Mat rotationMatrixInverse = cv::getRotationMatrix2D(center, angle, 1);
    
    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(binaryImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
    if (contours.size() != 1) {
        std::cout << "Warning: found " << contours.size() << " contours in binaryImg (expected one)" << std::endl;
        return result;
    }
    
    //turn vector of points into matrix (with points as column vectors, with a 3rd row full of 1's, i.e. points are converted to extended coords)
    cv::Mat contourMat(3, contours[0].size(), CV_64FC1);
    double* row0 = contourMat.ptr<double>(0);
    double* row1 = contourMat.ptr<double>(1);
    double* row2 = contourMat.ptr<double>(2);
    for (int i = 0; i < (int) contours[0].size(); i++) {
        row0[i] = (double) (contours[0])[i].x;
        row1[i] = (double) (contours[0])[i].y;
        row2[i] = 1;
    }
    
    cv::Mat uprightContour = rotationMatrix*contourMat;
    
    //get min/max in order to determine width and height
    double minX, minY, maxX, maxY;
    cv::minMaxLoc(cv::Mat(uprightContour, cv::Rect(0, 0, contours[0].size(), 1)), &minX, &maxX); //get minimum/maximum of first row
    cv::minMaxLoc(cv::Mat(uprightContour, cv::Rect(0, 1, contours[0].size(), 1)), &minY, &maxY); //get minimum/maximum of second row
    
    int minXi = cvFloor(minX);
    int minYi = cvFloor(minY);
    int maxXi = cvCeil(maxX);
    int maxYi = cvCeil(maxY);
    
    //fill result
    result.angle = angle;
    result.size.width = (float) (maxXi - minXi);
    result.size.height = (float) (maxYi - minYi);
    
    //Find the correct center:
    cv::Mat correctCenterUpright(3, 1, CV_64FC1);
    correctCenterUpright.at<double>(0, 0) = maxX - result.size.width/2;
    correctCenterUpright.at<double>(1,0) = maxY - result.size.height/2;
    correctCenterUpright.at<double>(2,0) = 1;
    cv::Mat correctCenterMat = rotationMatrixInverse*correctCenterUpright;
    cv::Point correctCenter = cv::Point(cvRound(correctCenterMat.at<double>(0,0)), cvRound(correctCenterMat.at<double>(1,0)));
    
    result.center = correctCenter;
    
    return result;
    

    }

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有指定角度的 OpenCV RotatedRect 的相关文章

  • OpenCV 中更新窗口的 waitKey() 的替代方法

    到目前为止我见过的所有示例和书籍都建议使用 waitKey 1 来强制重新绘制 OpenCV 窗口 这看起来很奇怪而且太老套了 不必要的时候为什么还要等待 1 毫秒呢 还有其他选择吗 我尝试了 cv updateWindow 但它似乎需要
  • 如何使用 Python 3 在 OpenCV 3 上正确加载 cv2.KeyPoint 和描述符?

    有一天 我不得不恢复一个使用 OpenCV 3 和 Python 2 7 的旧项目 在此代码中 要加载 cv2 KeyPoint 我执行以下操作 import numpy as np import cPickle import cv2 ke
  • 机器学习的周期性数据(例如度角 -> 179 与 -179 相差 2)

    我使用 Python 进行核密度估计 并使用高斯混合模型对多维数据样本的可能性进行排名 每一条数据都是一个角度 我不确定如何处理机器学习的角度数据的周期性 首先 我通过添加 360 来删除所有负角 因此所有负角都变成了正角 179 变成了
  • 使用 K 均值聚类 OpenCV 进行交通标志分割

    I used K Means Clustering to perform segmentation on this traffic sign as shown below 这些是我的代码 读取图像并模糊 img cv imread 000
  • 附加信息:OpenCV:使用 c# 的不同大小的对象

    目前 我的 EmguCV c 代码面临问题 我试图从数据库中识别我的图像 但它不起作用 一旦检测到我的脸 它就会崩溃 然后会出现此错误 附加信息 OpenCV 不同大小的对象 我尝试寻找这个错误 但我一无所知 这是我的代码 Action f
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • 有没有办法检测图像是否模糊? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道是否有一种方法可以通过分析图像数据来确定图像是否模糊 估计图像清晰度的另一种非常简单的方法是使用拉普拉斯 或 LoG 滤波器并
  • OpenCV:使用 StereoCamera 系统对颜色标记进行 3D 姿态估计

    我有一个立体摄像系统并使用两者正确校准它 cv calibrateCamera and cv stereoCalibrate My reprojection error似乎没问题 凸轮0 0 401427 凸轮1 0 388200 立体声
  • 在 Android 中使用 OpenCV 查找图像匹配

    我正在尝试构建一个 Android 应用程序 该应用程序可以比较设备相机拍摄的照片 以在一组图像中找到匹配项 我已经在 Android Studio 上配置了 OpenCV 但仅此而已 有人可以通过链接到资源或建议教程来提供帮助吗 Open
  • 如何在 opencv 3.0 Beta 中从文件读取 UMat?

    我想用UMat所以我的代码可以使用 OpenCL OpenCV 3 0 0 Beta 在 GPU 和 CPU 上运行 但我找不到将图像文件读入的方法UMat或转换一个Mat to UMat 如何将图像读入UMat 样品用于Mat to UM
  • 使用 OpenCV VideoWriter 将 RTSP 流存储为视频文件

    我正在使用 OpenCV 开发一个 Python 模块 该模块连接到 RTSP 流以对视频执行一些预处理 主要是降低 fps 和分辨率 然后将其存储在文件系统中 但是 即使在尝试了几种编解码器 寻找类似的开发之后 我总是得到一个空的视频 我
  • 如何在 OpenCV 中将 Float Mat 写入文件

    我有一个矩阵 Mat B 480 640 CV 32FC1 包含浮点值 我想将此矩阵写入一个可以打开的文件Notepad https en wikipedia org wiki Windows Notepad or 微软Word https
  • 如何将 OpenCV 的测试框架与 CMake 结合使用?

    好像 OpenCV 有一个测试框架 https github com Itseez opencv tree ef91d7e8830c36785f0b6fdbf2045da48413dd76 modules ts include opencv
  • 如何平滑循环列向量

    这是一个 OpenCV2 问题 我有一个矩阵代表closed空间曲线 cv Mat
  • 使用 openCV 对图像中的子图像进行通用检测

    免责声明 我是计算机视觉菜鸟 我看过很多关于如何在较大图像中查找特定子图像的堆栈溢出帖子 我的用例有点不同 因为我不希望它是具体的 而且我不确定如何做到这一点 如果可能的话 但我感觉应该如此 我有大量图像数据集 有时 其中一些图像是数据集的
  • OpenCV 中的 Gabor 内核参数

    我必须在我的应用程序中使用 Gabor 过滤器 但我不知道这个 OpenCV 方法参数值 我想对虹膜进行编码 启动 Gabor 过滤器并获取特征 我想对 12 组 Gabor 参数值执行此操作 然后我想计算 Hamming Dystans
  • Python 中的 Lanczos 插值与 2D 图像

    我尝试重新缩放 2D 图像 灰度 图像大小为 256x256 所需输出为 224x224 像素值范围从 0 到 1300 我尝试了两种使用 Lanczos 插值来重新调整它们的方法 首先使用PIL图像 import numpy as np
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码
  • 如何使用 OpencV 从 Firebase 读取图像?

    有没有使用 OpenCV 从 Firebase 读取图像的想法 或者我必须先下载图片 然后从本地文件夹执行 cv imread 功能 有什么办法我可以使用cv imread link of picture from firebase 您可以
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i

随机推荐