先看函数类型
CV_EXPORTS_W void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
//InputArray src:输入图像
//OutputArray dst:输出图像
//int code为颜色转换空间标志符
//int dstCn = 0:目标图像的通道数,如果该参数为0,通道数取原图像的通道数
关于int code这个参数,比如常见的 COLOR_BGR2GRAY等,详细见下表
1、RGB和BGR(opencv默认的彩色图像的颜色空间是BGR)颜色空间的转换
cv::COLOR_BGR2RGB
cv::COLOR_RGB2BGR
cv::COLOR_RGBA2BGRA
cv::COLOR_BGRA2RGBA
2、向RGB和BGR图像中增添alpha通道
cv::COLOR_RGB2RGBA
cv::COLOR_BGR2BGRA
3、从RGB和BGR图像中去除alpha通道
cv::COLOR_RGBA2RGB
cv::COLOR_BGRA2BGR
4、从RBG和BGR颜色空间转换到灰度空间
cv::COLOR_RGB2GRAY
cv::COLOR_BGR2GRAY
cv::COLOR_RGBA2GRAY
cv::COLOR_BGRA2GRAY
5、从灰度空间转换到RGB和BGR颜色空间
cv::COLOR_GRAY2RGB
cv::COLOR_GRAY2BGR
cv::COLOR_GRAY2RGBA
cv::COLOR_GRAY2BGRA
6、RGB和BGR颜色空间与BGR565颜色空间之间的转换
cv::COLOR_RGB2BGR565
cv::COLOR_BGR2BGR565
cv::COLOR_BGR5652RGB
cv::COLOR_BGR5652BGR
cv::COLOR_RGBA2BGR565
cv::COLOR_BGRA2BGR565
cv::COLOR_BGR5652RGBA
cv::COLOR_BGR5652BGRA
7、灰度空间域BGR565之间的转换
cv::COLOR_GRAY2BGR555
cv::COLOR_BGR5552GRAY
8、RGB和BGR颜色空间与CIE XYZ之间的转换
cv::COLOR_RGB2XYZ
cv::COLOR_BGR2XYZ
cv::COLOR_XYZ2RGB
cv::COLOR_XYZ2BGR
9、RGB和BGR颜色空间与uma色度(YCrCb空间)之间的转换
cv::COLOR_RGB2YCrCb
cv::COLOR_BGR2YCrCb
cv::COLOR_YCrCb2RGB
cv::COLOR_YCrCb2BGR
10、RGB和BGR颜色空间与HSV颜色空间之间的相互转换
cv::COLOR_RGB2HSV
cv::COLOR_BGR2HSV
cv::COLOR_HSV2RGB
cv::COLOR_HSV2BGR
11、RGB和BGR颜色空间与HLS颜色空间之间的相互转换
cv::COLOR_RGB2HLS
cv::COLOR_BGR2HLS
cv::COLOR_HLS2RGB
cv::COLOR_HLS2BGR
12、RGB和BGR颜色空间与CIE Lab颜色空间之间的相互转换
cv::COLOR_RGB2Lab
cv::COLOR_BGR2Lab
cv::COLOR_Lab2RGB
cv::COLOR_Lab2BGR
13、RGB和BGR颜色空间与CIE Luv颜色空间之间的相互转换
cv::COLOR_RGB2Luv
cv::COLOR_BGR2Luv
cv::COLOR_Luv2RGB
cv::COLOR_Luv2BGR
14、Bayer格式(raw data)向RGB或BGR颜色空间的转换
cv::COLOR_BayerBG2RGB
cv::COLOR_BayerGB2RGB
cv::COLOR_BayerRG2RGB
cv::COLOR_BayerGR2RGB
cv::COLOR_BayerBG2BGR
cv::COLOR_BayerGB2BGR
cv::COLOR_BayerRG2BGR
cv::COLOR_BayerGR2BGR
来看一段小程序,将彩色图转换成灰度图,注意,读的通道格式是BGR
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread("F:/Digital-image-project/BMPimages/DIP3E_Original_Images_CH06/Fig0635(top_ left_flower).bmp");
imshow("原图", img);
Mat dstImg;
cvtColor(img, dstImg, COLOR_BGR2GRAY);
imshow("灰度图", dstImg);
waitKey(0);
system("pause");
return 0;
}
我们来简单看一下cvtcolor这个函数的源码,这里用case来选择code颜色空间转换标志符,由于比较多,就先看一个BGR2GRAY的
void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn )
{
CV_INSTRUMENT_REGION()
int stype = _src.type();//表示Mat的类型,是一系列预定义的常量,CV_(位数)+(数据类型)+(通道数)
int scn = CV_MAT_CN(stype), depth = CV_MAT_DEPTH(stype), uidx, gbits, ycn;//scn为通道数、depth为每一个像素对应的位数
CV_OCL_RUN( _src.dims() <= 2 && _dst.isUMat() && !(depth == CV_8U && (code == COLOR_Luv2BGR || code == COLOR_Luv2RGB)),
ocl_cvtColor(_src, _dst, code, dcn) )
Mat src, dst;
if (_src.getObj() == _dst.getObj()) // inplace processing (#6653)
_src.copyTo(src);
else
src = _src.getMat();
Size sz = src.size();//得到src的Size信息,后面可以根据这个构造矩阵
CV_Assert( depth == CV_8U || depth == CV_16U || depth == CV_32F );
switch( code )
{
case COLOR_BGR2BGRA: case COLOR_RGB2BGRA: case COLOR_BGRA2BGR:
case COLOR_RGBA2BGR: case COLOR_RGB2BGR: case COLOR_BGRA2RGBA:
CV_Assert( scn == 3 || scn == 4 );
dcn = code == COLOR_BGR2BGRA || code == COLOR_RGB2BGRA || code == COLOR_BGRA2RGBA ? 4 : 3;
_dst.create( sz, CV_MAKETYPE(depth, dcn));
dst = _dst.getMat();
hal::cvtBGRtoBGR(src.data, src.step, dst.data, dst.step, src.cols, src.rows,
depth, scn, dcn, swapBlue(code));
break;
case COLOR_BGR2BGR565: case COLOR_BGR2BGR555: case COLOR_RGB2BGR565: case COLOR_RGB2BGR555:
case COLOR_BGRA2BGR565: case COLOR_BGRA2BGR555: case COLOR_RGBA2BGR565: case COLOR_RGBA2BGR555:
CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U );
gbits = code == COLOR_BGR2BGR565 || code == COLOR_RGB2BGR565 ||
code == COLOR_BGRA2BGR565 || code == COLOR_RGBA2BGR565 ? 6 : 5;
_dst.create(sz, CV_8UC2);
dst = _dst.getMat();
hal::cvtBGRtoBGR5x5(src.data, src.step, dst.data, dst.step, src.cols, src.rows,
scn, swapBlue(code), gbits);
break;
case COLOR_BGR5652BGR: case COLOR_BGR5552BGR: case COLOR_BGR5652RGB: case COLOR_BGR5552RGB:
case COLOR_BGR5652BGRA: case COLOR_BGR5552BGRA: case COLOR_BGR5652RGBA: case COLOR_BGR5552RGBA:
if(dcn <= 0) dcn = (code==COLOR_BGR5652BGRA || code==COLOR_BGR5552BGRA || code==COLOR_BGR5652RGBA || code==COLOR_BGR5552RGBA) ? 4 : 3;
CV_Assert( (dcn == 3 || dcn == 4) && scn == 2 && depth == CV_8U );
gbits = code == COLOR_BGR5652BGR || code == COLOR_BGR5652RGB ||
code == COLOR_BGR5652BGRA || code == COLOR_BGR5652RGBA ? 6 : 5;
_dst.create(sz, CV_MAKETYPE(depth, dcn));
dst = _dst.getMat();
hal::cvtBGR5x5toBGR(src.data, src.step, dst.data, dst.step, src.cols, src.rows,
dcn, swapBlue(code), gbits);
break;
case COLOR_BGR2GRAY: case COLOR_BGRA2GRAY: case COLOR_RGB2GRAY: case COLOR_RGBA2GRAY:
CV_Assert( scn == 3 || scn == 4 );//如果通道不是3或者4,就会返回一个错误的信息
_dst.create(sz, CV_MAKETYPE(depth, 1));//后面的这个是指得到矩阵的类型
dst = _dst.getMat();
//下面这个函数参数的意思
//src.data:MAT数据矩阵的首地址,Uchar类型
//src.step:矩阵中每一行的步长,以字节位单位
//cols:列数
//rows:行数
hal::cvtBGRtoGray(src.data, src.step, dst.data, dst.step, src.cols, src.rows,
depth, scn, swapBlue(code));
break;
case COLOR_BGR5652GRAY: case COLOR_BGR5552GRAY:
CV_Assert( scn == 2 && depth == CV_8U );
gbits = code == COLOR_BGR5652GRAY ? 6 : 5;
_dst.create(sz, CV_8UC1);
dst = _dst.getMat();
hal::cvtBGR5x5toGray(src.data, src.step, dst.data, dst.step, src.cols, src.rows, gbits);
break;
/*...省去一大段...*/
case COLOR_mRGBA2RGBA:
if (dcn <= 0) dcn = 4;
CV_Assert( scn == 4 && dcn == 4 && depth == CV_8U );
_dst.create(sz, CV_MAKETYPE(depth, dcn));
dst = _dst.getMat();
hal::cvtMultipliedRGBAtoRGBA(src.data, src.step, dst.data, dst.step, src.cols, src.rows);
break;
default:
CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" );
}
}
OK,大体可以发现,重点是
void cvtBGRtoBGR(const uchar * src_data, size_t src_step,
uchar * dst_data, size_t dst_step,
int width, int height,
int depth, int scn, int dcn, bool swapBlue)
这具体关于源码的实现,以后有时间再补充,这个系列暂且了解一下如何调用opencv的库函数等