2017-07-19 70 views
17

我有許多人像肖像的年鑑圖像,我正在嘗試構建能檢測這些肖像的algorytm。至少,要檢測正確的矩形肖像。 Example 1Example 2使用OpenCV檢測圖像上人物的長方形肖像

我試圖研究三個方向:

  1. 人臉檢測
  2. 黑暗矩形檢測(自畫像是在明亮的背景通常更暗的形狀)
  3. 人們從OCR'ed名稱提取文本

通過結合上述三種算法的結果,我希望能得到一些方法,也可以用到對於許多不同的年鑑頁面。

我將非常感謝任何幫助矩形檢測。 我開始使用Java和OpenCV 3.

這裏被應用於an image我的代碼:

System.loadLibrary(Core.NATIVE_LIBRARY_NAME); 
Mat source = Imgcodecs.imread("Path/to/image", Imgcodecs.CV_LOAD_IMAGE_ANYCOLOR); 
Mat destination = new Mat(source.rows(), source.cols(), source.type()); 

Imgproc.cvtColor(source, destination, Imgproc.COLOR_RGB2GRAY); 
Imgproc.GaussianBlur(destination, destination, new Size(5, 5), 0, 0, Core.BORDER_DEFAULT); 

int threshold = 100; 
Imgproc.Canny(destination, destination, 50, 100); 
Imgproc.Canny(destination, destination, threshold, threshold*3); 

在這一點上,我有這樣的結果: enter image description here

試圖找到從邊緣輪廓以上:

List<MatOfPoint> contourDetections = new ArrayList<>(); 
    Mat hierarchy = new Mat(); 

    // Find contours 
    Imgproc.findContours(destination, contourDetections, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); 

    // Draw contours 
    Imgproc.drawContours(source, contours, -1, new Scalar(255,0,0), 2); 

獲得此結果: enter image description here

但不知道如何從這些輪廓中提取矩形,因爲許多行不完整。

Mat lines = new Mat(); 
    int thre = 50; 
    int minLineSize = 250; 
    int lineGap = 80; 

    int ignoreLinesShorter = 300; 

    Imgproc.HoughLinesP(destination, lines, 1, Math.PI/180, thre, minLineSize, lineGap); 

    for(int c = 0; c < lines.rows(); c++) { 

     double[] vec = lines.get(c, 0); 

     double x1 = vec[0], 
       y1 = vec[1], 
       x2 = vec[2], 
       y2 = vec[3]; 

     // Filtering only verticat and horizontal lines 
     if(x1 == x2 || y1 == y2) { 

      // Filtering out short lines 
      if(Math.abs(x1 - x2) > ignoreLinesShorter || Math.abs(y1 - y2) > ignoreLinesShorter) { 

       Point start = new Point(x1, y1); 
       Point end = new Point(x2, y2); 

       // Draw line 
       Imgproc.line(source, start, end, new Scalar(0,0,255), 2); 
      } 
     } 
    } 

結果:使用HoughLinesP

再回到邊緣,並試圖找到垂直和水平線

enter image description here

用一樣的輪廓,我仍然沒有看到正確的是矩形我可以檢測到。你能幫助我一個正確的方向嗎?也許有一個更簡單的方法來執行此任務?

+1

輪廓是不完整的。你在Canny嘗試了較低的閾值嗎?你也可以用'contourArea'按尺寸過濾較小的輪廓。 –

+1

*如何增加*輪廓的閾值,然後擴展所有的垂直和水平線? –

回答

4

這不是一個完整的答案,但可能有用。

我用下面的代碼得到下面的圖像。

明白,你可以在http://answers.opencv.org/question/85884

參考我以前的答案,如果它似乎有希望,我們會盡量一起提高它的代碼。因爲邊緣是不完整的

enter image description here

#include <opencv2/highgui.hpp> 
#include <opencv2/imgproc.hpp> 

using namespace cv; 

int main(int argc, char** argv) 
{ 
    Mat img = imread("e:/test/twHVm.jpg"); 
    if (img.empty()) 
     return -1; 

    Mat resized, gray, reduced_h, reduced_w; 
    resize(img, resized, Size(), 1, 1); 

    cvtColor(resized, gray, CV_BGR2GRAY); 

    reduce(gray, reduced_h, 0, REDUCE_AVG); 
    reduce(gray, reduced_w, 1, REDUCE_AVG); 


    for (int i = 0; i < img.cols; i++) 
    { 
     if (reduced_h.at<uchar>(0, i) > 200) // this is experimental value 
     line(resized, Point(i, 0), Point(i, img.rows), Scalar(0, 255, 0), 1); 
    } 

    for (int i = 0; i < img.rows; i++) 
    { 
     if (reduced_w.at<uchar>(i, 0) > 225) // this is experimental value 
     line(resized, Point(0, i), Point(img.cols, i), Scalar(0, 255, 0), 1); 
    } 

    imshow("result", resized); 
    waitKey(0); 
    return 0; 
} 
+0

嗨,曾經在類似的項目上工作。我有一些照片旋轉,我不得不讓它們看起來很正常(旋轉到正常狀態)。所以我設法檢測它們是水平的還是垂直的並旋轉它們。但無法檢測到它們是否被鏡像 –

+0

您可以通過示例圖像和代碼提出另一個問題。請讓我看看我是否可以幫助您。 – sturkmen

+0

你有一個很好的結果,謝謝。我會看看你的代碼。 –