据我所知,内置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);
}
它可以工作,但是我没有在重新发明轮子,而是在寻找内置的。
建议的解决方案必须比我的解决方案快。
答案 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.png
,g.png
和r.png
,希望它们是您最初的解决方案:
希望有帮助!