首先拿到一张图片,通过split()函数把图像的RGB值分别拿出来存到到一个vector容器中,然后以灰度图像(即单通道)的形式分别输出R,G,B的值,再把R,G,B的值单独以彩色图像(三通道)的形式输出,达到下图的效果
写出代码如下:
int main()
{
Mat image = imread("F:/cv/1.bmp");
imshow("原图像", image);
std::vector<Mat> mv;//存储分离后的管道
split(image, mv); // 管道分离
imshow("蓝色通道", mv[0]);
imshow("绿色通道", mv[1]);
imshow("红色通道", mv[2]);
std::vector<Mat> blue(mv);
std::vector<Mat> green(mv);
std::vector<Mat> red(mv);
Mat dst;//存储输出图像
blue[1] = 0;
blue[2] =0;
merge(blue, dst);
imshow("蓝色图像", dst);
green[0] = 0;
green[2] =0;
merge(green, dst);
imshow("绿色图像", dst);
red[0] = 0;
red[1] = 0;
merge(red, dst);
imshow("红色图像", dst);
}
上述代码创建一个容器对象mv存储分离后的通道值,mv[0] -> 蓝色,mv[1] -> 绿色,mv[2] -> 红色.
如果要以彩色图像分别输出图像的B,G,R值,再创建三个容器对象,blue,green,red.(此处创建方式有问题),要拿到blue的蓝色值,就要把红和绿全部过滤,代码实现为 (blue[1] = 0; blue[2] = 0;),同理单独拿到green的绿色值,red的红色值,之后通过merge()函数合并三个通道的值,输出,结果却出了问题
输出的红色图像和绿色图像全为黑色,这是因为创建容器对象blue,green,red的时候出了问题
std::vector<Mat> blue(mv);
std::vector<Mat> green(mv);
std::vector<Mat> red(mv);
因为Mat类并不是像int一样,是系统自带的数据类型,所以这种创建方式会调用vector的默认拷贝构造,即浅拷贝。造成的结果就是这个三个容器对象数据完全共享,这三个对象都指向mv,所以第一次输出彩色图像时可以正常输出,但第二次输出绿色图像时,green[1]的值已经全被 blue[1]=0; 的操作全被改为了0,此时只有green[0]还正常存储图像的蓝色值,但是后面的代码把蓝色值也赋值为0,最终导致这三个矩阵green[0],green[1],green[2]都是0,然后就输出了纯黑图像,代码运行到red,自然也是纯黑。
所以我们要创建三个相互独立的容器对象blue,green,red,只需把原来用来创建的的三行代码替换为下面的内容:
std::vector<Mat> blue;//蓝
for (const Mat& m : mv)
{
blue.push_back(m.clone());
}
std::vector<Mat> green;
for (const Mat& m : mv)//绿
{
green.push_back(m.clone());
}
std::vector<Mat> red;//红
for (const Mat& m : mv)
{
red.push_back(m.clone());
}
此处使用枚举循环进行构造,参考此文:(4条消息) C++:枚举循环,全局作用域,子类调用父类函数,const类成员赋值_头发乌黑茂密的博客-CSDN博客
创建的每个容器对象,都是通过mv的克隆函数构造的,彼此相互独立(也可以使用copyTo函数),这样就可以达到我们的目的了。