Получите выходы заливки (связанные пиксели), скопированные в новый мат

Есть ли удобный способ создать новый мат из выходов операции floodfill? Я хочу получить мат только из пикселей, которые обнаружены как связанные с начальным пикселем и технически заполнены заливкой.

Угадайте, что я применил метод floodFill к определенной исходной точке, и только 1/4 от общего числа пикселей были заполнены по мере их соединения. Я хочу скопировать эти пиксели только в новое изображение, которое представляет только те 1/4 числа пикселей и, скорее всего, меньше исходного входного изображения.

В любом случае, я сделал это с помощью очень долгого подхода, требующего больше времени + процессора. Короче говоря, мой подход заключался в том, чтобы давать разные цвета для разных вызовов floodfill и хранить записи пикселей одного цвета в отдельной структуре данных и т. д.

Я хочу знать, есть ли прямой и более простой подход с использованием маски, созданной floodfill, или с использованием любого другого подхода.


person Samitha Chathuranga    schedule 24.08.2015    source источник


Ответы (1)


Не совсем понятно, что именно вам нужно. Пожалуйста, взгляните на этот код и проверьте, соответствует ли croppedResult тому, что вам нужно.

#include <opencv2\opencv.hpp>
using namespace cv;

int main()
{
    // Create a test image
    Mat1b img(300, 200, uchar(0));
    circle(img, Point(150, 200), 30, Scalar(255));
    rectangle(img, Rect(30, 50, 40, 20), Scalar(255));
    rectangle(img, Rect(100, 80, 30, 40), Scalar(255));

    // Seed inside the circle
    Point seed(160, 220);

    // Setting up a mask with correct dimensions
    Mat1b mask;
    copyMakeBorder(img, mask, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(0));

    Rect roi;
    uchar seedColor = 200;
    floodFill(img, mask,
        seed + Point(1,1),  // Since the mask is larger than the filled image, a pixel (x,y) in image corresponds to the pixel (x+1,y+1) in the mask
        Scalar(0),          // If FLOODFILL_MASK_ONLY is set, the function does not change the image ( newVal is ignored),
        &roi,               // Minimum bounding rectangle of the repainted domain.
        Scalar(5),          // loDiff
        Scalar(5),          // upDiff 
        4 | (int(seedColor) << 8) | FLOODFILL_MASK_ONLY);
        // 4-connected | with defined seedColor | use only the mask 

    // B/W image, where white pixels are the one set to seedColor by floodFill
    Mat1b result = (mask == seedColor);

    // Cropped image
    roi += Point(1,1);
    Mat1b croppedResult = result(roi);

    return 0;
}

Тестовое изображение img:

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

Маска mask после floodFill:

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

Маска result всего с seedColor пикселями:

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

Обрезанная маска croppedResult:

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


ОБНОВЛЕНИЕ

    // B/W image, where white pixels are the one set to seedColor by floodFill
    Mat1b resultMask = (mask == seedColor);
    Mat1b resultMaskWithoutBorder = resultMask(Rect(1,1,img.cols,img.rows));

    Mat3b originalImage;
    cvtColor(img, originalImage, COLOR_GRAY2BGR); // Probably your original image is already 3 channel

    Mat3b imgMasked(img.size(), Vec3b(0,0,0));
    originalImage.copyTo(imgMasked, resultMaskWithoutBorder);

    Mat3b croppedResult = imgMasked(roi);
    return 0;
person Miki    schedule 24.08.2015
comment
Спасибо за ответ. Но я не понимаю этих утверждений.||||| Результат Mat1b = (маска == seedColor); // Обрезанное изображение roi += Point(1,1); Mat1b croppedResult = результат(ROI);|||| А что это за параметр roi флудфилла и что там хранится? - person Samitha Chathuranga; 25.08.2015
comment
Выберите только пиксель со значением == seedColor; переместите Rect на 1 пиксель вниз и на 1 пиксель вправо; получить подматрицу, используя Rect. Как говорит документ, roi - это ограничивающая рамка заполненных точек. - person Miki; 25.08.2015
comment
Очень интересно..!!! Но почему мы должны переводить Rect на 1 пиксель вниз и на 1 пиксель вправо? Это потому, что roi дается в связи с исходным изображением и? Я знаю, что маска в любом случае на 1 пиксель шире и выше оригинала, и происходит ли увеличение сверху и слева? - person Samitha Chathuranga; 25.08.2015
comment
Да, точно. Маска на 2 пикселя больше исходного изображения (1 слева, 1 справа) и на 2 пикселя выше (1 вверху, 1 внизу) - person Miki; 25.08.2015
comment
И я думаю, что, поскольку я хочу, наконец, получить часть исходного изображения, обрезка также должна быть сделана из исходного изображения. то есть: Mat1b croppedResult = img(roi); (roi += Point(1,1); вызов производить не следует) - person Samitha Chathuranga; 25.08.2015
comment
Да, вы можете обрезать исходное изображение без добавления точки (1,1) - person Miki; 25.08.2015
comment
Но теперь возникает другая проблема. Пиксели, которые находятся за пределами области круга, но все же внутри ограничивающей записи, также будут скопированы из исходного изображения. Мне нужны только пиксели в области круга. - person Samitha Chathuranga; 25.08.2015
comment
Проверьте обновленный ответ. Вам просто нужно использовать copyTo с маской. Вы должны позаботиться об инициализации матриц и согласовании размеров и каналов. - person Miki; 25.08.2015
comment
Хорошо, я вернусь к вам после того, как попробую это. Я думаю, что это сделает мою работу. - person Samitha Chathuranga; 25.08.2015
comment
Еще одна вещь.|| Mat1b resultMask = (маска == seedColor); Что здесь произошло на самом деле. Я имею в виду, как выполняется матричная операция? Я не знаком с такими операциями. Если объяснение больше, соответствующая ссылка приветствуется. - person Samitha Chathuranga; 25.08.2015
comment
OpenCV MatExpr: Сравнение: A cmpop B, A cmpop alpha, alpha cmpop A, где cmpop — одно из: ›, ›=, ==, !=, ‹=, ‹. Результатом сравнения является 8-битная одноканальная маска, элементы которой устанавливаются в 255 (если конкретный элемент или пара элементов удовлетворяют условию) или 0. - person Miki; 25.08.2015
comment
По сути, он создает двоичную маску resultMask, где пикселям, значение которых равно seedColor в mask, присваивается значение 255 или 0 в противном случае. - person Miki; 25.08.2015