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;
}


结果:






  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值