cv :: RotatedRect中的零像素

如标题所示,我试图在cv :: Mat的某个区域中找到非零像素的数量,即在RotatedRect内。

对于常规的Rect,人们可以简单地在ROI上使用countNonZeroPixels。 但是ROI只能是常规(不旋转)矩形。

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

有没有人有如何优雅地解决这个问题的解决方案?

谢谢 !


好的,这是我第一次看到它。

这个想法是将图像旋转到矩形的旋转方向,然后在直线矩形上应用一个圆角。

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

    #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);
    }
    

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

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

    在这里输入图像描述


    为了避免在类似任务中旋转,我使用这样的函数遍历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 */
        }
    }
    
    链接地址: http://www.djcxy.com/p/89715.html

    上一篇: zero pixels in a cv::RotatedRect

    下一篇: grid external export buttons