1.首先叛薯,是opencv中的cvtColor方法羊始。
C++:void cvtColor(InputArray src, OutputArray dst,int code,int dstCn=0 );
參數(shù)解釋:
. InputArray src: 輸入圖像即要進(jìn)行顏色空間變換的原圖像旱幼,可以是Mat類
. OutputArray dst: 輸出圖像即進(jìn)行顏色空間變換后存儲(chǔ)圖像,也可以Mat類
. int code: 轉(zhuǎn)換的代碼或標(biāo)識(shí)突委,即在此確定將什么制式的圖片轉(zhuǎn)換成什么制式的圖片柏卤,后面會(huì)詳細(xì)將
. int dstCn = 0: 目標(biāo)圖像通道數(shù),如果取值為0匀油,則由src和code決定
我們可以令code參數(shù)為COLOR_BGRABGRA缘缚,將圖像轉(zhuǎn)化為帶透明通道的圖片。這里要注意敌蚜,加上的透明通道忙灼,默認(rèn)值為255,也就是說(shuō)钝侠,默認(rèn)將圖像轉(zhuǎn)換為不透明圖该园。如果需要對(duì)圖像的透明度進(jìn)行調(diào)整,則還需要另寫代碼帅韧。下面是部分代碼里初,來(lái)驗(yàn)證默認(rèn)值確實(shí)為255。
std::string path = "E:/140.jpg";
Mat image = cv::imread(image_path);
std::cout << "原圖像通道數(shù): " << image.channels() << std::endl;
cvtColor(image, image, COLOR_BGR2BGRA);
std::cout << "轉(zhuǎn)換后圖像通道數(shù): " << image.channels() << std::endl;
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
std::cout<<(int)image.at<Vec4b>(i, j)[3]<<std::endl;
}
}
得到的輸出為:
代碼中忽舟,image.at可以獲取圖像像素值双妨,而中括號(hào)內(nèi),0代表B叮阅,1代表G刁品,2代表R,3代表A浩姥,所以括號(hào)中為3挑随。而強(qiáng)制類型轉(zhuǎn)換為int,則是因?yàn)樵趏pencv中勒叠,單像素的類型為uchar兜挨,如果直接標(biāo)準(zhǔn)輸出,則會(huì)輸出一大堆字符眯分,而不是我們想要的像素值拌汇。如果圖像在讀取的時(shí)候沒(méi)有要求讀取透明通道,或者圖像本身沒(méi)有透明通道弊决,那么圖像的通道數(shù)默認(rèn)為3噪舀,可以簡(jiǎn)單地說(shuō),這個(gè)內(nèi)置方法,就是為圖像的通道數(shù)組多加了一列作為透明通道与倡,這個(gè)數(shù)組類型為Mat類型先改。
2.接下來(lái),是手寫代碼的方法
由上述說(shuō)明可知蒸走,默認(rèn)方法所做的就是給圖像的通道數(shù)組再加上一列仇奶,而這一列所表示的,就是圖像每個(gè)像素的透明度比驻。而這個(gè)透明度數(shù)組该溯,也是一個(gè)Mat類型數(shù)組。
所以别惦,我們可以新建一個(gè)Mat類型數(shù)組狈茉,數(shù)組大小與圖像的分辨率一致。這里掸掸,我們還可以以圖像的灰度圖作為參考氯庆,將圖像的每個(gè)像素以灰度值來(lái)設(shè)置透明度,這樣一來(lái)扰付,就實(shí)現(xiàn)了圖像按像素值自動(dòng)的調(diào)整每一個(gè)像素點(diǎn)的透明度堤撵。創(chuàng)建透明通道的方法如下:
//創(chuàng)建透明通道
cv::Mat createAlpha(cv::Mat& src)
{
cv::Mat alpha = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
cv::Mat gray = cv::Mat::zeros(src.rows, src.cols, CV_8UC1);
//根據(jù)灰度創(chuàng)建透明度通道
cv::cvtColor(src, gray, cv::COLOR_RGB2GRAY);
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
//透明度為灰度的兩倍,可自行調(diào)整
alpha.at<uchar>(i, j) = gray.at<uchar>(i, j) * 2;
}
}
return alpha;
}
這個(gè)alpha羽莺,就是圖像的透明通道实昨。然而,這里的透明通道僅僅是被創(chuàng)建了出來(lái)盐固,并沒(méi)有被加入圖像中荒给。我們可以使用opencv中的split和merge函數(shù)來(lái)添加透明通道。其中刁卜,split函數(shù)作用是分割圖像的通道志电,merge函數(shù)則是合并圖像的各通道。我們可以先把原圖像的各個(gè)通道分開蛔趴,然后再連帶著透明通道合并挑辆,就得到了帶透明通道的圖像。代碼如下:
int addAlpha(cv::Mat& src, cv::Mat& dst, cv::Mat& alpha)
{
if (src.channels() == 4)
{
return -1;
}
else if (src.channels() == 1)
{
cv::cvtColor(src, src, cv::COLOR_GRAY2RGB);
}
dst = cv::Mat(src.rows, src.cols, CV_8UC4);
std::vector<cv::Mat> srcChannels;
std::vector<cv::Mat> dstChannels;
//分離通道
cv::split(src, srcChannels);
dstChannels.push_back(srcChannels[0]);
dstChannels.push_back(srcChannels[1]);
dstChannels.push_back(srcChannels[2]);
//添加透明度通道
dstChannels.push_back(alpha);
//合并通道
cv::merge(dstChannels, dst);
return 0;
}
再處理的過(guò)程中夺脾,先調(diào)用createAlpha函數(shù)創(chuàng)建透明通道之拨,再調(diào)用addAlpha函數(shù)加入透明通道即可。下面放一個(gè)測(cè)試結(jié)果咧叭。
原圖:
加入透明通道:
可以看到,一些像素變成了全透明烁竭,而一些像素是半透明菲茬。如果把這個(gè)圖貼在其他圖上的話,看的更明顯一點(diǎn):