Opencv(C++)学习之Mat数据按位操作与通道分离合并

**

以前一直用MATLAB做图像仿真,这次学习OPENCV后,第一步就是读取图像,并对图像进行位操作,在OPENCV中比较重要和基础的一个数据结构是MAT,针对MAT型结构的位处理,进行了以下试验。

**

#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
#include"hessianHead.h"
using namespace cv;
using namespace std;
#define Name1 "图一_3通道_Ptr_8位有符号"
#define Name2 "图二_3通道_At_8位有符号"
#define Name3 "图三_1通道_At_8位无符号"
#define Name4 "图四_对分离后的channel进行操作"
#define Name5 "图五_直接生成channel再进行合并"
int main()
{
	//namedWindow(windowsName3, WINDOW_NORMAL);
	Mat emptyImg1(500,500,CV_8SC3);
	//这里100*100是像元数,不是矩阵实际数,实际矩阵应该是100*100*C(通道数)
	Mat emptyImg2(500, 500, CV_8SC3);
	for (int i = 0; i < emptyImg1.rows; i++)
	{
		for (int b = 0, g = 1, r = 2; r < emptyImg1.rows*3; b += 3, g += 3, r += 3)
	//因为是三通道,所以列数应该乘以3
		{
			emptyImg1.ptr<char>(i)[b] = 120;
			emptyImg1.ptr<char>(i)[g] = -127;
			emptyImg1.ptr<char>(i)[r] = -127;
			
			emptyImg2.at<char>(i,b) = 120;
			emptyImg2.at<char>(i,g) = 0;
			emptyImg2.at<char>(i,r) = 0;
		}
	}
	namedWindow(Name1, WINDOW_NORMAL);
	imshow(Name1, emptyImg1);
	namedWindow(Name2, WINDOW_NORMAL);
	imshow(Name2, emptyImg2);

	//这里是8通道无符号的赋值
	Mat emptyImg3(20, 20, CV_8UC1);
	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j< 20; j++)
		{
			emptyImg3.at<uchar>(i, j) = 60;
		}
	}
	namedWindow(Name3, WINDOW_NORMAL);
	imshow(Name3, emptyImg3);

	//通道分离与合并
	Mat emptyImg4(20, 20, CV_8SC3);
	Mat megeImg1, megeImg2;
	vector<Mat> channels;
	vector<Mat> channelsForMege;
	Mat imgBlueChannel;
	Mat imgGrayChannel;
	Mat imgRedChannel;

	//分离处颜色通道
	split(emptyImg4, channels);
	/* 
	方法一:可以复制地址到新的Mat空间
	imgBlueChannel=channels.at(0);
	imgGrayChannel=channels.at(1);
	imgRedChannel=channels.at(2);
	*/
	//方法二:也可以拷贝数据到新的Mat空间,修改后原图不变
	channels.at(0).copyTo(imgBlueChannel);
	channels.at(1).copyTo(imgGrayChannel);
	channels.at(2).copyTo(imgRedChannel);

	for (int i = 0; i < 20; i++)
	{
		for (int j = 0; j< 20; j++)
		{
			//方法一:这里利用通道空间来赋值
			channels.at(0).at<uchar>(i, j) = 0;
			channels.at(1).at<uchar>(i, j) = 100;
			channels.at(2).at<uchar>(i, j) = 100;
			/*
			除了之间使用通道空间来赋值外,也可以用复制地址后的通道来赋值;
			imgBlueChannel.at<uchar>(i, j) =120;
			imgGrayChannel.at<uchar>(i, j) = -127;
			imgRedChannel.at<uchar>(i, j) = -127;
			*/

			//方法二:这里利用了复制数据后的通道来复制
			imgBlueChannel.at<uchar>(i, j) = 1;
			imgGrayChannel.at<uchar>(i, j) = 1;
			imgRedChannel.at<uchar>(i, j) = 1;

		
		}
	}
	//使用方法二:需要重新做一个通道向量以便利用merge函数
	//这里应该按先后顺序,按照B-G-R的顺序存入;
	channelsForMege.push_back(imgBlueChannel);
	channelsForMege.push_back(imgGrayChannel);
	channelsForMege.push_back(imgRedChannel);

	//*合并通道
	merge(channelsForMege, megeImg2);
	merge(channels, megeImg1);
	
	namedWindow(Name4, WINDOW_NORMAL);
	namedWindow(Name5, WINDOW_NORMAL);
	imshow(Name4, megeImg1);
	imshow(Name5, megeImg2);


	Mat emptyImg6(20, 20, CV_32FC3);//(输入数据类型为32位Float型)
	double gr = 228 / 255;
	for (int i = 0; i < emptyImg6.rows; i++)
	{
		for (int b = 0, g = 1, r = 2; r < emptyImg6.rows * 3; b += 3, g += 3, r += 3)
			//因为是三通道,所以列数应该乘以3
		{
			//(float 型的输入,输入范围应该在0~1,与图四相同,则输入应127/255=0.5,228/255=0.89,228/255)
			emptyImg6.ptr<float>(i)[b] = 0.5;
			emptyImg6.ptr<float>(i)[g] = 0.89;
			emptyImg6.ptr<float>(i)[r] = 0.89;
		}
	}
	cout << gr;
	namedWindow("six", WINDOW_NORMAL);
	imshow("six", emptyImg6);

	waitKey(0);
	return 0;
}

试验结果图

试验结果图

总结:

1.按位操作,可以用MAT的at和ptr函数来实现,两者的写法不同,对位置位(i,j)处的像素,两者的表示的是at(i,j),ptr(i)[j];

2.彩色图像在OPENCV中的存储通道顺序是B-G-R,对彩色图像进行通道分离,可以利用split(srcImg, channels),这里channels是一个MAT类型的通道向量,可以通过at提取出来;

3.对多个通道合并可以用merge(channels,dstImg)函数,这里这里channels是一个MAT类型的通道向量,并按BGR的顺序在0-2的位置存放对应色彩通道数据,其中,通道向量可以用vector channels创建,并用channels.push_back( )按B-G-R的先后顺序存入;

4.对于1中的type类型,如果图像开始创建的类型为8S/8U,这里type对应着char/uchar,其赋值范围为-127127/0255;若初始创建类型为32F,则type类型可用float,赋值范围为0~1,小数点后几位。(此条待进一步修正)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值