c++ - 如何使用 OpenCV 正确旋转不规则矩形?

标签 c++ opencv

我正在尝试像这样旋转一个不规则的矩形:

Example

以放直为目的。我的轮廓是一个 cv::vector< cv::Point > 类型,在转换之后我得到一个 cv::vector< cv::Point2f > 类型,以便进行一些精确的计算。

正因为如此,我还需要一种进行这种旋转的好方法,所以首先我需要检测边。我试过使用“minarearect”,但结果一点也不好。边界矩形不匹配具有足够精度的不规则矩形方向。

是否有任何“最佳周长矩形”或类似的东西,而不是“最小面积矩形”?我认为这会让我更准确。 但是,您知道旋转矩形的其他方法吗?

请原谅我的英语。并感谢您的帮助!

最佳答案

您可以使用 PCA 获取矩形方向(第一和第二分量)的边,有了这些轴方向,您可以计算旋转角度。此处示例:http://docs.opencv.org/3.1.0/d1/dee/tutorial_introduction_to_pca.html

enter image description here

刚刚绘制了另一个变体的草图:

#include <iostream>
#include <vector>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;

//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
void getSamplePoints(Mat& src,vector<Point2f>& pts)
{
    pts.clear();
    for (int i = 0; i < src.rows; ++i)
    {
        for (int j = 0; j < src.cols; ++j)
        {
            uchar v = src.at<uchar>(i, j);
            if (v > 0)
            {
                pts.push_back(Point2f(j, i));
            }
        }
    }
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
double distance_to_Line(cv::Point2f line_start, cv::Point2f line_end, cv::Point2f point)
{
    double normalLength = _hypot(line_end.x - line_start.x, line_end.y - line_start.y);
    double distance = (double)((point.x - line_start.x) * (line_end.y - line_start.y) - (point.y - line_start.y) * (line_end.x - line_start.x)) / normalLength;
    return distance;
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
void getPointsFromVector(vector<Point2f>& pts,Point2f p1, Point2f p2, float dist, vector<Point2f>& pts_res)
{
    for (int i = 0; i < pts.size(); ++i)
    {
        double d = distance_to_Line(p1, p2, pts[i]);
        if (fabs(d) < dist)
        {
            pts_res.push_back(pts[i]);
        }
    }
}
//-----------------------------------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------------------------------
int main(int argc, unsigned int** argv)
{
    string fname = "../../data/rect_to_fit.png";
    Mat src = imread(fname, 1);
    if (src.empty())
    {
        return 0;
    }
    cvtColor(src, src, COLOR_BGR2GRAY);

    vector<Point2f> pts;
    getSamplePoints(src, pts);


    RotatedRect R = minAreaRect(pts);
    Point2f r_pts[4];
    R.points(r_pts);

    for (int j = 0; j < 4; j++)
    {
        vector<Point2f> res_pts;
        Point2f p1 = r_pts[j];
        Point2f p2 = r_pts[(j + 1) % 4];
        getPointsFromVector(pts,p1,p2,20, res_pts);
        for (auto p : res_pts)
        {
            circle(src, p, 3, Scalar::all(255), -1);
        }
      //  imshow("src", src);
      //  waitKey(0);
        Vec4f L;
        fitLine(res_pts, L, cv::DIST_L2, 0, 0.01, 0.01);
        float x = L[2];
        float y = L[3];
        float vx = L[0];
        float vy = L[1];
        float lefty = int((-x*vy / vx) + y);
        float righty = int(((src.cols - x)*vy / vx) + y);
        line(src, Point2f(src.cols - 1, righty), Point2f(0, lefty), Scalar::all(255), 2);
    }

    imshow("src", src);
    imwrite("result.jpg", src);
    waitKey(0);

    return 0;
}

我得到的结果: enter image description here

关于c++ - 如何使用 OpenCV 正确旋转不规则矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43316747/

相关文章:

c++ - 持有对自身的引用的类

c++ - C++ 中未初始化的变量行为

Python CV2 视频编写器不保存视频

c++ - C++、OpenCV : Cannot include imgproc library for Cvtcolor function

c - 如何识别图像中的钞票?

c++ - 当找到某个标记时,是否有更快的方法来拆分文本文件?

c++ - Boost Process `system` 函数中的错误处理

c++ - 为什么 OpenCV C++ 接口(interface)中的某些函数中有结构声明?

python - 视频帧作为 Tensorflow 图的输入

c++ - 使用 PlayEnhMetaFile 绘制带有 alpha channel 的增强图元文件