Mat和IplImage访问像素的方法总结
来源:互联网 发布:京津冀生态环境数据 编辑:程序博客网 时间:2024/05/21 20:08
在opencv的编程中,遍历访问图像元素是经常遇到的操作,掌握其方法非常重要,无论是Mat类的像素访问,还是IplImage结构体的访问的方法,都必须扎实掌握,毕竟,图像处理本质上就是对像素的各种操作,访问元素就是各种图像处理算法的第一步。
首先先看看图像的是怎么存储的。
单通道图像
多通道图像
Mat访问图像元素方法汇总
1.用指针访问元素
在大多数图像处理任务中, 执行计算时你都需要对图像的所有像素进行扫描。 当需要访问的像素数量非常庞大, 你必须采用高效的方式来执行这个任务来提高效率。 如果你需要高效扫描大图片的数据,那么请使用指针方式。
#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp>using namespace std;using namespace cv;int main(int argc, char** argv){ Mat img = imread("lena.jpg", 1); if (img.empty()) { cout << "fail to read image" << endl; return -1; } Mat img1 = img.clone(); int div = 64; /* 方法1:用指针访问 */ //多通道访问法1 int rows = img1.rows; int cols = img1.cols; for (int i = 0; i < rows; i++) { //uchar* p = img1.ptr<uchar>(i); //获取第i行的首地址 for (int j = 0; j < cols; j++) { //在这里操作具体元素 uchar *p = img1.ptr<uchar>(i, j); p[0] = p[0] / div*div + div / 2; p[1] = p[1] / div*div + div / 2; p[2] = p[2] / div*div + div / 2; } } imshow("lean", img1); //多通道访问法2 Mat img3 = img.clone(); int channels = img3.channels(); //获取通道数 int rows3 = img3.rows; int cols3 = img3.cols* channels; //注意,是列数*通道数 for (int i = 0; i < rows3; i++) { uchar* p = img3.ptr<uchar>(i); //获取第i行的首地址 for (int j = 0; j < cols3; j++) { //在这里操作具体元素 p[j] = p[j] / div*div + div / 2; p[j+1] = p[j+1] / div*div + div / 2; p[j+2] = p[j+2] / div*div + div / 2; } } imshow("lean3", img3); //单通道图像 Mat img2 = img.clone(); cvtColor(img2, img2, COLOR_BGR2GRAY); for (int i = 0; i < img2.rows; i++) { uchar* p = img2.ptr<uchar>(i); //获取第i行的首地址 for (int j = 0; j < img2.cols; j++) { //在这里操作具体元素 p[j] = p[j] / div*div + div / 2; } } imshow("lean2", img2); waitKey(0); return 0;}
2.用迭代器访问元素
在面向对象编程时, 我们通常用迭代器对数据集合进行循环遍历。 标准模板库(STL) 对每个集合类都定义了对应的迭代器类, OpenCV也提供了cv::Mat的迭代器类, 并且与C++ STL中的标准迭代器兼容。
#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp>using namespace std;using namespace cv;int main(int argc, char** argv){ Mat img = imread("lena.jpg",1); //载入灰度图 Mat img1 = img.clone(); int div = 64; /* 方法2:用迭代器访问 */ /******************多通道的可以这么写***************/ Mat_<Vec3b>::iterator it = img1.begin<Vec3b>(); //获取起始迭代器 Mat_<Vec3b>::iterator it_end = img1.end<Vec3b>(); //获取结束迭代器 for (; it != it_end; it++) { //在这里分别访问每个通道的元素 (*it)[0] = (*it)[0] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; (*it)[1] = (*it)[1] / div*div + div / 2; } imshow("lean", img1); /******************单通道的可以这么写***************/ Mat img2; cvtColor(img, img2, COLOR_RGB2GRAY); //转化为单通道灰度图 Mat_<uchar>::iterator it2 = img2.begin<uchar>(); //获取起始迭代器 Mat_<uchar>::iterator it_end2 = img2.end<uchar>(); //获取结束迭代器 for (; it2 != it_end2; it2++) { //在这里分别访问每个通道的元素 *it2 = *it2 / div*div + div / 2; } imshow("lena2", img2); waitKey(0); return 0;}}
若要从图像的第二行开始,程序该怎么修改? 我们可以用
image.begin<cv::Vec3b>()+image.cols
初始化cv::Mat迭代器。 获得集合结束位置的方法也类似, 只是改用end方法。 但是, 用end方法得到的迭代器已经超出了集合范围, 因此必须在结束位置停止迭代过程。 结束的迭代器也能使用数学计算, 例如, 如果你想在最后一行前就结束迭代, 可使用
image.end<cv::Vec3b>()-image.cols
3.动态地址+at()访问元素
#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp>using namespace std;using namespace cv;int main(int argc, char** argv){ Mat img = imread("lena.jpg",1); Mat img1 = img.clone(); int div = 64; /* 方法3:用at访问 */ /****************访问多通道元素*********************/ int rows = img1.rows; int cols = img1.cols; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { //在这里访问每个通道的元素,注意,成员函数at(int y,int x)的参数 img1.at<Vec3b>(i,j)[0] = img1.at<Vec3b>(i, j)[0] / div*div + div / 2; img1.at<Vec3b>(i, j)[1] = img1.at<Vec3b>(i, j)[1] / div*div + div / 2; img1.at<Vec3b>(i, j)[2] = img1.at<Vec3b>(i, j)[2] / div*div + div / 2; } } imshow("lena", img1); /****************访问单通道元素*********************/ Mat img2; cvtColor(img, img2, COLOR_RGB2GRAY); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { //在这里访问每个通道的元素,注意,成员函数at(int y,int x)的参数 img2.at<uchar>(i, j) = img2.at<uchar>(i, j) / div*div + div / 2; } } imshow("lena2", img2); waitKey(0); return 0;}
IplImage访问元素方法汇总
1.使用cvGet2D()函数访问
#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp>using namespace std;using namespace cv;int main(int argc, char** argv){ /*访问单通道元素*/ IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1); //单通道图像 CvScalar s; double tmp; for (int i = 0; i < img->height; i++) { for (int j = 0; j < img->width; j++) { //可以在这里访问元素 tmp = cvGet2D(img, i, j).val[0]; cvSet2D(img, i, j, 255); //第三个参数是要设置的值 } } cvShowImage("img", img); /*访问多通道元素*/ IplImage* img2 = cvCreateImage(cvSize(640, 480), IPL_DEPTH_32F, 3); double tmpb, tmpg, tmpr; for (int i = 0; i < img->height; i++) { for (int j = 0; j < img->width; j++) { tmpb = cvGet2D(img, i, j).val[0]; tmpg = cvGet2D(img, i, j).val[1]; tmpr = cvGet2D(img, i, j).val[2]; cvSet2D(img2, i, j, CvScalar(255,255,255)); //第三个参数是要设置的值,三个通道一起设置 } } cvShowImage("img2", img2); waitKey(0); return 0;}
2.指针方式直接访问
追求高效率地访问元素请使用该方法。
#include<opencv2\opencv.hpp> #include<opencv2\highgui\highgui.hpp>using namespace std;using namespace cv;int main(int argc, char** argv){ /*访问多通道元素*/ IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 3); uchar* data = (uchar *)img->imageData; int step = img->widthStep / sizeof(uchar); int channels = img->nChannels; uchar b, g, r; for (int i = 0; i < img->height; i++) { for (int j = 0; j < img->width; j++) { //获得元素的值 b = data[i*step + j*channels + 0]; g = data[i*step + j*channels + 1]; r = data[i*step + j*channels + 2]; //修改元素的值 data[i*step + j*channels + 0] = 255; } } cvShowImage("img", img); /*访问单通道元素*/ IplImage* img2 = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1); uchar* data2 = (uchar *)img2->imageData; int step2 = img2->widthStep / sizeof(uchar); uchar v; for (int i = 0; i < img2->height; i++) { for (int j = 0; j < img2->width; j++) { //获得元素的值 v = data2[i*step2 + j]; //修改元素的值 data2[i*step2 + j] = 255; } } cvShowImage("img2", img2); waitKey(0); return 0;}
阅读全文
0 0
- Mat和IplImage访问像素的方法总结
- Alpha通道?Mat和IplImage访问像素、uchar、Scalar?
- IplImage和Mat访问图像中每个像素
- 访问Mat图像中的每个像素的值和IplImage格式图像中每个像素的值
- OpenCV 中cv::Mat 和 IplImage 的转换总结
- IplImage和Mat的转换
- Opencv 访问Mat中像素的值的快速方法
- opencv访问(Mat)图像的像素方法汇总
- cv::Mat,cvMat和IplImage的相互转换方法
- cv::Mat,cvMat和IplImage的相互转换方法
- Mat,cvMat和IplImage的相互转换方法
- cv::Mat,cvMat和IplImage的相互转换方法
- IplImage\Mat\CvMat像素处理
- 【OpenCV】cv::Mat对单个像素的访问和操作
- IplImage像素访问
- iplimage 像素访问
- IplImage 类型与Mat 类型数据访问方法
- opencv像素的访问(Mat)
- 【Scikit-Learn 中文文档】交叉分解
- PHP重置数组为连续数字索引的几种方式
- C# ConcurrentStack实现
- linux下生成core dump文件方法及设置 bug定位
- MyBatis初学
- Mat和IplImage访问像素的方法总结
- gpio学习
- 2017年11月12日所看链接(GSON 泛型 下载)
- iOS性能优化系列之__builtin_expect分支预测优化
- 如何扛住1.8亿/秒的双11数据洪峰?阿里流计算技术全揭秘
- 基础登录界面+第三方登录代码片
- 获得下拉列表中的选中值
- ttyUSB
- Activiti 外置表单的一种简单部署方式