学习Opencv 2.4.9(二) ---操作像素

作者:咕唧咕唧liukun321

来自:http://blog.csdn.net/liukun321

本质上说一张图像就是由数值组成的矩阵。Opencv 2.x由 cv::Mat 这个数据结构来表示一张图像。矩阵的每一个元素代表了一个像素。对于彩色图像而言矩阵的元素是一个三元数。对图像有了这个新的认识,下面可以试着借助opencv处理图像了。

先来看一下今天要处理的图像:

今天的主题是存取像素,首先来看一下如何存取像素值。其实对于像素值的操作都可以由cv::Mat类中成员直接或间接实现,cv::Mat有若干成员函数可以获取图像的数据及属性。

操作单个像素方法:

at(int y, int x)

cv::mat的成员函数: at(int y, int x)可以用来存取图像中对应坐标为(x,y)的元素坐标。但是在使用它时要注意,在编译期必须要已知图像的数据类型,这是因为cv::mat可以存放任意数据类型的元素。因此at方法的实现是用模板函数来实现的。

使用方法:假设提前已知一幅图像img的数据类型为 unsigned char型灰度图(单通道),要对坐标为(10,12)的像素重新赋值为128,则对应操作如下:

img.at<uchar>(12,10) = 128;

如果要操作的图片img是一幅数据类型同样为unsigned char的彩色图片,再次要求将坐标(10,12)的像素赋值为128。这个操作跟上面的就有点区别了,需要对这个像素三个通道的每个对应元素赋值,Opencv中图像三原色在内存中的排列顺序为B-G-R(见下面注释),操作过程如下:

img.at<cv::Vec3b>(12,10) [0]= 128;//B
img.at< cv::Vec3b >(12,10) [1]= 128;//G
img.at< cv::Vec3b >(12,10) [2]= 128;//R

了解了at方法的用法,下面就尝试一下使用at方法对刚才的图片做一个简单的处理(将图像中加入椒盐噪点)。椒盐噪点是一种特殊的噪点,是随机的将图像的部分像素设置为黑色或白色。

既然灰度图与彩色图像对单个元素的操作方式不同,这就需要有一个图像类型判断的过程。

cv::Mat image = cv::imread("test.jpg");
if(image.channles() == 1)
{
	//灰度图
}else{
	//彩色图
}

清楚了这些过程,下面就来看看添加椒盐噪点函数的实现过程:

#include <opencv2/opencv.hpp>
#include<cstdlib>
using namespace cv;

void salt(Mat &img,int saltNum)
{
	int x,y;
	int i ;
	for(i = 0;i < saltNum; i++)
		{
			x = rand()%img.cols;
			y = rand()%img.rows;

			if(img.channels() == 1)
				{
					img.at<uchar>(y,x) = 255;
				}else if(img.channels() == 3)
				{
					img.at<Vec3b>(y,x)[0] = 255;
					img.at<Vec3b>(y,x)[1] = 255;
					img.at<Vec3b>(y,x)[2] = 255;
				}
		}

}
int main()
{
	Mat image = imread("../test.jpg");

	 Mat result;
	result = image.clone();
	salt(result,3000);
	namedWindow("src(http://blog.csdn.net/liukun321)" , CV_WINDOW_AUTOSIZE);
	imshow("src(http://blog.csdn.net/liukun321)", image);
	imshow("dst(http://blog.csdn.net/liukun321)", result);
	waitKey();
	return 0;
}

程序运行后的效果图:

原图

加入椒盐噪声后效果

其实除了at方法操作像素,还可以使用opencv提供的类cv::Mat_   来实现。cv::Mat_是一个模板子类。这个类定义了很多额外的方法,但是没有提供公共的成员变量。如果已知了矩阵的类型,使用cv::Mat_会带来很多便利。它的使用方法如下:

cv::Mat_<uchar>  img = imread("test.jpg");
img(10,12) = 128;//10行 12列

还有一种操作像素的方法:使用Mat类的ptr()方法配合cols 、rows、step、elemSize等成员变量,直接进行指针操作。下面先来说说这几个成员变量

cols代表图像的列数

rows代表图像的高度

step 代表以字节为单位的图像宽度

elemSize 代表像素的大小 (比如一个三通道uchar 型矩阵,返回值为3)

prt()方法同样是个模板类,需要编译期已知像素点的类型:

cv::Mat_<uchar>  img = imread("test.jpg");
uchar* addr =  img.ptr<uchar>(10);//返回10行的地址
addr +=12;//单通道灰度图
*addr = 128;

同样完成了对第10行第12列像素的操作。若图象为三通道彩色图:

cv::Mat_<uchar>  img = imread("test.jpg");
uchar* addr =  img.ptr<uchar>(10);//返回10行的地址
addr +=12* img.elemSize;//单通道灰度图
*addr = 128;

addr +=12* img.elemSize是因为彩色图象在内存中的存储方式:图像缓冲区中的前三个字节对应图像左上角第一个像素的三个通道值,接下来的三个字节对应第一行的第二个像素,以此类推。而且注意Opencv默认是使用BGR的通道顺序。

到此已经介绍了3中操作图像中像素的方法。除这三种以外还有一种使用迭代器的操作。今天就不再介绍了。

学习Opencv 2.4.9(二) ---操作像素

时间: 2024-10-07 13:13:13

学习Opencv 2.4.9(二) ---操作像素的相关文章

《学习opencv》笔记——矩阵和图像操作——cvSum,cvSVD,cvSVBkSb,cvTrace,cvTranspose,cvXor,cvXorS and cvZero

矩阵和图像的操作 (1)cvSum函数 其结构 CvScalar cvSum(//计算arr各通道所有像素总和 CvArr* arr//目标矩阵 ); 实例代码 #include <cv.h> #include <highgui.h> #include <stdio.h> #include <iostream> using namespace std; int main() { IplImage *src1,*dst1,*dst2,*dst3,*dst4;

《学习opencv》笔记——矩阵和图像操作——cvCalcCovarMatrix,cvCmp and cvCmpS

矩阵和图像的操作 (1)cvCalcCovarMatrix函数 其结构 void cvCalcCovarMatrix(计算给定点的均值和协方差矩阵 const CvArr** vects,//给定向量 int count,//给定向量的组数 CvArr* cov_mat,//结果矩阵 CvArr* avg,//根据flag得到结果 int flags//标记位 ); 标记位参数值极其意义 标志参数的具体标志值 意义 CV_COVAR_NORMAL 计算均值和协方差 CV_COVAR__SCRAM

《学习opencv》笔记——矩阵和图像操作——cvOr,cvOrS,cvrReduce,cvRepeat,cvScale,cvSet and cvSetZero

矩阵和图像的操作 (1)cvOr函数 其结构 void cvOr(//两个矩阵对应元素做或运行 const CvArr* src1,//矩阵1 const CvArr* src2,//矩阵2 CvArr* dst,//结果矩阵 const CvArr* mask = NULL//矩阵"开关" ); 实例代码 #include <cv.h> #include <highgui.h> #include <stdio.h> int main(int arg

《学习opencv》笔记——矩阵和图像操作——cvAnd、cvAndS、cvAvg and cvAvgSdv

矩阵和图像的操作 (1)cvAnd函数 其结构 void cvAnd( //将src1和src2按像素点取"位与运算" const CvArr* src1,//第一个矩阵 const CvArr* src2,//第二个矩阵 CvArr* dst,//结果矩阵 const CvArr* mask = NULL;//矩阵经行像素点与的"开关" ); 程序实例 #include <cv.h> #include <highgui.h> #includ

学习OpenCV范例(二十四)—ViBe前景检测(二)

最近导师没给什么项目做,所以有那么一点点小时间,于是就研究起了前景检测,既然前景检测有很多种算法,那干脆就把这些模型都学起来吧,以后用到前景检测时至少还有那么几种方法可以选择,上次介绍的是GMM模型,其实GMM模型本身就是一个很不错的模型,现在也很多人在研究,并且做改进,主要是OpenCV有函数调用,用起来非常方便,当我们都在兴高采烈的讨论GMM各种好的时候,B哥不爽了,他说老子是搞前景检测的,怎么可能让你们这么嚣张,而且老子就不按照你那套路来,什么高斯模型,混合高斯模型,我统统不用,就来个简单

《学习opencv》笔记——矩阵和图像操作——cvGertDims,cvGetDimSize,cvGetRow,cvGetRow,cvGetSize and cvGetSubRect

矩阵和图像的操作 (1)cvGetDims函数 其结构 int cvGetDims(//返回矩阵的维度和每维上的大小 const CvArr* arr,//目标矩阵 int * sizes = NULL//每个维上的大小,是个数组 ); 实例代码 #include <cv.h> #include <highgui.h> #include <stdio.h> #include <iostream> using namespace std; int main()

《学习opencv》笔记——矩阵和图像操作——cvGEMM,cvGetCol,cvGetCols and cvGetDiag

矩阵和图像的操作 (1)cvGEMM函数 其结构 double cvGEMM(//矩阵的广义乘法运算 const CvArr* src1,//乘数矩阵 const CvArr* src2,//乘数矩阵 double alpha,//1号矩阵系数 const CvArr* src3,//加权矩阵 double beta,//2号矩阵系数 CvArr* dst,//结果矩阵 int tABC = 0//变换标记 ); tABC变换标记及其对应的含义 CV_GEMM_A_T 转置 src1 CV_GE

学习OpenCV研究报告指出系列(二)源代码被编译并配有实例project

下载并安装CMake3.0.1 要自己编译OpenCV2.4.9的源代码.首先.必须下载编译工具,使用的比較多的编译工具是CMake. 以下摘录一段关于CMake的介绍: CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描写叙述全部平台的安装(编译过程).他可以输出各种各样的makefile或者project文件,能測试编译器所支持的C 特性,类似UNIX下的automake.仅仅是 CMake 的组态档取名为 CmakeLists.txt.Cmake 并不直接建构出终于的软件,而是

《学习opencv》笔记——矩阵和图像操作——cvDet,cvDit,cvDotProduct,cvEigenVV and cvFlip

矩阵和图像的操作 (1)cvDet函数 其结构 double cvDet(//计算矩阵的行列式 const CvArr* mat ); 实例代码 #include <cv.h> #include <highgui.h> #include <stdio.h> #include <iostream> using namespace std; int main() { double va[] = {1,0,0,0,2,0,0,0,3}; CvMat Va=cvMa