是否有内置功能将3通道Mat分成三个3通道Mat,而不是三个1通道Mat?

时间:2019-06-06 08:39:07

标签: opencv

据我所知,内置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 个答案:

答案 0 :(得分:2)

编辑:我结合了Dan从他的评论中提出的改进建议。


我想不出一个内置函数可以做到这一点,而且我也找不到。但是在进行一些研究时,我遇到了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

然后,我们有以下测试代码:

    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.pngg.pngr.png,希望它们是您最初的解决方案:

希望有帮助!