Number of non-zero pixels in a cv::RotatedRect

旧巷老猫 提交于 2020-01-10 20:10:44

问题


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 !


回答1:


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



回答2:


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:




回答3:


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 */
    }
}


来源:https://stackoverflow.com/questions/6653272/number-of-non-zero-pixels-in-a-cvrotatedrect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!