opencv RGB三通道分離


如果我們想分離出每個通道的具體值,並且可以演示看出分離的是“紅”“綠”“藍”的效果。可以用如下函數:

1、C接口程序:

	IplImage* img = cvLoadImage("baboon.jpg");
	IplImage* rImg=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);    
	IplImage* gImg=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);    
	IplImage* bImg=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1); 
	cvSplit( img,bImg, gImg,rImg,0);  
	IplImage* rImg3=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);    
	IplImage* gImg3=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);    
	IplImage* bImg3=cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);   
	cvMerge(bImg,gImg,0,0,rImg3);  
	cvMerge(bImg,0,rImg,0,gImg3);  
	cvMerge(0,gImg,rImg,0,bImg3); 

cvMerge源程序:

CV_IMPL void cvMerge(const void* srcarr0, const void* srcarr1, const void* srcarr2,
         const void* srcarr3, void* dstarr )
{
    const void* sptrs[] = { srcarr0, srcarr1,srcarr2, srcarr3 };
    cv::Mat dst = cv::cvarrToMat(dstarr);
    int i, j, nz = 0;
    for( i = 0; i < 4; i++ )
        nz += sptrs[i] != 0;
    CV_Assert( nz > 0 );
    cv::vector<cv::Mat> svec(nz);
    cv::vector<int> pairs(nz*2);
 
    for( i = j = 0; i < 4; i++ )
    {
        if( sptrs[i] != 0 )
        {
            svec[j] = cv::cvarrToMat(sptrs[i]);
            CV_Assert( svec[j].size == dst.size&&
                svec[j].depth() == dst.depth()&&
                svec[j].channels() == 1&& i < dst.channels() );
            pairs[j*2] = j;
            pairs[j*2+1] = i;
            j++;
        }
    }
    if( nz == dst.channels() )
        cv::merge( svec, dst );
    else
    {
        cv::mixChannels( &svec[0], nz,&dst, 1, &pairs[0], nz );
    }
}

說明:cvMerge函數中cv::Mat dst = cv::cvarrToMat(dstarr);這句會使得dst中元素全爲205,具體爲什麼不清楚。

2、C++接口程序

//單窗口顯示多幅圖像
int showManyImages( const std::vector<cv::Mat> &srcImages, cv::Size imgSize,cv::Mat& dstImage )
{
	int nNumImages = srcImages.size();
	cv::Size nSizeWindows;
	if(nNumImages > 12)
	{
		std::cout << " Not more than 12 images!" << std::endl;
		return -1;
	}
	// 根據圖片序列數量來確定分割小窗口形態
	switch(nNumImages)
	{
	case 1: nSizeWindows = cv::Size(1,1);break;
	case 2: nSizeWindows = cv::Size(2,1);break;
	case 3: 
	case 4: nSizeWindows = cv::Size(2,2);break;
	case 5: 
	case 6: nSizeWindows = cv::Size(3,2);break;
	case 7: 
	case 8: nSizeWindows = cv::Size(4,2);break;
	case 9: nSizeWindows = cv::Size(3,3);break;
	default:nSizeWindows = cv::Size(4,3);break;
	}
	// 設置小圖像尺寸,間隙,邊界
	cv::Size nShowImageSize = cv::Size(300,200);//每張圖顯示在畫布上的尺寸
	int nSplitLineSize  = 30;
	int nAroundLineSize = 50;
	// 創建輸出圖像,圖像大小根據輸入源確定
	const int imagesHeight = nShowImageSize.height * nSizeWindows.height+ 
		nAroundLineSize + (nSizeWindows.width - 1) *
		nSplitLineSize;
	const int imagesWidth = nShowImageSize.width*nSizeWindows.height + 
		nAroundLineSize + (nSizeWindows.height - 1) * 
		nSplitLineSize;
	//std::cout << imagesWidth << " " << imagesHeight << std::endl;
	cv::Mat resultImage(imagesHeight, imagesWidth, 
		CV_8UC3,cv::Scalar(0,0,0));
	// 提取對應小圖像的左上角座標X,Y
	int posX = (resultImage.cols-(nShowImageSize.width*
		nSizeWindows.width+(nSizeWindows.width-1)*
		nSplitLineSize))/2;
	int posY = (resultImage.rows-(nShowImageSize.height*
		nSizeWindows.height+(nSizeWindows.height-1)*
		nSplitLineSize))/2;
	//std::cout << posX << " " << posY  << std::endl;
	int tempPosX = posX;
	int tempPosY = posY;

	//write text on image	
	std::vector<cv::string> msg;
	msg.push_back("original image");
	msg.push_back("blue image");
	msg.push_back("green image");
	msg.push_back("red image");
	int baseLine = 0;

	// 將每一小幅圖像整合大圖像
	for(int i = 0; i < nNumImages; i++)
	{
		// 小圖像座標轉換
		if(( i % nSizeWindows.width == 0) && ( tempPosX != posX ))
		{
			tempPosX = posX;
			tempPosY  += (nSplitLineSize + nShowImageSize.height);
		}
		// 利用Rect區域將小圖像置於大圖像相應區域
		cv::Mat tempImage = resultImage(cv::Rect(tempPosX, 
			tempPosY , nShowImageSize.width, nShowImageSize.height));
		// 利用resize函數實現圖像縮放
		resize(srcImages[i], tempImage,
			cv::Size( nShowImageSize.width ,   nShowImageSize.height));

		cv::Size textSize = cv::getTextSize(msg[i], 1, 1, 1, &baseLine);//returns bounding box of the text string
		int textPosX = tempPosX + nShowImageSize.width/2 - textSize.width/2;
		int textPosY = tempPosY - 10;
		cv::Point textOrigin(textPosX,textPosY);
		cv::putText(resultImage,msg[i],textOrigin,1,1,cv::Scalar(255,255,255),1,8);

		tempPosX += (nSplitLineSize + nShowImageSize.width);	
	}
	dstImage = resultImage.clone();
}
int main()
{
	cv::Mat srcImage = cv::imread("baboon.jpg"); 
	if(!srcImage.data) return -1;
	std::vector<cv::Mat> vecImage(3),bgrImage(3);
	cv::split(srcImage,vecImage);// B/G/R
	for (int i = 0;i<3;i++)
	{
		cv::split(srcImage,vecImage);// B/G/R
		for (int j = 0;j<3;j++)
		{
			if (i != j )  
				vecImage[i] = cv::Mat::ones(srcImage.size(), vecImage[0].type())*205;//爲了保持與cvMerge結果一致  
		}
		cv::merge(vecImage,bgrImage[i]); 
	}
	cv::Mat showImage;
    	bgrImage.insert(bgrImage.begin(),srcImage);
	showManyImages(bgrImage,cv::Size(2,2),showImage);
	cv::imwrite("showImage.jpg",showImage);
	cv::waitKey(0);
	return 0;
}


結果:






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章