RotatedRect的OpenCV最小直立边界矩形

时间:2021-11-07 23:02:39

I'm trying to determin minimum bouding rect of a rotated rectangle. I tried a couple of samples like this from RotatedRect reference or from this tutorial about ellipses and bounding boxes. Nothing with satisfactory results. On the image bellow, yellow rectangle is the desired result.

我正在尝试确定旋转矩形的最小布局矩形。我从RotatedRect参考或本教程中尝试了几个类似于椭圆和边界框的样本。没有令人满意的结果。在下面的图像上,黄色矩形是期望的结果。

Example data for my test:

我测试的示例数据:

Image:
    Width: 1500
    Height: 843

RotatedRect:
    Center:
        X: 783.490417
        Y: 433.673492
    Size:
        Width: 810.946899
        Height: 841.796997
    Angle: 95.4092407

Sample code:

示例代码:

cv::RotatedRect r(cv::Point2f(783.490417, 433.673492), 
    cv::Size2f(810.946899, 841.796997), 
    95.4092407);

cv::Mat img = Mat::zeros(843, 1500, CV_8UC3);

cv::Rect rect  = r.boundingRect();
cv::ellipse(img, r, cv::Scalar(0, 0, 255)); // RED

Point2f vertices[4];
r.points(vertices);

for (int i = 0; i < 4; i++)
    line(img, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0)); // GREEN

rectangle(img, rect, Scalar(255, 0, 0)); // BLUE
cv::imshow("Result", img);
  • RED - RotatedRect for which min bouding rect is calculated
  • RED - RotatedRect,计算min bouding rect
  • BLUE - r.boundingRect()
  • 蓝色 - r.boundingRect()
  • GREEN - r.points()
  • GREEN - r.points()
  • YELLOW - desired result
  • 黄色 - 期望的结果

RotatedRect的OpenCV最小直立边界矩形

1 个解决方案

#1


3  

i think here you can find a function doing your desired result.

我想在这里你可以找到一个功能来做你想要的结果。

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"


using namespace cv;

int main( int argc, char**)
{
    RotatedRect r ;
    r.center =  cv::Point2f(783.490417, 433.673492);
    r.angle = 95.4092407;
    r.size = cv::Size2f(810.946899, 841.796997);

    cv::Mat img = Mat::zeros(843, 1500, CV_8UC3);

    cv::Rect rect  = r.boundingRect();
    cv::ellipse(img, r, cv::Scalar(0, 0, 255)); // RED

    Point2f vertices[4];
    r.points(vertices);

    for (int i = 0; i < 4; i++)
        line(img, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0)); // GREEN

    rectangle(img, rect, Scalar(255, 0, 0)); // BLUE


    float degree = r.angle*3.1415/180;
    float majorAxe = r.size.width/2;
    float minorAxe = r.size.height/2;
    float x = r.center.x;
    float y = r.center.y;
    float c_degree = cos(degree);
    float s_degree = sin(degree);
    float t1 = atan(-(majorAxe*s_degree)/(minorAxe*c_degree));
    float c_t1 = cos(t1);
    float s_t1 = sin(t1);
    float w1 = majorAxe*c_t1*c_degree;
    float w2 = minorAxe*s_t1*s_degree;
    float maxX = x + w1-w2;
    float minX = x - w1+w2;

    t1 = atan((minorAxe*c_degree)/(majorAxe*s_degree));
    c_t1 = cos(t1);
    s_t1 = sin(t1);
    w1 = minorAxe*s_t1*c_degree;
    w2 = majorAxe*c_t1*s_degree;
    float maxY = y + w1+w2;
    float minY = y - w1-w2;
    if (minY > maxY)
    {
        float temp = minY;
        minY = maxY;
        maxY = temp;
    }
    if (minX > maxX)
    {
        float temp = minX;
        minX = maxX;
        maxX = temp;
    }
    Rect yellowrect(minX,minY,maxX-minX+1,maxY-minY+1);

    rectangle(img, yellowrect, Scalar(0, 255, 255)); // YELLOW
    cv::imshow("Result", img);
    waitKey();
}

#1


3  

i think here you can find a function doing your desired result.

我想在这里你可以找到一个功能来做你想要的结果。

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"


using namespace cv;

int main( int argc, char**)
{
    RotatedRect r ;
    r.center =  cv::Point2f(783.490417, 433.673492);
    r.angle = 95.4092407;
    r.size = cv::Size2f(810.946899, 841.796997);

    cv::Mat img = Mat::zeros(843, 1500, CV_8UC3);

    cv::Rect rect  = r.boundingRect();
    cv::ellipse(img, r, cv::Scalar(0, 0, 255)); // RED

    Point2f vertices[4];
    r.points(vertices);

    for (int i = 0; i < 4; i++)
        line(img, vertices[i], vertices[(i + 1) % 4], Scalar(0, 255, 0)); // GREEN

    rectangle(img, rect, Scalar(255, 0, 0)); // BLUE


    float degree = r.angle*3.1415/180;
    float majorAxe = r.size.width/2;
    float minorAxe = r.size.height/2;
    float x = r.center.x;
    float y = r.center.y;
    float c_degree = cos(degree);
    float s_degree = sin(degree);
    float t1 = atan(-(majorAxe*s_degree)/(minorAxe*c_degree));
    float c_t1 = cos(t1);
    float s_t1 = sin(t1);
    float w1 = majorAxe*c_t1*c_degree;
    float w2 = minorAxe*s_t1*s_degree;
    float maxX = x + w1-w2;
    float minX = x - w1+w2;

    t1 = atan((minorAxe*c_degree)/(majorAxe*s_degree));
    c_t1 = cos(t1);
    s_t1 = sin(t1);
    w1 = minorAxe*s_t1*c_degree;
    w2 = majorAxe*c_t1*s_degree;
    float maxY = y + w1+w2;
    float minY = y - w1-w2;
    if (minY > maxY)
    {
        float temp = minY;
        minY = maxY;
        maxY = temp;
    }
    if (minX > maxX)
    {
        float temp = minX;
        minX = maxX;
        maxX = temp;
    }
    Rect yellowrect(minX,minY,maxX-minX+1,maxY-minY+1);

    rectangle(img, yellowrect, Scalar(0, 255, 255)); // YELLOW
    cv::imshow("Result", img);
    waitKey();
}