2017-07-19 2 views
17

J'ai beaucoup d'images d'annuaires avec des portraits de personnes et j'essaye de construire un algorithme qui détectera ces portraits. Au moins, pour détecter les portraits rectangulaires corrects. Example 1Example 2Détecter des portraits rectangulaires de personnes sur des images avec OpenCV

Je suis en train d'étudier trois directions:

  1. Détection des visages
  2. détection des rectangles noir (Comme portraits sont des formes généralement plus sombres sur fond clair)
  3. personnes d'extraction de nom de OCR'ed textes

En combinant les résultats de trois algorithmes ci-dessus, j'espère obtenir une méthodologie, qui sera applicable pour de nombreuses pages d'annuaires différentes.

Je serais très reconnaissant pour toute aide pour la détection de rectangles. J'ai commencé avec Java et OpenCV 3.

Voici mon code demandé 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); 

À ce stade, je dois ce résultat: enter image description here

Essayer de trouver les contours des bords ci-dessus:

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

Obtenir ce résultat: enter image description here

Mais vous ne savez pas comment extraire des rectangles de ces contours car beaucoup de lignes sont incomplètes.

Pour en revenir aux bords et en essayant de trouver des lignes verticales et horizontales à l'aide 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); 
      } 
     } 
    } 

Résultat:

enter image description here

Comme avec les contours, je ne suis toujours pas voir rectangles corriger les Je pourrais détecter. Pourriez-vous m'aider avec une direction correcte? Peut-être qu'il existe un moyen plus facile d'effectuer cette tâche?

+1

Les contours sont incomplets car les bords sont incomplètes. Avez-vous essayé des valeurs de seuil inférieures dans Canny? Vous pouvez également filtrer les petits contours par taille avec 'contourArea'. –

+1

Que diriez-vous d'augmenter le seuil du contour et d'étendre toutes les lignes verticales et horizontales? –

Répondre

4

ce n'est pas une réponse complète mais peut-être utile.

Je reçois l'image ci-dessous avec le code suivant.

pour comprendre le code que vous pouvez vous référer à ma vieille réponse à http://answers.opencv.org/question/85884

si elle semble prometteuse, nous allons essayer de l'améliorer ensemble.

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

Bonjour, je travaillais sur un projet similaire. J'avais quelques photos qui ont été tournées et j'ai dû les faire paraître normales (tourner à un état normal). J'ai donc réussi à détecter si elles sont horizontales ou verticales et les faire pivoter. Mais ne pouvait pas détecter si elles sont en miroir –

+0

vous pouvez poser une autre question avec un exemple d'image et votre code.let me voir si je vous aide. – sturkmen

+0

Vous avez un bon résultat, merci. Je vais jeter un oeil à votre code. –