opencv中的图像坐标和行列的关系
OpenCV坐标系与操作像素的四种方法

OpenCV坐标系与操作像素的四种⽅法像素是图像的基本组成单位,熟悉了如何操作像素,就能更好的理解对图像的各种处理变换的实现⽅式了。
1.at⽅法第⼀种操作像素的⽅法是使⽤“at”,如⼀幅3通道的彩⾊图像image的第i⾏j列的B、G、R分量分别表⽰为:image.at<Vec3b>(i,j)[0];image.at<Vec3b>(i,j)[1];image.at<Vec3b>(i,j)[2];⽽对于单通道的灰度图像就简单很多了:image.at<uchar>(i,j);这⾥要注意at中(i,j)的顺序表⽰的是第i⾏第j列,跟Point(i,j)和Rect(i,j)中表⽰第j⾏第i列是相反的,如果把这个搞混了,很容易导致内存异常,还不容易发现错误。
补充说明⼀下:opencv中坐标体系中的零点坐标定义为图⽚的左上⾓,X轴为图像矩形的上⾯那条⽔平线,从左往右;Y轴为图像矩形左边的那条垂直线,从上往下。
在Point(x,y)和Rect(x,y)中,第⼀个参数x代表的是元素所在图像的列数,第⼆个参数y代表的是元素所在图像的⾏数,⽽在at(x,y)中是相反的。
演⽰程序如下:#include<iostream>#include<core/core.hpp>#include<highgui/highgui.hpp>using namespace cv;using namespace std;int main(){Mat image(Size(500,500),CV_8UC3);image.at<Vec3b>(100,250)[0]=0;image.at<Vec3b>(100,250)[1]=0;image.at<Vec3b>(100,250)[2]=255;putText(image,"at(100,250) is Here!",Point(250,100),0,0.7,Scalar(255,0,0));image.at<Vec3b>(Point(100,250))[0]=0;image.at<Vec3b>(Point(100,250))[1]=0;image.at<Vec3b>(Point(100,250))[2]=255;putText(image,"at(Point(100,250)) is Here!",Point(100,250),0,0.7,Scalar(255,0,0));imshow("Test Function at",image);waitKey();return 0;}2.⾏指针⽅法⾏指针⽅法的思路是获取图像每⼀⾏的⾸地址的指针,把每⼀⾏当成⼀个循环对象,逐⾏遍历所有的像素。
OpenCV相机标定坐标系详解

OpenCV相机标定坐标系详解在OpenCV中,可以使⽤calibrateCamera函数,通过多个视⾓的2D/3D对应,求解出该相机的内参数和每⼀个视⾓的外参数。
使⽤C++接⼝时的输⼊参数如下:objectPoints - 每⼀个视⾓中,关键点的世界坐标系。
可以使⽤vector < vector <Point3f> >类型,第⼀层vector表⽰每⼀个视⾓,第⼆层vector表⽰每⼀个点。
如果使⽤OpenCV⾃带的棋盘格,可以直接传⼊交叉点(不包括边⾓)的实际坐标,以物理世界尺度(例如毫⽶)为单位。
写坐标时,要保证z轴为0,按照先x变化,后y变化,从⼩到⼤的顺序来写。
如果⽹格尺⼨为5厘⽶,写作:(0,0,0),(5,0,0), (10,0,0)...(0,5,0), (5,5,0), (10,5,0),...如下图例⼦,x⽅向是8个交叉点,y⽅向3个较差点。
imagePoints - 每⼀个视⾓中,关键点的图像坐标系。
可以使⽤vector < vector <Point2f> >类型。
这个值可以通过findChessboardCorners函数从图像中获得。
注意:传⼊findChessboardCorners函数的patternSize参数,要和objectPoints 中的⾏列数统⼀。
imageSize - 图像尺⼨。
flags - 参数。
决定是否使⽤初始值,扭曲参数个数等。
输出参数如下:cameraMatrix - 3*3的摄像机内矩阵。
distCoeffs - 4*1(具体尺⼨取决于flags)。
对图像坐标系进⾏进⼀步扭曲。
这两个参数是内参数,可以把摄像机坐标系转换成图像坐标系。
rvecs - 每⼀个视图的旋转向量。
vector<Mat>类型,每个vec为3*1,可以⽤Rodrigues函数转换为3*3的旋转矩阵。
tvecs - 每⼀个视图的平移向量。
OpenCV图像变换二投影变换与极坐标变换实现圆形图像修正

OpenCV图像变换⼆投影变换与极坐标变换实现圆形图像修正投影变换##在放射变换中,物体是在⼆维空间中变换的。
如果物体在三维空间中发⽣了旋转,那么这种变换就成为投影变换,在投影变换中就会出现阴影或者遮挡,我们可以运⽤⼆维投影对三维投影变换进⾏模块化,来处理阴影或者遮挡。
在OpenCV中有类似于getAffineTransform函数:getPerspectiveTransform(src,dst)函数⽤来处理计算投影变换矩阵。
与getAffineTransform函数不同的是传⼊的参数是三维空间坐标系的空间坐标,也就是4*2的⼆维ndarray,其中每⼀⾏代表⼀个坐标并且传⼊的数据类型必须为float32.⽰例:import cv2import numpy as npsrc=np.array([[0,0],[100,0],[0,100],[100,100]],np.float32)dst=np.array([[100,10],[100,10],[50,70],[200,150]],np.float32)P=cv2.getPerspectiveTransform(src,dst)print(P)运⾏结果:[[-7.77156117e-16 -1.00000000e+00 1.00000000e+02][-2.77555756e-15 -1.00000000e-01 1.00000000e+01][-2.66713734e-17 -1.00000000e-02 1.00000000e+00]]由结果可以看出当前输出的类型是float64.对于仿射变换在OpenCV中提供了如下的函数cv2.warpPerspective(src,M,dsize[,dst[,flags[,borderMode[,borderValue]]]])输⼊的矩阵类型是3⾏3列的投影变换矩阵。
⽰例:import cv2import numpy as npimport matplotlibdef Perspect(path):img=cv2.imread(path,cv2.IMREAD_GRAYSCALE)if not isinstance(img, np.ndarray):print('PASS')passelse:h,w=img.shape#设置变换坐标变化src=np.array([[0,0],[w-1,0],[0,h-1],[w-1,h-1]],np.float32)dst=np.array([[100,100],[w/3,100],[100,h-1],[w-1,h-1]],np.float32)#计算投影变换矩阵P=cv2.getPerspectiveTransform(src,dst)#利⽤变化矩阵进⾏投影变换r=cv2.warpPerspective(img,P,(w,h),borderValue=126)#显⽰图像cv2.imshow('A',img )cv2.imshow('B',r)cv2.waitKey(0)cv2.destroyAllWindows()print(P)Perspect('img/aa.jpg')极坐标变换##极坐标变换主要处理校正图像中的圆形物体或者在圆形中物体\(r=\sqrt{(x-(\overline{x})^2)+(y-(\overline{y})^2)}\)\[\theta= \left\{ \begin{matrix} 2\pi +arctan2(y-\overline{y},x-\overline{x}), &y-\overline{y}\leq0\\ arctan2(y-\overline{y},x-\overline{x},&y-\overline{y}>0 \end{matrix} \right\} \]以变换中⼼为圆⼼的同⼀个圆⼼上的点,在极坐标系\(\theta\)or中显⽰为⼀条直线。
opencv 仿射变换后坐标偏移

opencv 仿射变换后坐标偏移仿射变换是计算机视觉领域中常用的一种图像处理方法,它可以通过对图像进行旋转、平移、缩放和剪切等操作,改变图像的形状和位置。
在进行仿射变换后,图像中的像素坐标会发生一定程度的偏移。
本文将探讨仿射变换后坐标偏移的问题,并介绍一种常用的解决方法。
我们来了解一下仿射变换的基本概念和原理。
仿射变换是指在二维平面上对图像进行线性变换和平移操作,可以通过一个矩阵乘法来表示。
具体而言,对于一个二维坐标点(x, y),它在经过仿射变换后的坐标点(x', y')可以表示为:x' = a*x + b*y + cy' = d*x + e*y + f其中,a、b、c、d、e和f是仿射变换矩阵的元素,它们决定了变换的方式和程度。
通过调整这些参数,我们可以实现对图像的各种变换操作。
在进行仿射变换后,图像中的像素坐标会发生一定程度的偏移。
具体来说,对于图像中的每个像素点,我们可以通过仿射变换的逆变换得到它在原始图像中的坐标,然后再通过仿射变换的正变换得到它在变换后图像中的坐标。
通过比较这两个坐标,我们可以计算出坐标偏移量。
为了更好地理解坐标偏移的概念,我们可以通过一个具体的例子来说明。
假设我们有一张图像,它的原始坐标系为(x, y),经过仿射变换后的坐标系为(x', y')。
现在我们想要计算图像中某个像素点的坐标偏移量。
我们需要找到这个像素点在原始图像中的坐标(x, y),然后通过仿射变换的逆变换得到它在变换前图像中的坐标(x0, y0)。
接下来,我们再将这个坐标(x0, y0)通过仿射变换的正变换得到它在变换后图像中的坐标(x', y')。
最后,我们可以计算坐标偏移量为:delta_x = x' - xdelta_y = y' - y通过这样的计算,我们可以得到图像中任意像素点的坐标偏移量。
在实际应用中,我们通常使用OpenCV库来进行仿射变换。
opencv中Mat格式的数据访问.at

opencv中Mat格式的数据访问.atopencv3中图形存储基本为Mat格式,如果我们想获取像素点的灰度值或者RGB值,可以通过image.at<uchar>(i,j)的⽅式轻松获取。
Mat类中的at⽅法对于获取图像矩阵某点的RGB值或者改变某点的值很⽅便,对于单通道的图像,则可以使⽤:image.at<uchar>(i, j)其中有⼀个要注意的地⽅是i对应的是点的y坐标,j对应的是点的x坐标,⽽不是我们习惯的(x,y)来获取或改变该点的值,⽽RGB通道的则可以使⽤:image.at<Vec3b>(i, j)[0]image.at<Vec3b>(i, j)[1]image.at<Vec3b>(i, j)[2]来分别获取B、G、R三个通道的对应的值。
下边的代码实现对图像加椒盐噪声:// created by ning zhang 2018/4/25// The function of this program is to add noise to the image#include <opencv2/opencv.hpp>#include <iostream>using namespace std;using namespace cv;void salt_noise( Mat image, int time );int main ( int argc, char** argv ){Mat image = imread("../lena.jpg",0); //input the gray imageif ( image.empty() ){cout << "Load image error" << endl;return -1;}salt_noise(image, 3000);namedWindow("image", 1);imshow("image", image);waitKey();return 0;}void salt_noise ( Mat image, int time ){for (int k = 0; k < time; k++ ) //time is the number of noise you add{int i = rand() % image.rows;int j = rand() % image.cols;if (image.channels() == 1) //single channel{image.at<uchar>(i,j) = rand() % 255;}else if (image.channels() == 3) //RGB channel{image.at<Vec3b>(i, j)[0] = rand() % 255;image.at<Vec3b>(i, j)[1] = rand() % 255;image.at<Vec3b>(i, j)[2] = rand() % 255;}}}效果图如下所⽰,可以为图⽚增加噪点还有⽐较省时的⽅法使⽤Mat的模板⼦类Mat_<T>,,对于单通道的具体使⽤:Mat_<uchar> img = image;img(i, j) = rand() % 255;对于RGB通道的使⽤:Mat_<Vec3b> img = image;img(i, j)[0] = rand() % 255;img(i, j)[1] = rand() % 255;mg(i, j)[2] = rand() % 255;还可以⽤指针的⽅法遍历每⼀像素:(耗时较⼩)void colorReduce(Mat image, int div = 64){int nrow = image.rows;int ncol = image.cols*image.channels();for (int i = 0; i < nrow; i++){uchar* data = image.ptr<uchar>(i);//get the address of row i;for (int j = 0; j < ncol; j++){data[i] = (data[i] / div)*div ;}}}我们要尤其注意OpenCV坐标系与row&col的关系 (Mat::at(x,y)和Mat::at(Point(x, y))的区别)直接给出对应关系吧row == heigh == Point.ycol == width == Point.xMat::at(Point(x, y)) == Mat::at(y,x)因为还有点的坐标,所以建议在访问时都⽤Mat::at(Point(x, y))这种形式吧,免去了点坐标和⾏列的转换详细说明:1. 坐标体系中的零点坐标为图⽚的左上⾓,X轴为图像矩形的上⾯那条⽔平线;Y轴为图像矩形左边的那条垂直线。
OpenCV图像处理之投影变换

OpenCV图像处理之投影变换解释:1、仿射变换之后,平行的线还是平行的,因此这一点也是仿射变换与投影变换的区别。
2、投影变换只是保证同一条直线的点还是在同一条直线上,但不再保证平行了。
因为投影变换是一个二维图像(车牌)经过一个三维变换,然后映射到另外一个二维空间,3、二维图像的二维空间与映射后的二维空间不一样,如果一样,就是仿射变换。
Python代码实现样例:import cv2 as cvimport numpy as npimage = cv.imread("E:/OpencvVideo/6.jpg") #读取图像h,w = image.shape[:2] #获取图像大小信息,包括(行数,列数,通道数),在此取行数和列数即可#原图像4个需要变换的像素点src = np.array([[0,0],[w-1,0],[0,h-1],[w-1,h-1]],np.float32)#投影变换的4个像素点dst = np.array([[80,80],[w/2,50],[80,h-80],[w-40,h-40]],np.float32) M = cv.getPerspectiveTransform(src,dst) #计算出投影变换的矩阵#进行投影变换imagel = cv.warpPerspective(image,M,(w,h),borderValue=125)#显示图像cv.imshow("image",image) #显示原始图像cv.imshow("imagel",imagel) #显示变换后的图像cv.waitKey()cv.destroyAllWindows()。
图像畸变对智能车控制的影响及对策研究

图像畸变对智能车控制的影响及对策研究作者:况宗旭李军红何俊延马锦模张逸帆来源:《科技风》2018年第21期摘要:由于智能车视野范围的要求,摄像头一般要向下倾斜一定角度安装,这种安装方式会造成图像畸变,得到的图像不能反映路面的真实情况。
本文分析图像畸变的产生及对智能车控制的影响,提出采用“非均匀行采集”和“线性补偿”的方法矫正摄像头图像畸变,并基于Opencv进行仿真实验,且在智能小车上应用图像矫正算法进行实车调试。
实验结果表明,根据矫正后的图像信息识别路径,能有效地避免智能车偏离导航线,提高智能车的控制精度和响应速度。
关键词:图像畸变;非均匀行采集;线性补偿;智能小车1绪论利用摄像头摄取道路图像信息,识别路面引导线实现自主导航是现阶段智能车较常用的导航方法。
[1]摄像头在拍摄图像时,最理想的位置是垂直于拍摄平面,这样才能保证图像按几何比例重现。
由于智能车视野范围的要求,摄像头的安装一般与拍摄平面成一定倾斜角度,这种角度的存在会造成图像畸变。
在这种情况下,直接利用目标引导线在图像中的相对位置制定控制策略,会造成较大的误差,甚至使小车严重偏离导航线。
针对上述问题,本文采用“非均匀行采集”和“线性补偿”的方法矫正摄像头图像畸变,根据矫正后的图像信息进行路径识别。
仿真实验和实车调试的结果表明,图像畸变矫正为智能车控制策略的实现奠定了基础,能有效提高智能车的控制性能。
2图像畸变的产生及影响2.1图像畸变的产生当摄像头垂直安装时,与向下倾斜一定角度安装相比,获得的视野范围是最小的。
因此,为了满足车辆视野范围的要求,摄像头一般会向下倾斜一定角度。
由于俯仰角不为零,摄像机的主光轴与所摄的路面不垂直,而像平面与摄像机主光轴垂直,根据几何光学可知,图像存在几何图像畸变。
几何图像畸变主要分为两个部分,包括横向畸变和纵向畸变,[2]如下图所示。
2.1.1横向畸变如图1所示,在摄像头垂直拍摄输出的道路图像中,两条车道线是平行关系,当摄像头向下倾斜拍摄,图像中两条车道线却变为不平行,且横向距离不断被压缩。
opencv 计算两组点的多个点的映射关系

一、引言OpenCV是一个开源计算机视觉和机器学习软件库,它提供了各种各样的图像处理和计算机视觉算法。
其中,计算两组点的多个点的映射关系是计算机视觉领域中的重要问题之一,本文将介绍在OpenCV中如何实现这一功能。
二、问题描述在计算机视觉领域中,常常需要对图像中的特征点进行匹配,从而得到这些特征点的映射关系。
在实际应用中,一般我们会有两组特征点,分别是原始图像中的特征点和目标图像中的特征点,我们需要计算这两组特征点之间的映射关系。
三、OpenCV中的解决方案在OpenCV中,我们可以使用cv::findHomography函数来计算两组特征点之间的映射关系。
该函数的原型如下:cv::Mat cv::findHomography(InputArray srcPoints, // 原始图像中的特征点InputArray dstPoints, // 目标图像中的特征点int method=0, // 计算方法double ransacReprojThreshold=3, // 阈值OutputArray mask=noArray() // 输出的掩模);其中,srcPoints和dstPoints分别是原始图像中的特征点和目标图像中的特征点。
method参数指定了计算映射关系的方法,通常情况下可以使用默认值。
ransacReprojThreshold参数是RANSAC算法的阈值,用于剔除错误匹配的点。
最后一个参数mask是用来输出RANSAC算法的掩模,用于标识哪些点是正确匹配的。
四、示例代码下面是一个使用findHomography函数计算特征点映射关系的示例代码:```cpp#include <opencv2/opencv.hpp>int main() {// 读入原始图像和目标图像cv::Mat srcImage = cv::imread("src.jpg");cv::Mat dstImage = cv::imread("dst.jpg");// 使用ORB算法提取特征点cv::Ptr<cv::Feature2D> feature = cv::ORB::create();std::vector<cv::KeyPoint> srcKeyPoints, dstKeyPoints;cv::Mat srcDescriptors, dstDescriptors;feature->detectAndCompute(srcImage, cv::noArray(), srcKeyPoints, srcDescriptors);feature->detectAndCompute(dstImage, cv::noArray(), dstKeyPoints, dstDescriptors);// 计算特征点的映射关系std::vector<cv::DMatch> matches;cv::BFMatcher matcher(cv::NORM_HAMMING);matcher.match(srcDescriptors, dstDescriptors, matches);// 取出匹配的特征点std::vector<cv::Point2f> srcPoints, dstPoints;for (int i = 0; i < matches.size(); i++) {srcPoints.push_back(srcKeyPoints[matches[i].queryIdx].pt); dstPoints.push_back(dstKeyPoints[matches[i].trainIdx].pt); }// 计算映射关系cv::Mat H = cv::findHomography(srcPoints, dstPoints, cv::RANSAC);return 0;}```以上代码使用了ORB算法提取了图像的特征点,并通过BFMatcher 进行了特征点的匹配,然后利用findHomography函数计算了特征点的映射关系。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
OpenCV中文站中有一篇关于OpenCV基础操作的文章《OpenCV 编程简介(矩阵/图像/视频的基本读写操作)入门必读》,上面对OpenCV的一些入门操作进行了详细的介绍。
我也是看了这篇文章后才开始了OpenCV的编程。
但是最近发现了一个理解上的小失误,导致一个问题困扰了很长时间。
现在问题解决了,就把思考的过程写在这跟大家分享一下。
该文章其中有一部分是关于如何操作图像像素值的介绍:基于指针的直接访问:(简单高效)IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);int height = img->height;int width = img->width;int step = img->widthStep/sizeof(uchar);uchar* data = (uchar *)img->imageData;data[i*step+j] = 111;对像素值的访问,作者用了data[i*step+j]这样的格式,当时没怎么仔细想,就认为这是图像中坐标为(i, j)像素的值,其实并不是这样的。
首先,来看一下IplImage的结构,其中像素值存放在char *imageData指针做指向的区域,OpenCV官方文档中将其解释为"A pointer to the aligned image data",就是指向排列好的图像数据的指针。
但是指针取出来,是一个一维数组data[i*step+j],是怎么体现出“排列好的”这个性质的呢?OpenCV用了一个辅助的变量来实现。
就是IplImage的widthStep,它表示图像一行有多少个字节。
用这个值除以一个像素所占的字节数,就可以得到一行有多少个像素。
data[i*step+j]就是第i行第j个像素的像素值(i和j从0开始,这个应该不用我说吧)。
但是,如果用(i, j)来表示坐标的话,正好反了。
因为行号是在列的方向递增的。
比如说第5行,那么它的纵坐标应该是5-1。
第五行的第几个,这个几才代表横坐标。
明白了这点就好办了,如果想用(i, j)同时来表示坐标和数组中的点,那么应该用data[i+j*step]。
i在图像宽度范围内递增,j在图像高度范围内递增。
如果图像宽和高非别为w和h,那么对像素的遍历可以用下面的循环搞定:for(int j = 0; j < h; j++) {for(int i = 0; i < w; i++) {printf("(%d, %d)=%d\t", i, j, data[i+j*step]);}}以后就定义成data[i+j*step],方便后面的操作。
一般情况下还是习惯i在前、j在后的格式。
(坐标是从0开始的,并且是相对图像原点的位置。
图像原点或者是左上角(img->origin=IPL_ORIGIN_TL) 或者是左下角 (img->origin=IPL_ORIGIN_BL) )∙假设有 8-bit 1-通道的图像 I (IplImage* img):I(x,y) ~ ((uchar*)(img->imageData + img->widthStep*y))[x]∙假设有 8-bit 3-通道的图像 I (IplImage* img):I(x,y)blue ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3]I(x,y)green ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3+1]I(x,y)red ~ ((uchar*)(img->imageData + img->widthStep*y))[x*3+2]例如,给点 (100,100) 的亮度增加 30 ,那么可以这样做:CvPoint pt = {100,100};((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3] += 30;((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+1] += 30;((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3+2] += 30;或者更高效地:CvPoint pt = {100,100};uchar* temp_ptr = &((uchar*)(img->imageData + img->widthStep*pt.y))[pt.x*3]; temp_ptr[0] += 30;temp_ptr[1] += 30;temp_ptr[2] += 30;∙假设有 32-bit 浮点数, 1-通道图像 I (IplImage* img):I(x,y) ~ ((float*)(img->imageData + img->widthStep*y))[x]∙现在,一般的情况下,假设有 N-通道,类型为 T 的图像:I(x,y)c ~ ((T*)(img->imageData + img->widthStep*y))[x*N + c]你可以使用宏 CV_IMAGE_ELEM( image_header, elemtype, y, x_Nc )I(x,y)c ~ CV_IMAGE_ELEM( img, T, y, x*N + c )也有针对各种图像(包括 4 通道图像)和矩阵的函数(cvGet2D, cvSet2D),但是它们非常慢。
如何访问矩阵元素?方法是类似的(下面的例子都是针对 0 起点的列和行)∙设有 32-bit 浮点数的实数矩阵 M (CvMat* mat):M(i,j) ~ ((float*)(mat->data.ptr + mat->step*i))[j]∙设有 64-bit 浮点数的复数矩阵 M (CvMat* mat):Re M(i,j) ~ ((double*)(mat->data.ptr + mat->step*i))[j*2]Im M(i,j) ~ ((double*)(mat->data.ptr + mat->step*i))[j*2+1]∙对单通道矩阵,有宏 CV_MAT_ELEM( matrix, elemtype, row, col ), 例如对 32-bit 浮点数的实数矩阵:M(i,j) ~ CV_MAT_ELEM( mat, float, i, j ),例如,这儿是一个 3x3 单位矩阵的初始化:CV_MAT_ELEM( mat, float, 0, 0 ) = 1.f;CV_MAT_ELEM( mat, float, 0, 1 ) = 0.f;CV_MAT_ELEM( mat, float, 0, 2 ) = 0.f;CV_MAT_ELEM( mat, float, 1, 0 ) = 0.f;CV_MAT_ELEM( mat, float, 1, 1 ) = 1.f;CV_MAT_ELEM( mat, float, 1, 2 ) = 0.f;CV_MAT_ELEM( mat, float, 2, 0 ) = 0.f;CV_MAT_ELEM( mat, float, 2, 1 ) = 0.f;CV_MAT_ELEM( mat, float, 2, 2 ) = 1.f;OpenCV中获取图像某一像素值收藏This is a basic example for the OpenCV.First we must know the structure of IplImage:IPL image:IplImage|-- int nChannels; // Number of color channels (1,2,3,4)|-- int depth; // Pixel depth in bits:| // IPL_DEPTH_8U, IPL_DEPTH_8S,| // IPL_DEPTH_16U,IPL_DEPTH_16S,| // IPL_DEPTH_32S,IPL_DEPTH_32F,| // IPL_DEPTH_64F|-- int width; // image width in pixels|-- int height; // image height in pixels|-- char* imageData; // pointer to aligned image data| // Note that color images are stored in BGR order|-- int dataOrder; // 0 - interleaved color channels,| // 1 - separate color channels| // cvCreateImage can only create interleaved images|-- int origin; // 0 - top-left origin,| // 1 - bottom-left origin (Windows bitmaps style)|-- int widthStep; // size of aligned image row in bytes|-- int imageSize; // image data size in bytes = height*widthStep|-- struct _IplROI *roi;// image ROI. when not NULL specifies image| // region to be processed.|-- char *imageDataOrigin; // pointer to the unaligned origin of image data | // (needed for correct image deallocation)||-- int align; // Alignment of image rows: 4 or 8 byte alignment| // OpenCV ignores this and uses widthStep instead|-- char colorModel[4]; // Color model - ignored by OpenCV//------------------------------------------------------------------------------int main(int argc, char* argv[])...{IplImage *img=cvLoadImage("c://fruitfs.bmp",1);CvScalar s;for(int i=0;i<img->height;i++)...{for(int j=0;j<img->width;j++)...{s=cvGet2D(img,i,j); // get the (i,j) pixel valueprintf("B=%f, G=%f, R=%f ",s.val[0],s.val[1],s.val[2]);s.val[0]=111;s.val[1]=111;s.val[2]=111;cvSet2D(img,i,j,s);//set the (i,j) pixel value}}cvNamedWindow("Image",1);cvShowImage("Image",img);cvWaitKey(0); //等待按键cvDestroyWindow( "Image" );//销毁窗口cvReleaseImage( &img ); //释放图像return 0;}其实还有更好的方法,例如将其封装成类,调用起来更加方便,效率也很高。