2011-07-11 27 views
3

正如標題所說我試圖找到一個品種的某個區域的非零像素數::墊,即內RotatedRect。在簡歷數的非零像素:: RotatedRect

對於常規的矩形一個可以簡單地在ROI使用countNonZeroPixels。但是ROI只能是常規(不旋轉)矩形。

另一個想法是繪製旋轉矩形並使用它作爲掩模。然而,openCV既不支持旋轉矩形的繪製,也不支持countNonZeroPixels接受一個掩碼。

有沒有人有如何優雅地解決這個問題的解決方案?

謝謝!

+0

嗯,所以我沒有拿出一個解決方案,但我不能回答我的問題呢。我明天 - 如果任何人都有自己的想法,直到那時,我很好奇,你就會想出:) – joekr

+0

我添加了一個新的想法,我認爲這可能是更容易實現 – Entreco

回答

3

好的,這是我的第一個看法。

的想法是將圖像旋轉反向矩形的旋轉比在筆直的矩形應用的投資回報率。

  • 這將打破,如果旋轉矩形並不是完全在圖像中
  • 你或許可以加快這通過旋轉之前將另一投資回報率,以避免旋轉整個圖像...

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

一個完全不同的方法可能是旋轉你的圖像(在相反的方向),並仍然使用矩形ROI與countNonZeroPixels結合。唯一的問題將是,你必須圍繞ROI中心的樞軸旋轉圖像...

使其更清晰,見附件例如:

enter image description here

+0

我不明白這是怎麼不完全是上面的代碼確實... – joekr

+0

你是對的。我只看到了代碼,很快就認爲它是這樣的。 Excusez-moi – Entreco

+0

順便說一句,您可以在答案中自由使用該圖片,作爲解決方案中的其他見解 – Entreco

0

爲了避免在旋轉類似的任務我遍歷每個像素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 */ 
    } 
}