cv::RotatedRect 中非零像素的数量

发布于 2024-11-19 15:01:49 字数 250 浏览 3 评论 0原文

正如标题所说,我试图找到 cv::Mat 的某个区域(即 RotatedRect 内)的非零像素数。

对于常规矩形,可以简单地在 ROI 上使用 countNonZeroPixels。然而 ROI 只能是规则的(非旋转的)矩形。

另一个想法是绘制旋转的矩形并将其用作遮罩。然而 openCV 既不支持旋转矩形的绘制,也不接受 countNonZeroPixels 接受掩码。

有谁有解决方案来优雅地解决这个问题?

谢谢 !

as the title says i'm trying to find the number of non-zero pixels in a certain area of a cv::Mat, namely within a RotatedRect.

For a regular Rect one could simply use countNonZeroPixels on a ROI. However ROIs can only be regular (non rotated) rectangles.

Another idea was to draw the rotated rectangle and use that as a mask. However openCV neither supports the drawing of rotated rectangles nor does countNonZeroPixels accept a mask.

Does anyone have a solution for how to elegantly solve this ?

Thank you !

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云淡风轻 2024-11-26 15:01:49

好的,这是我的第一次尝试。

这个想法是将图像旋转到与矩形旋转相反的方向,然后在拉直的矩形上应用 roi。

  • 如果旋转的矩形不完全在图像内,这将会中断
  • 您可以通过在旋转之前应用另一个 roi 来加快速度,以避免旋转整个图像...

    #include ;
    #include ;
    
    
    //来自http://stackoverflow.com/questions/2289690/opencv-how-to-rotate-iplimage
    cv::MatrotateImage(const cv::Mat&源,cv::Point2f中心,双角度)
    {
      cv::Mat rot_mat = cv::getRotationMatrix2D(中心,角度,1.0);
      简历::Mat dst;
      cv::warpAffine(source, dst, rot_mat, source.size());
      返回目的地;
    }
    
    int main()
    {
      cv::namedWindow("test1");
    
      // 我们的旋转矩形
      整数x = 300;
      整数 y = 350;
      整数 w = 200;
      整数 h = 50;
      浮动角=47;
      cv::RotatedRect 矩形 = cv::RotatedRect(cv::Point2f(x,y), cv::Size2f(w,h), 角度);
    
      // 空图像
      cv::Mat img = cv::Mat(cv::Size(640, 480), CV_8UC3);
    
      // 将旋转的矩形绘制为椭圆以获得一些视觉反馈
      cv::椭圆(img, 矩形, cv::标量(255,0,0), -1);
    
      // 将图像旋转 rect.angle * -1
      cv::Mat rotimg =rotateImage(img, 矩形中心, -1 * 矩形角度);
    
      // 将 roi 设置为现在未旋转的矩形
      CV::矩形投资回报率;
      roi.x = rect.center.x - (rect.size.width / 2);
      roi.y = rect.center.y - (rect.size.height / 2);
      roi.width = rect.size.width;
      roi.height = rect.size.height;
    
      cv::imshow("test1", rotimg(roi));
      CV::waitKey(0);
    }
    

Ok, so here's my first take at it.

The idea is to rotate the image reverse to the rectangle's rotation and than apply a roi on the straightened rectangle.

  • This will break if the rotated rectangle is not completely within the image
  • You can probably speed this up by applying another roi before rotation to avoid having to rotate the whole image...

    #include <highgui.h>
    #include <cv.h>
    
    
    // From http://stackoverflow.com/questions/2289690/opencv-how-to-rotate-iplimage
    cv::Mat rotateImage(const cv::Mat& source, cv::Point2f center, double angle)
    {
      cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, 1.0);
      cv::Mat dst;
      cv::warpAffine(source, dst, rot_mat, source.size());
      return dst;
    }
    
    int main()
    {
      cv::namedWindow("test1");
    
      // Our rotated rect
      int x = 300;
      int y = 350;
      int w = 200;
      int h = 50;
      float angle = 47;
      cv::RotatedRect rect = cv::RotatedRect(cv::Point2f(x,y), cv::Size2f(w,h), angle);
    
      // An empty image
      cv::Mat img = cv::Mat(cv::Size(640, 480), CV_8UC3);
    
      // Draw rotated rect as an ellipse to get some visual feedback
      cv::ellipse(img, rect, cv::Scalar(255,0,0), -1);
    
      // Rotate the image by rect.angle * -1
      cv::Mat rotimg = rotateImage(img, rect.center, -1 * rect.angle);
    
      // Set roi to the now unrotated rectangle
      cv::Rect roi;
      roi.x = rect.center.x - (rect.size.width / 2);
      roi.y = rect.center.y - (rect.size.height / 2);
      roi.width = rect.size.width;
      roi.height = rect.size.height;
    
      cv::imshow("test1", rotimg(roi));
      cv::waitKey(0);
    }
    
绮烟 2024-11-26 15:01:49

一种完全不同的方法可能是旋转图像(沿相反方向),并仍然将矩形 ROI 与 countNonZeroPixels 结合使用。唯一的问题是您必须围绕 ROI 中心的轴旋转图像...

为了使其更清楚,请参阅随附的示例:

在此处输入图像描述

A totally different approach might be to rotate your image (in opposite direction), and still use the rectangular ROI in combination with countNonZeroPixels. The only problem will be that you have to rotate your image around a pivot of the center of the ROI...

To make it clearer, see attached example:

enter image description here

要走干脆点 2024-11-26 15:01:49

为了避免类似任务中的旋转,我使用这样的函数迭代 RotatedRect 中的每个像素:

double filling(Mat& img, RotatedRect& rect){

    double non_zero = 0;
    double total = 0;
    Point2f rect_points[4];
    rect.points( rect_points );

    for(Point2f i=rect_points[0];norm(i-rect_points[1])>1;i+=(rect_points[1]-i)/norm((rect_points[1]-i))){
        Point2f destination = i+rect_points[2]-rect_points[1];
        for(Point2f j=i;norm(j-destination)>1;j+=(destination-j)/norm((destination-j))){
            if(img.at<uchar>(j) != 0){
                non_zero+=1;
            }
            total+=1;
        }
    }

    return non_zero/total;
}

它看起来像通常对矩形的迭代,但在每一步中,我们将单位 1px 向量添加到目标方向的当前点。

这个循环不会迭代所有点并跳过一些像素,但这对我的任务来说是可以的。

UPD: 使用 LineIterator 进行迭代要好得多:

Point2f rect_points[4];
rect.points(rect_points);

Point2f x_start = rect_points[0];
Point2f x_end = rect_points[1];
Point2f y_direction = rect_points[3] - rect_points[0];

LineIterator x = LineIterator(frame, x_start, x_end, 4);
for(int i = 0; i < x.count; ++i, ++x){
    LineIterator y = LineIterator(frame, x.pos(), x.pos() + y_direction, 4);
    for(int j=0; j < y_count; j++, ++y){
        Vec4b pixel = frame.at<Vec4b>(y.pos);
        /* YOUR CODE HERE */
    }
}

To avoid rotation in similar task I iterate over each pixel in RotatedRect with such function:

double filling(Mat& img, RotatedRect& rect){

    double non_zero = 0;
    double total = 0;
    Point2f rect_points[4];
    rect.points( rect_points );

    for(Point2f i=rect_points[0];norm(i-rect_points[1])>1;i+=(rect_points[1]-i)/norm((rect_points[1]-i))){
        Point2f destination = i+rect_points[2]-rect_points[1];
        for(Point2f j=i;norm(j-destination)>1;j+=(destination-j)/norm((destination-j))){
            if(img.at<uchar>(j) != 0){
                non_zero+=1;
            }
            total+=1;
        }
    }

    return non_zero/total;
}

It's looks like usual iteration over rectangle, but on each step we add unit 1px vector to current point in direction to destination.

This loop NOT iterate over all points and skip a few pixels, but it was okay for my task.

UPD: It much better to use LineIterator to iterate:

Point2f rect_points[4];
rect.points(rect_points);

Point2f x_start = rect_points[0];
Point2f x_end = rect_points[1];
Point2f y_direction = rect_points[3] - rect_points[0];

LineIterator x = LineIterator(frame, x_start, x_end, 4);
for(int i = 0; i < x.count; ++i, ++x){
    LineIterator y = LineIterator(frame, x.pos(), x.pos() + y_direction, 4);
    for(int j=0; j < y_count; j++, ++y){
        Vec4b pixel = frame.at<Vec4b>(y.pos);
        /* YOUR CODE HERE */
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文