Как извлечь внутренний прямоугольник из двоичного изображения вложенных прямоугольников? - PullRequest
0 голосов
/ 01 ноября 2018

Я пытаюсь локализовать ЖК-дисплей в наборе изображений, но в данный момент застрял в определенной точке процесса. Это двоичное изображение области интереса, как мне извлечь из нее внутренний прямоугольник или координаты внутреннего угла границ.

binary image of LCD

Я попробовал следующее, Найдите края на изображении, используя Canny(), используйте findContours(), чтобы найти контуры. Из списка контуров я сталкиваюсь с двумя проблемами,

  1. Какой контур выбрать?
  2. Из этого изображения я получил более 10 контуров, и только внешний прямоугольник является полным прямоугольником. Остальные все контуры представляют собой непересекающиеся линии, которые вместе образуют внутренний прямоугольник

Это мой код,

// threshold
Mat im1_thresh;
threshold(im1, im1_thresh, 100, 200, THRESH_BINARY);        

// find edges
Mat im1_canny;
Canny(im1_thresh, im1_canny, 50, 100);

// find contours
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours(im1_canny, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));

// draw contours
RNG rng;
vector<Rect> boundRect(contours.size());
Mat im1_contours = Mat::zeros(im1_thresh.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++) {
    // draw each contour in a different color
    Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
    drawContours(im1_contours, contours, i, color, 2, 8, hierarchy, 0, Point());

    // draw bounding boxes around each contour in original image
    boundRect[i] = boundingRect(Mat(contours[i]));
    rectangle(im1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
}

Вопрос : Как локализовать внутренний прямоугольник из указанного выше двоичного изображения?

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Чтобы найти самый прямоугольный контур, вы можете запустить minAreaRect, чтобы подогнать повернутый прямоугольник, а затем сравнить результат с исходным контуром.

Соотношение площадей каждого может быть достаточно, в зависимости от шума и т. Д.

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

0 голосов
/ 02 ноября 2018

Из этого изображения я получил более 10 контуров, и только внешний прямоугольник является полным прямоугольником. Остальные все контуры представляют собой непересекающиеся линии, которые вместе образуют внутренний прямоугольник

Вы используете Canny apertureSize = 3 по умолчанию, попробуйте увеличить его до 5 или 7, и он обнаружит внутренний контур как один вместо нескольких маленьких контуров. Попробуйте это:

int apertureSize = 5;
Canny(im1_thresh, im1_canny, 50, 100, apertureSize);

Вчера вечером я столкнулся с другой проблемой: если на экране есть битый пиксель, он также отображается в списке контуров.

Проверьте площадь каждого контура, чтобы убедиться, что он больше минимально допустимой площади. Размер предоставленной вами картинки 250х450, а размер внутреннего прямоугольника ~ 170х380. Таким образом, вы можете установить minArea как 80% от 170x380 (= 0,8 * 64600). Например, добавьте эту проверку в цикл перед рисованием.

float minArea = 0.8 * 64600;   
if (boundRect[i].area() > minArea ){
    rectangle(im1, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
}
0 голосов
/ 01 ноября 2018

Чтобы решить проблему непересекающихся контуров - я корректировал пороговое значение, пока контур не стал гладким. Размытие также помогает иногда. После этого я выбираю самый внутренний контур.

Я использовал массив hierarchy в приведенном выше коде, чтобы выбрать соответствующий контур и создать ограничивающий прямоугольник, используя его на исходном изображении. Массив иерархии представляет собой матрицу N * 4, где N - количество контуров. Для каждого контура hierarchy содержит информацию о связанных контурах как [previous, next, child, parent]. Вы можете увидеть значение -1, если нет связанного контура.

Это матрица иерархии для рассматриваемого изображения,

[- 1, -1,1, -1]
[-1, -1,2,0]
[-1, -1,3,1]
[-1, -1, -1,2]

Меня интересует последний контур. Он бездетен и имеет 2 в качестве родителя. Это моя реализация,

Rect boundRect;

// loop through the contours/hierarchy
for (int i = 0; i<contours.size(); i++) {
    // hierarchy is (previous, next, child, parent)
    // look for innermost -- no child but a parent exists
    if (hierarchy[i][2] == -1 && hierarchy[i][3] != -1) {
        // draw contour
        Scalar color = Scalar(255,0,0);
        drawContours(im1_contours, contours, i, color);

        // draw a bounding rectangle around original image
        boundRect = boundingRect(Mat(contours[i]));
        rectangle(im1, boundRect.tl(), boundRect.br(), color);
    }
}

// subset the image
Mat im1_roi;
im1_roi = im1(boundRect);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...