2017-07-19 61 views
17

Mam wiele zdjęć roczników z portretami ludzi i staram się zbudować algorytm, który wykryje te portrety. Przynajmniej, aby wykryć prawidłowe prostokątne portrety. Example 1Example 2Wykryj prostokątne portrety ludzi na obrazach z OpenCV

staram się badać trzech kierunkach:

  1. wykrywania twarzy
  2. Ciemne prostokąty wykrywanie (Od portrety są zwykle ciemniejsze kształty na jaśniejszym tle)
  3. Ludzie ekstrakcji nazwa od OCR'ed teksty

Łącząc wyniki trzech powyższych algorytmów, mam nadzieję uzyskać pewną metodologię, która będzie miała zastosowanie dla wielu różnych stron roczników.

Byłbym bardzo wdzięczny za każdą pomoc w wykryciu prostokątów. Zacząłem Java i OpenCV 3.

Tu jest mój kod stosowany dla 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); 

W tym momencie mam taki wynik: enter image description here

próbując znaleźć kontury od krawędzi powyżej:

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

Uzyskanie tego wyniku: enter image description here

Nie wiem jednak, jak wyodrębnić prostokąty z tych konturów, ponieważ wiele linii jest niekompletnych.

Wracając do krawędzi i próbuje znaleźć pionowe i poziome linie korzystające 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); 
      } 
     } 
    } 

Wynik:

enter image description here

jak z konturami nie, ja wciąż widząc, że odpowiednie prostokąty Mogłem wykryć. Czy możesz mi pomóc we właściwym kierunku? Być może istnieje łatwiejszy sposób wykonania tego zadania?

+1

kontury są niepełne ponieważ krawędzie są niekompletne. Czy próbowałeś niższych wartości progowych w Canny? Możesz także filtrować mniejsze kontury według rozmiaru za pomocą opcji 'contourArea'. –

+1

Co powiecie na: * zwiększenie * progu konturu, a następnie rozciągnięcie wszystkich linii pionowych i poziomych? –

Odpowiedz

4

to nie jest kompletna odpowiedź, ale może być przydatna.

Otrzymam poniższy obraz z poniższym kodem.

zrozumienie kodu można odnieść się do mojego starego odpowiedź na http://answers.opencv.org/question/85884

jeśli wydaje się obiecujący postaramy się poprawić to razem.

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

Witam, kiedyś pracował nad podobnym projektem. Miałem kilka zdjęć, które zostały obrócone i musiałem sprawić, by wyglądały normalnie (obrócić do normalnego stanu). Tak więc udało mi się wykryć, czy są one poziome czy pionowe i obracać je. Ale nie mogłem wykryć, czy są one odzwierciedlone –

+0

możesz zadać inne pytanie z przykładowy obraz i kod. Zobacz, czy ci pomóc. – sturkmen

+0

Masz dobry wynik, dzięki. Opowiem ci o twoim kodzie. –