Подтвердить что ты не робот

Обнаружение прямоугольных портретов людей на изображениях с помощью OpenCV

У меня много изображений ежегодников с портретами людей, и я пытаюсь построить алгорифм, который обнаружит эти портреты. По крайней мере, для обнаружения правильных прямоугольных портретов. Пример 1 Пример 2

Я пытаюсь исследовать три направления:

  • Распознавание лиц
  • Определение темных прямоугольников (поскольку портреты обычно более темные на более ярком фоне)
  • Удаление имен людей из текстов OCR

Объединив результаты трех алгоритмов выше, я надеюсь получить некоторую методологию, которая будет применима для многих разных страниц ежегодников.

Я был бы очень признателен за любую помощь в обнаружении прямоугольников. Я начал с Java и OpenCV 3.

Вот мой код для изображение:

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

В этот момент у меня есть такой результат: введите описание изображения здесь

Попытка найти контуры по краям выше:

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

Получение этого результата: введите описание изображения здесь

Но не уверен, как извлечь прямоугольники из этих контуров, поскольку многие из строк являются неполными.

Возвращаясь к краям и пытаясь найти вертикальные и горизонтальные линии с помощью 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);
            }
        }
    }

Результат:

введите описание изображения здесь

Как и с контурами, я все еще не вижу правильных прямоугольников, которые я мог обнаружить. Не могли бы вы помочь мне в правильном направлении? Может быть, есть более простой способ выполнить эту задачу?

4b9b3361

Ответ 1

это не полный ответ, но, возможно, полезный.

Я получаю изображение ниже со следующим кодом.

чтобы понять код, на который вы можете ссылаться на мой старый ответ на http://answers.opencv.org/question/85884

если кажется перспективным, мы попытаемся улучшить его вместе.

введите описание изображения здесь

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