2013-03-28 64 views
1

我問了一個類似的問題here,但是這更關注於tesseract。如何確定感興趣的區域,然後使用OpenCV裁剪圖像

我有一個示例圖像如下。我想使我的興趣區域成爲白色方塊,然後剪出這個部分(方塊)並用它創建一個新圖像。我將使用不同的圖像,因此廣場不會始終位於所有圖像的相同位置。所以我需要以某種方式檢測廣場的邊緣。

enter image description here

什麼是一些預處理方法,我能達到的效果?

回答

11

使用您的測試圖像,我能夠刪除所有與一個簡單的erosion運行噪音。

之後,Mat一個簡單的迭代找到角落像素是微不足道的,和我談上this answer。出於測試目的,我們可以得出綠色線在這些點之間,以顯示我們有興趣在原始圖像中的區域:

最後,我設置ROI原始圖像和作物出那部分。

的最終結果顯示在下面的圖片上:

我寫執行使用C++的OpenCV接口此任務的樣本代碼。我對你將這段代碼翻譯成Python的技能很有信心。如果你不能這樣做,忘記密碼,並堅持使用我在這個答案上分享的roadmap

#include <cv.h> 
#include <highgui.h> 

int main(int argc, char* argv[]) 
{ 
    cv::Mat img = cv::imread(argv[1]); 
    std::cout << "Original image size: " << img.size() << std::endl; 

    // Convert RGB Mat to GRAY 
    cv::Mat gray; 
    cv::cvtColor(img, gray, CV_BGR2GRAY); 
    std::cout << "Gray image size: " << gray.size() << std::endl; 

    // Erode image to remove unwanted noises 
    int erosion_size = 5; 
    cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS, 
             cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), 
             cv::Point(erosion_size, erosion_size)); 
    cv::erode(gray, gray, element); 

    // Scan the image searching for points and store them in a vector 
    std::vector<cv::Point> points; 
    cv::Mat_<uchar>::iterator it = gray.begin<uchar>(); 
    cv::Mat_<uchar>::iterator end = gray.end<uchar>(); 
    for (; it != end; it++) 
    { 
     if (*it) 
      points.push_back(it.pos()); 
    } 

    // From the points, figure out the size of the ROI 
    int left, right, top, bottom; 
    for (int i = 0; i < points.size(); i++) 
    { 
     if (i == 0) // initialize corner values 
     { 
      left = right = points[i].x; 
      top = bottom = points[i].y; 
     } 

     if (points[i].x < left) 
      left = points[i].x; 

     if (points[i].x > right) 
      right = points[i].x; 

     if (points[i].y < top) 
      top = points[i].y; 

     if (points[i].y > bottom) 
      bottom = points[i].y; 
    } 
    std::vector<cv::Point> box_points; 
    box_points.push_back(cv::Point(left, top)); 
    box_points.push_back(cv::Point(left, bottom)); 
    box_points.push_back(cv::Point(right, bottom)); 
    box_points.push_back(cv::Point(right, top)); 

    // Compute minimal bounding box for the ROI 
    // Note: for some unknown reason, width/height of the box are switched. 
    cv::RotatedRect box = cv::minAreaRect(cv::Mat(box_points)); 
    std::cout << "box w:" << box.size.width << " h:" << box.size.height << std::endl; 

    // Draw bounding box in the original image (debugging purposes) 
    //cv::Point2f vertices[4]; 
    //box.points(vertices); 
    //for (int i = 0; i < 4; ++i) 
    //{ 
    // cv::line(img, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 1, CV_AA); 
    //} 
    //cv::imshow("Original", img); 
    //cv::waitKey(0); 

    // Set the ROI to the area defined by the box 
    // Note: because the width/height of the box are switched, 
    // they were switched manually in the code below: 
    cv::Rect roi; 
    roi.x = box.center.x - (box.size.height/2); 
    roi.y = box.center.y - (box.size.width/2); 
    roi.width = box.size.height; 
    roi.height = box.size.width; 
    std::cout << "roi @ " << roi.x << "," << roi.y << " " << roi.width << "x" << roi.height << std::endl; 

    // Crop the original image to the defined ROI 
    cv::Mat crop = img(roi); 

    // Display cropped ROI 
    cv::imshow("Cropped ROI", crop); 
    cv::waitKey(0); 

    return 0; 
} 
+0

感謝您的迴應。我目前正在嘗試將您提供給JavaCV的C代碼進行轉換:)。再次感謝。 – birdy

+0

無需感謝我,只需投票答案。考慮點擊附近的複選框將其選爲正式答案。通過做這些事情你會幫助未來的遊客。 – karlphillip

+0

行「if(* it)」代表/代表什麼? – birdy

4

看到該文本是唯一的大團塊,一切勉強大於一個像素,一個簡單的形態開應該足夠

你可以這樣做in opencvwith imagemagic

之後的白色矩形應該是圖像中剩下的唯一東西。你可以用opencvs findcontours發現,與CvBlobs庫OpenCV的或與ImageMagick的-crop功能

這裏是2步侵蝕之後2步擴張的應用圖像: enter image description here 您可以簡單地將這個圖像轉換成OpenCV的findContours功能在Squares tutorial example獲得位置

+0

這將用於檢測正方形,但是,您提供的結果圖像模糊了文本。我希望廣場內的文字保持不變,因爲最終我想將該文字提供給OCR。請讓我知道是否有更好的方法來實現我想要做的事 – birdy

+0

當你有矩形(甚至沒有填充)時,這很容易 - 使用findContours函數(http://docs.opencv.org/doc/tutorials /imgproc/shapedescriptors/find_contours/find_contours.html)來查找矩形的輪廓(可能會發現多個輪廓 - 只取最大的輪廓),然後用白色填充。您將填充矩形,因此現在只需在該圖像和原始圖片上使用按位和(http://docs.opencv.org/modules/core/doc/operations_on_arrays.html#bitwise-and)。 – cyriel