2017-07-19 20 views
17

Tôi có nhiều hình ảnh của sách năm với chân dung người và tôi đang cố gắng xây dựng một algorytm sẽ phát hiện những bức chân dung đó. Ít nhất, để phát hiện đúng chân dung hình chữ nhật. Example 1Example 2Phát hiện chân dung hình chữ nhật của những người trên hình ảnh với OpenCV

Tôi đang cố gắng để điều tra ba hướng:

  1. nhận diện khuôn mặt
  2. tối phát hiện hình chữ nhật (Kể từ bức chân dung là hình dạng thường sẫm trên nền sáng)
  3. dân tên khai thác từ OCR'ed văn bản

Bằng cách kết hợp các kết quả của ba thuật toán ở trên, tôi hy vọng sẽ nhận được một số phương pháp, sẽ áp dụng được cho nhiều trang niên giám khác nhau.

Tôi sẽ rất cảm kích vì bất kỳ trợ giúp nào cho việc phát hiện hình chữ nhật. tôi bắt đầu với Java và OpenCV 3.

Dưới đây là mã của tôi nộp đơn xin 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); 

Tại thời điểm này, tôi có kết quả như vậy: enter image description here

Cố gắng tìm đường nét từ mép ở trên:

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

Nhận kết quả này: enter image description here

Nhưng không chắc chắn cách trích xuất hình chữ nhật từ các đường viền đó vì nhiều dòng chưa hoàn thành.

Bắt trở lại cạnh và cố gắng tìm dọc và ngang dòng sử dụng HoughLinesP:

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

Kết quả:

enter image description here

Giống như với đường nét, tôi vẫn không nhìn thấy hình chữ nhật đúng khi cho rằng Tôi có thể phát hiện. Bạn có thể giúp tôi với một hướng đúng không? Có thể có một cách dễ dàng hơn để thực hiện tác vụ này?

+1

Các đường nét chưa đầy đủ vì các cạnh chưa đầy đủ. Bạn đã thử các giá trị ngưỡng thấp hơn trong Canny chưa? Ngoài ra, bạn có thể lọc các đường viền nhỏ hơn theo kích thước bằng 'contourArea'. –

+1

Làm thế nào về * tăng * ngưỡng của đường viền và sau đó mở rộng tất cả các đường thẳng đứng và nằm ngang? –

Trả lời

4

nó không phải là một câu trả lời hoàn chỉnh nhưng có thể hữu ích.

tôi lấy hình ảnh bên dưới bằng mã sau.

để hiểu mã bạn có thể tham khảo câu trả lời cũ của tôi tại http://answers.opencv.org/question/85884

nếu nó có vẻ đầy hứa hẹn, chúng tôi sẽ cố gắng để cải thiện nó với nhau.

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

Xin chào, đã từng làm việc trên một dự án tương tự. Tôi đã có một số bức ảnh được xoay và tôi phải làm cho chúng trông bình thường (quay sang trạng thái bình thường). Vì vậy, tôi quản lý để phát hiện xem chúng là nằm ngang hoặc dọc và xoay chúng. Nhưng không thể phát hiện nếu họ được nhân đôi –

+0

bạn có thể đặt một câu hỏi khác với một hình ảnh mẫu và mã của bạn.cho tôi xem nếu tôi giúp bạn. – sturkmen

+0

Bạn có kết quả tốt, cảm ơn. Tôi sẽ xem xét mã của bạn. –

Các vấn đề liên quan