Есть ли встроенная функция для разделения 3-канального мата на три 3-канальных мата, а не на три 1-канальных мата? - PullRequest
1 голос
/ 06 июня 2019

Насколько я знаю, встроенный split разделит один 3-канальный Mat на три 1-канальных Mat.В результате эти три Mat являются просто серой шкалой с различными интенсивностями.

Мое намерение состоит в том, чтобы получить три 3-канальных Mat следующим образом.

void splitTo8UC3(const Mat& input, vector<Mat>& output)
{
    Mat blue = input.clone();
    Mat green = input.clone();
    Mat red = input.clone();
    const uint N = input.rows * input.step;

    for (uint i = 0; i < N; i += 3)
    {
        // blue.data[i]
        green.data[i] = 0;
        red.data[i] = 0;


        blue.data[i + 1] = 0;
        //green.data[i+1]
        red.data[i + 1] = 0;


        blue.data[i + 2] = 0;
        green.data[i + 2] = 0;
        //red.data[i+2]
    }

    output.push_back(blue);
    output.push_back(green);
    output.push_back(red);
}

Это работаетно вместо того, чтобы заново изобретать колесо, я ищу встроенное, если оно есть.

Редактировать

Предлагаемое решение должно быть быстрее, чем у меня.

1 Ответ

2 голосов
/ 06 июня 2019

РЕДАКТИРОВАТЬ: Я включил предложенные Дэном улучшения из его комментария.


Я не могу думать о встроенной функции, которая точно делает это, и я также не мог ее найти. Но, проводя некоторые исследования, я наткнулся на функцию mixChannels, которая может улучшить ваше решение. По крайней мере, он избегает реализации цикла.

Вот мои модификации вашего кода:

void splitTo8UC3(const cv::Mat& input, std::vector<cv::Mat>& output)
{
    // Allocate outputs
    cv::Mat b(cv::Mat::zeros(input.size(), input.type()));
    cv::Mat g(cv::Mat::zeros(input.size(), input.type()));
    cv::Mat r(cv::Mat::zeros(input.size(), input.type()));

    // Collect outputs
    cv::Mat out[] = { b, g, r };

    // Set up index pairs
    int from_to[] = { 0,0, 1,4, 2,8 };

    cv::mixChannels(&input, 1, out, 3, from_to, 3);
    output.assign(std::begin(out), std::end(out));
}

Давайте получим это тестовое изображение colors.png:

image

And, let's have this test code:

    cv::Mat img = cv::imread("images/colors.png");

    std::vector<cv::Mat> bgr;

    splitTo8UC3(img, bgr);

    cv::imwrite("images/b.png", bgr[0]);
    cv::imwrite("images/g.png", bgr[1]);
    cv::imwrite("images/r.png", bgr[2]);

Затем мы получим следующие выходные данные b.png, g.png и r.png, которые, как мы надеемся, являются теми же, что и для вашего исходного решения:

image image image

Надеюсь, это поможет!

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