opencv
中默认读取的图片格式是BGR
,并非RGB
.
下面是opencv
更直接的BGR
转RGB
方法:
cv::cvtColor(bgr_img, rgb_img, cv::COLOR_BGR2RGB);
关于cv::split()
与cv::merge()
更细节的直观展示内容可以参考这篇博文:图像通道分离与合并——cv::split()与cv::merge()详解
void split(
const cv::Mat& src_img, //输入图像
std::vector<Mat>& mat_vct // 输出的多通道序列(n个单通道序列)
);
void merge(
const vector<cv::Mat>& mat_vct, // 输入的多通道序列(n个单通道序列)
cv::OutputArray dst // 输出图像(cv::OutputArray可以理解为等价于cv::Mat类型)
);
注意上面两个函数:
cv::split
的输入是cv::Mat
,输出是std::vector
;
cv::merge
的输入是std::vector
,输出是cv::Mat
。
cv::Mat::convertTo(cv::OutputArray m, int type )
用法:
//将cv::Mat类型的mat_1转换为CV_8UC3类型,输出到cv::Mat类型的mat_2中,mat_1值不变
mat_1.convertTo(mat_2, CV_8UC3);
下面是通道的分离与合并的例子:
cv::Mat src_img=cv::imread("./lena.png",1); //1是BGR,0是单通道灰度图
std::string window_name = "origin:BGR";
cv::namedWindow(window_name, 0);
cv::imshow(window_name, src_img);
cv::waitKey(1);
std::vector<cv::Mat> mat_vct_1(3);
cv::split(src_img, mat_vct_1); //这句话把src_img分离为三个Mat
//其实这个mat_vct_2有点多余,完全可以直接使用mat_vct_1进行merge即可。
//之所以这里增加一个mat_vct_2变量,是测试修改通道顺序看效果
std::vector<cv::Mat> mat_vct_2;
//下面[0]、[1]、[2]分别表示B、G、R通道
//下面从[2]到[0]进行push_back就是变成了RGB顺序通道
mat_vct_2.push_back(mat_vct_1[2]);
mat_vct_2.push_back(mat_vct_1[1]);
mat_vct_2.push_back(mat_vct_1[0]);
cv::Mat dst_img;
cv::merge(mat_vct_2, dst_img); //这句话把mat_vct_2合并为一个3通道的Mat
window_name = "RGB";
cv::namedWindow(window_name, 0);
cv::imshow(window_name, dst_img);
cv::waitKey(0);
上面的做法没有使用convertTo
函数进行数据类型转换,会保持原来的数据类型。
下面的操作是使用convertTo
函数进行数据类型转换,如16位
转化为32位
等操作,cv::Mat::type()
的值和图片的 通道数 无关,例如,数据类型是CV_8U
,而不是CV_8UC3
这样的带通道的描述。
此处type
返回的是一个int
,具体的类型如下表:
例如:type()
返回0
就表示CV_8UC1
,返回16
就表示CV_8UC3
。
convertTo
函数进行数据类型转换:cv::Mat src_img=cv::imread("./lena.png",0); //BGR
std::vector<cv::Mat> mat_vct_1(3);
cv::split(src_img, mat_vct_1); //这句话把src_img分离为三个Mat
cv::Mat b_channel,g_channel,r_channel;
mat_vct_1.at(0).convertTo(b_channel, CV_8UC1);
mat_vct_1.at(1).convertTo(g_channel, CV_8UC1);
mat_vct_1.at(2).convertTo(r_channel, CV_8UC1);
下面是把存有3个cv::Mat
的vector
变量mat_vct_1
合并为一个三通道cv::Mat
的图像dst_img
cv::Mat img_tmp,dst_img;
//这句话把mat_vct_1合并为一个3通道的Mat: img_tmp
cv::merge(mat_vct_1, img_tmp);
//将img_tmp转换为CV_8UC3类型,输出到dst_img中
img_tmp.convertTo(dst_img, CV_8UC3);
测试
时的编译命令:
g++ `pkg-config opencv --cflags` test.cpp -std=c++11 -pthread -o test `pkg-config opencv --libs`
不同颜色通道组合
后是什么颜色:int main(void) {
int cols = 500, rows = 500;
cv::Mat img_b = cv::Mat::zeros(cv::Size(cols, rows), CV_8UC1) + 255;
cv::Mat img_g = cv::Mat::zeros(cv::Size(cols, rows), CV_8UC1);
cv::Mat img_r = cv::Mat::zeros(cv::Size(cols, rows), CV_8UC1);
std::vector<cv::Mat> mat_vct;
//下面[0]、[1]、[2]分别表示B、G、R通道
//下面从[2]到[0]进行push_back就是变成了RGB顺序通道
mat_vct.push_back(img_b);
mat_vct.push_back(img_g);
mat_vct.push_back(img_r);
cv::Mat dst_img;
cv::merge(mat_vct, dst_img); //这句话把mat_vct合并为一个3通道的Mat
std::string window_name = "img";
cv::namedWindow(window_name, 0);
cv::imshow(window_name, dst_img);
cv::waitKey(0);
return 0;
}