opencv 图像读取显示和像素操作

从今天起,开始从头系统学习下opencv,下面记录下图像的基本操作:

  1. 图像的读取和显示

Mat image = imread(imagePath, 1);
第二个参数表示图片读入的方式(flags可以缺省,缺省时flags=1,表示以彩色图片方式读入图片)
flags>0时表示以彩色方式读入图片
flags=0时表示以灰度图方式读入图片
flags<0时表示以图片的本来的格式读入图片。

char *f = "E:\\opencv\\sources\\samples\\wp8\\OpenCVXaml\\OpenCVXaml\\Assets\\Lena.png";
	Mat lena;
	lena = imread(f);
	imshow("lena", lena);
	IplImage * lena2;
	//lena2 = cvLoadImage(f, CV_LOAD_IMAGE_GRAYSCALE); // 加载灰度图
	lena2 = cvLoadImage(f, CV_LOAD_IMAGE_UNCHANGED);//加载原始图像
	cvNamedWindow("lena2", CV_WINDOW_AUTOSIZE);//创建窗口
	cvShowImage("lena2", lena2);

opencv窗口的大小控制

		Mat frame;
		...
		int h = frame.rows;
		int w = frame.cols;
		const char *name = "video";
		// 这里定义为0,则窗口图像会随着窗口压缩,为1则不会,若窗口小于图像没,
		//则图像显示不全
		cvNamedWindow(name,0);
		cvResizeWindow(name, w/2, h/2);
		imshow(name, frame);

像素读取和操作

1. 利用cv::Mat的at函数,直接访问具体地址

void get_setImagePixel(char *imagePath , int x , int y)
{
//	Mat image = imread(imagePath , 0);
	Mat image = imread(imagePath, 1);
	//得宽高
	int w = image.cols;
	int h = image.rows;

	int channels = image.channels();
	if (x < w && y < h)
	{
		//灰度图,像素为单通道
		if (channels == 1)
		{
			int pixel = image.at<uchar>(x, y);
			cout << "灰度图像,处的灰度值为" << pixel << endl;
		}
		else
		{
			//通过实验,彩色图像的默认存储是bgr, 且存储的格式如下
			
			//读取
			int b = image.at<Vec3b>(x, y)[0]; // b = image.at<uchar>(x,y*3);
			cout << b << endl;
			int g = image.at<Vec3b>(x, y)[1]; //g = image.at<uchar>(x, y * 3 + 1);
			cout << g << endl;
			int r = image.at<Vec3b>(x, y)[2]; //r = image.at<uchar>(x, y * 3 + 1);
			cout << r << endl;

			//设置像素值
			image.at<Vec3b>(x, y)[0] = 255;
			image.at<Vec3b>(x, y)[1] = 255;
			image.at<Vec3b>(x, y)[2] = 255;
		 }
	}
	imshow("cc", image);
}

2. 利用Mat 的prt 函数:行首地址访问

void get_setImagePixel2(char *imagePath, int x, int y)
{
	Mat image = imread(imagePath, 1);
	//得宽高
	int w = image.cols;
	int h = image.rows;
	int channels = image.channels();
	//如果图像连续 ,可以将数据转化为1维数组,提高访问效率,但对少量像素访问就没必要
	//if (image.isContinuous())
	//{
	//	//reshape函数用于改变矩阵维度  
	//	//图像行数为1,列数为原先的行数乘上列数  
	//	image.reshape(1, image.cols*image.rows);
	//}

	//获得第y行的首地址
	uchar *data = image.ptr<uchar>(y);
	int position = x*channels;
	if (channels == 1)
	{
		int pixel = data[position];
		cout << "灰度图像,处的灰度值为" << pixel << endl;
	}
	else
	{
		//通过实验,彩色图像的默认存储是bgr, 且存储的格式如下

		//读取
		int b = data[position];
		cout << b << endl;
		int g = data[position+1];
		cout << g << endl;
		int r = data[position+2];
		cout << r << endl;

		//设置像素值
		data[position] = 255;
		data[position+1] = 255;
		data[position+2] = 255;
	}
	imshow("cc", image);
}

3. 利用迭代器遍历图像

void get_setImagePixel3(char *imagePath, int x, int y)
{
	Mat image = imread(imagePath, 1);
	//得宽高
	int w = image.cols;
	int h = image.rows;
	int channels = image.channels();
	
	
	if (channels == 1)
	{
		//得到初始位置的迭代器  
		Mat_<uchar>::iterator it = image.begin<uchar>();
		//得到终止位置的迭代器  
		Mat_<uchar>::iterator itend = image.end<uchar>();
		int pixel = *(it + y * w + x);
		cout << "灰度图像,处的灰度值为" << pixel << endl;
	}
	else
	{
		//得到初始位置的迭代器  
		Mat_<Vec3b>::iterator it = image.begin<Vec3b>();
		//得到终止位置的迭代器  
		Mat_<Vec3b>::iterator itend = image.end<Vec3b>();
		//读取
		it = it + y * w + x;
		int b = (*it)[0];
		cout << b << endl;
		int g = (*it)[1];
		cout << g << endl;
		int r = (*it)[2];
		cout << r << endl;

		
		//设置像素值
			(*it)[0] = 255;
			(*it)[1] = 255;
			(*it)[2] = 255;
		
	}
	imshow("cc", image);

}

若是大量访问数据和更改数据时用第二种方式效率高。

Node: 在修改像素时候,最好先用变量存储,设定好了再赋值给Mat成员对象,如data,因为如果直接进行操作时,当一个分量值大于255时,向前进1的原则,则会修改前面像素的值,如下:

void colorReduce(cv::Mat&image, int div)
{
	int nl = image.rows; //图像的行数  
	//图像每行的像素数  
	int nc = image.cols * image.channels();
	for (int j = 0; j<nl; j++)
	{
		//得到第j行的首地址  
		uchar* data = image.ptr<uchar>(j);
		//遍历每行的像素  
		for (int i = 0; i<nc; i++)
		{
			//printf("%d    ", data[i]);
			//data[i] = data[i] / div*div + 6;// 这里需要用c来存储,因为如果大于255时会向前进1,则影响前面的像素,data[i] 会自己变得小255
			int c = data[i] / div*div + 100;		
			data[i] =  c > 255 ? 255 : c;    //将每个像素值都变为div的倍数,即将颜色数缩减了div倍  						
			
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值