Opencv备忘-Load/Read Pixel

Opencv备忘之Load Image,Operator Pixels

从《OpenCV 2 Computer Vision Application Programming Cookbook》中整理

刚好现在有时间,将Opencv的基础操作,整理为code,偶尔翻翻,避免遗忘!

1.Loading, displaying, and saving images

#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;

int main()
{
	//opencv现由Intel负责维护,同时其将cv::Mat读入图像的方式同IPL(Intel图像处理库)综合;
	//这也是随后的一种趋势,需要使用IplImage类部分代替cv类读取图像,或者进行图像处理!
	IplImage* iplImage = cvLoadImage("road.jpg");
	cv::Mat image(iplImage, false);

	//另一种直接使用cv::Mat读入图像的方式;
	//cv::Mat image;
	//image = cv::imread("road.jpg");
	//检查图片是否读取成功!
	if (!image.data)
	{
		std::cout << "ERROR:no image has been created." << std::endl;
	}
	//读取图像的宽高
	std::cout << "size: " << image.size().height << ","
		<< image.size().width << std::endl;
	//先定义一个窗口,然后在该窗口显示图片!
	cv::namedWindow("Original Image");//define the window
	cv::imshow("Original Image",image);//show the image

	//flip这个function是做什么功能?
	//reverses the order of rows,columns or both in the matrix
	cv::Mat result;
	cv::flip(image,result,1);//positive for horizontal
	//0 for vertical, negative for both ?

	cv::Mat resultScd, resultTrd;
	//仅复制了图片指针,内存并没有copy
	resultScd = result;//the two pointers have the same memory
	//新建了一块内存
	result.copyTo(resultTrd);//new memory block;


	//可以使用多个窗口显示图片,但前提是需要定义不同的窗口名称!
	cv::namedWindow("Output Image");//define the window
	cv::imshow("Output Image", result);//show the image

	//因为控制台窗口在程序执行结束后会关掉所有的窗口,所以需有添加此方法,用于观察图片显示!
	cv::waitKey(0);
	//将处理后的图片,保存为bmp
	cv::imwrite("flipOutImage.bmp",result);

	//若使用IPL则需要在使用结束后释放掉内存!
	cvReleaseImage(&iplImage);
	return 0;
}

2.Accessing pixel values

#include<opencv2\opencv.hpp>
#include<iostream>
#include<string>

using namespace std;
using namespace cv;

void salt(cv::Mat &image,int n);

int main(void)
{
	//open image as new to old model
	IplImage* IPLmg = cvLoadImage("Tulips.jpg");
	cv::Mat cvImg(IPLmg, false);

	//add noise to the image
	salt(cvImg, 3000);

	//display image that has noise
	cv::namedWindow("noise window");
	cv::imshow("noise window",cvImg);
	cv::waitKey(0);

	//write the noise image
	cv::imwrite("noise.bmp",cvImg);

	return 0;
}
//function: add salt-and-pepper noise
//向图像中添加椒盐噪声
//输入Mat image,及添加噪声的数目;
void salt(cv::Mat &image, int n)
{
	for (int k = 0; k < n; ++k)
	{
		//rand() is the MFC random number generator
		//try qrand() with Qt
		int i = rand() % image.cols;
		int j = rand() % image.rows;

		if (image.channels() == 1)//gray-level image
		{
			image.at<uchar>(j, i) = 255;
		}
		else if (image.channels()==3)//color image
		{
			//cv::Vec3b用于3通道的RGB图像的向量-vector
			image.at<cv::Vec3b>(j, i)[0] = 255;
			image.at<cv::Vec3b>(j, i)[1] = 255;
			image.at<cv::Vec3b>(j, i)[2] = 255;
			//类似的对于2-element或4-element vectors可以用cv::Vec2b或cv::Vec4b
			// In this later case, the last letter is replaced by s for short, i for int,
			// f for float, and d for double.All of these types are defined using the
			//template class cv::Vec<T, N> where T is the type and N is the number of vector elements.

			//使用方法.at或许会有些笨拙;所以在已知图像元素类型的情况下可以使用cv::Mat的子类cv::Mat_
			//进行访问像素,此方法为操作符重载,即operator();
			//cv::Mat_<uchar> ImgOperator=image;//ImgOperator refers to image
			//ImgOperator()=0;//access to row 50 and column 100;
		}
	}
}

3.Scanning an image with pointers

#include <opencv2\opencv.hpp>
#include <iostream>
#include <string>
//#include assert.h

using namespace std;
using namespace cv;
void colorReduce(cv::Mat &image,cv::Mat &outImg, int div = 64);
int main(void)
{
	IplImage* IPLImg = cvLoadImage("Tulips.jpg");
	cv::Mat MatImg(IPLImg);

	if (!MatImg.data)
	{
		std::cout << "Error: it's error!" << std::endl;
		assert(0);
	}

	//clone原图像方法一
	//cv::Mat ImgClone = MatImg.clone();
	//颜色降级
	//colorReduce(ImgClone);
	cv::Mat ImgClone;
	colorReduce(MatImg,ImgClone);
	//display
	cv::namedWindow("output Image");
	cv::imshow("output Image", ImgClone);
	waitKey(0);
	
	//释放memory
	cvReleaseImage(&IPLImg);
	return 0;
}
//对8bit的RGB图像进行降级;由256×256×256将为16*16*16
void colorReduce(cv::Mat &image,cv::Mat &outImg, int div)
{
	//克隆源图像方法二:
	//克隆源图像,然后对克隆的图像进行处理!
	outImg.create(image.rows,image.cols,image.type());
	int RowsImg = outImg.rows;//number of lines
	int ColsChannelsImg = (outImg.cols)*(outImg.channels());//total number of elements per line

	//为了内存对齐便于快捷操作访问等原因,在某些地方会填充一些非图片像素;
	//使用下述方法可检测像素是否连续,若是则可以将图像中所有的行连接,看作一维,进行操作;
	if (image.isContinuous())
	{
		//then no padded pixels,没有填充
		ColsChannelsImg = ColsChannelsImg*RowsImg;
		RowsImg = 1;//it is now a 1D array
		//若图像没有填充像素,则可以进行图像改造;
		image.reshape(1,//new number of channels 
			image.cols*image.rows);//new number of rows
	}

	for (int j = 0; j < RowsImg; ++j)
	{
		//get the address of row j
		//取得指向每行的指针.ptr
		const uchar* data_in = image.ptr<uchar>(j);
		uchar* data_out = outImg.ptr<uchar>(j);

		for (int i = 0; i < ColsChannelsImg; ++i)
		{
			//process each pixel---------------
			//16*16*16,如何能保证每个通道分别除以16??
			//Opencv的三通道按BGR顺序排列
			//方法1:直接除法
			data_out[i] = data_in[i] / div*div + div / 2;
			//方法2:取模运算
			//data_out[i] = data_in[i] - data_in[i] % div + div / 2;
			//方法3:位运算
			//mask used to round the pixel value
			//uchar mask = 0xFF << n;//e.g. for div=16, mask=0xF0;
			//data_out[i] = (data_in[i] & mask) + div / 2;
			//end of pixels process!
		}
		//下述写法可替代上述循环
		//*data++=*data/div*div+div/2;

		//当然还有一些低层次的访问方式
		//uchar* data = image.data;//获取图像第一行的指针
		//data += image.step;//next line,step方法提供一行中所有的字节数,包括填充像素
		
		//采取下述方式也可以访问像素,但是在ROI问题时会造成一些ERROR,所以建议不要使用,知道即可!
		//address of pixel at (j,i) that is &image.at(j,i);
		//data = image.data + j*image.step + i*image.elemSize();
		
	}//end process!
}

明天继续贴---


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值