访问像素的三种方法

①指针访问:最快

②迭代器iterator:较慢,非常安全,指针访问可能出现越界问题

③动态地址计算:更慢,通过at()实现。适用于访问具体某个第i行,j列的像素,而不适用遍历像素

Mat在内存中存储形式

  灰度图的存储形式

    

  RGB的存储形式

  

一般情况下,Mat是连续存储的,按行连接。可以通过isContinuous()函数,判断矩阵是否连续存储,若连续返回true。

访问像素的三种方法

1.指针访问

 void VisitImgByPointer(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
int rows = dstImg.rows;
int cols = dstImg.cols * dstImg.channels(); for(int i = ; i < rows; i++)
{
uchar* data = dstImg.ptr<uchar>(i);
for(int j = ; j < cols; j++)
{
data[j] = ; //处理每一个像素
//add code
}
}
}

当Mat按行连续存储时,可以用指针直接访问所有数据。

 void VisitContinueImgByPointer(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
int rows = dstImg.rows;
int cols = dstImg.cols;
int channels = dstImg.channels(); if(dstImg.isContinuous())
{
cols *= rows;
rows = ;
//cout << "is continuous " << endl;
} for(int i = ; i < rows; i++)
{
uchar* data = dstImg.ptr<uchar>(i);
for(int j = ; j < cols * channels; j++)
{
data[j] = ; //处理每一个像素
//add code
}
}
//若存储连续,等效于以下代码
//uchar* data = dstImg.data;
//for(int i = 0; i < cols * rows * channels; i++)
// data[i] = 155; //处理每一个像素 }

2.迭代器访问

 void VisitImgByIterator(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
const int channels = dstImg.channels(); switch(channels)
{
case :
{
Mat_<uchar>::iterator it= dstImg.begin<uchar>();
Mat_<uchar>::iterator itend= dstImg.end<uchar>();
for ( ; it!= itend; it++) //处理每一个像素
{
*it = ;
}
break;
}
case :
{
Mat_<Vec3b>::iterator it3= dstImg.begin<Vec3b>();
Mat_<Vec3b>::iterator itend3= dstImg.end<Vec3b>();
for ( ; it3!= itend3; it3++) //处理每一个像素
{
(*it3)[]= ;
(*it3)[]= ;
(*it3)[]= ;
}
break;
}
}
}

3.动态地址访问

 void VisitImgByAt(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
int rows = dstImg.rows;
int cols = dstImg.cols;
int channels = dstImg.channels(); switch(channels)
{
case :
{
for(int i = ; i < rows; i++)
for(int j = ; j < cols; j++)
dstImg.at<uchar>(i,j) = ;
break;
}
case :
{
for(int i = ; i < rows; i++)
for(int j = ; j < cols; j++)
{
dstImg.at<Vec3b>(i,j)[] = ;
dstImg.at<Vec3b>(i,j)[] = ;
dstImg.at<Vec3b>(i,j)[] = ;
}
break;
}
}
}

测试代码-总

 #include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std; void VisitImgByPointer(Mat &inputImg, Mat &dstImg);
void VisitContinueImgByPointer(Mat &inputImg, Mat &dstImg);
void VisitImgByIterator(Mat &inputImg, Mat &dstImg);
void VisitImgByAt(Mat &inputImg, Mat &dstImg); int main()
{
Mat srcImg = imread("pig.png"), dstImg;
Mat grayImg;
cvtColor(srcImg, grayImg, CV_BGR2GRAY);
//VisitImgByPointer(srcImg,dstImg);
//VisitContinueImgByPointer(grayImg,dstImg); //VisitImgByIterator(srcImg,dstImg);
//VisitImgByIterator(grayImg,dstImg); //VisitImgByAt(srcImg,dstImg);
VisitImgByAt(grayImg,dstImg); //imshow("原始图", srcImg);
//imshow("灰度图", grayImg);
imshow("生成图", dstImg); waitKey();
return ;
} void VisitImgByPointer(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
int rows = dstImg.rows;
int cols = dstImg.cols * dstImg.channels(); for(int i = ; i < rows; i++)
{
uchar* data = dstImg.ptr<uchar>(i);
for(int j = ; j < cols; j++)
{
data[j] = ; //处理每一个像素
//add code
}
}
} void VisitContinueImgByPointer(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
int rows = dstImg.rows;
int cols = dstImg.cols;
int channels = dstImg.channels(); if(dstImg.isContinuous())
{
cols *= rows;
rows = ;
//cout << "is continuous " << endl;
} for(int i = ; i < rows; i++)
{
uchar* data = dstImg.ptr<uchar>(i);
for(int j = ; j < cols * channels; j++)
{
data[j] = ; //处理每一个像素
//add code
}
}
//若存储连续,等效于一下代码
//uchar* data = dstImg.data;
//for(int i = 0; i < cols * rows * channels; i++)
// data[i] = 155; //处理每一个像素 } void VisitImgByIterator(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
const int channels = dstImg.channels(); switch(channels)
{
case :
{
Mat_<uchar>::iterator it= dstImg.begin<uchar>();
Mat_<uchar>::iterator itend= dstImg.end<uchar>();
for ( ; it!= itend; it++) //处理每一个像素
{
*it = ;
}
break;
}
case :
{
Mat_<Vec3b>::iterator it3= dstImg.begin<Vec3b>();
Mat_<Vec3b>::iterator itend3= dstImg.end<Vec3b>();
for ( ; it3!= itend3; it3++) //处理每一个像素
{
(*it3)[]= ;
(*it3)[]= ;
(*it3)[]= ;
}
break;
}
}
} void VisitImgByAt(Mat &inputImg, Mat &dstImg)
{
dstImg = inputImg.clone();
int rows = dstImg.rows;
int cols = dstImg.cols;
int channels = dstImg.channels(); switch(channels)
{
case :
{
for(int i = ; i < rows; i++)
for(int j = ; j < cols; j++)
dstImg.at<uchar>(i,j) = ;
break;
}
case :
{
for(int i = ; i < rows; i++)
for(int j = ; j < cols; j++)
{
dstImg.at<Vec3b>(i,j)[] = ;
dstImg.at<Vec3b>(i,j)[] = ;
dstImg.at<Vec3b>(i,j)[] = ;
}
break;
}
}
}

opencv之访问图像像素的更多相关文章

  1. opencv 访问图像像素的三种方式

    访问图像中的像素 访问图像像素有三种可行的方法方法一:指针访问指针访问访问的速度最快,Mat类可以通过ptr函数得到图像任意一行的首地址,同时,Mat类的一些属性也可以用到公有属性 rows和cols ...

  2. opencv学习笔记(八)IplImage* 访问图像像素的值

    opencv2.1版本之前使用IplImage*数据结构来表示图像,2.1之后的版本使用图像容器Mat来存储.IplImage结构体如下所示. typedef struct _IplImage { i ...

  3. opencv学习笔记(九)Mat 访问图像像素的值

    对图像的像素进行访问,可以实现空间增强,反色,大部分图像特效系列都是基于像素操作的.图像容器Mat是一个矩阵的形式,一般情况下是二维的.单通道灰度图一般存放的是<uchar>类型,其数据存 ...

  4. opencv学习之路(7)、访问图像像素

    一.动态地址访问 #include <opencv2/opencv.hpp> #include<iostream> using namespace cv; using name ...

  5. 【OpenCV】访问图像中每个像素的值

    http://blog.csdn.net/xiaowei_cqu/article/details/7557063

  6. 【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整

    今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度. 在之前我们先来看一下图像矩阵数据的排列方式.我们以一个简单的矩阵来说明: 对单通道图像排列如下: 对于双通道图像排列如下: 那么对 ...

  7. opencv 3 core组件进阶(1 访问图像中的像素)

    访问图像像素的三类方法 ·方法一 指针访问:C操作符[ ]; ·方法二 迭代器iterator; ·方法三 动态地址计算. #include <opencv2/core/core.hpp> ...

  8. OpenCV坐标系与操作像素的四种方法

    像素是图像的基本组成单位,熟悉了如何操作像素,就能更好的理解对图像的各种处理变换的实现方式了. 1.at方法 第一种操作像素的方法是使用"at",如一幅3通道的彩色图像image的 ...

  9. 访问图像中的像素[OpenCV 笔记16]

    再更一发好久没更过的OpenCV,不过其实写到这个部分对计算机视觉算法有所了解的应该可以做到用什么查什么了,所以后面可能会更的慢一点吧,既然开了新坑,还是机器学习更有研究价值吧... 图像在内存中的存 ...

随机推荐

  1. docker——安全防护与配置

    Docker是基于Linux操作系统实现的应用虚拟化.运行在容器内的进程,跟运行在本地系统的进程本质上并无区别,配置不合适的安全策略将可能给本地系统带来安全风险,因此,Docker的安全性在生产环境中 ...

  2. Liferay portlet首选项(preferences)设置、存储处理

    最近使用Liferay做项目集成,由于团队人员在之前对Liferay这东西都没有充分的了解,用起来着实费了不少力气,最近为了为定制好的portlet添加初始化信息,翻阅了一些文章,下面是了解到的关于初 ...

  3. idea中使用插件Grep Console在IDEA的log的不同的级别,可以设置不同的颜色。

    一.安装. 1. 2. 3. 二,使用. 1. 2.

  4. http之请求方法

    根据HTTP标准,HTTP请求可以使用多种请求方法.HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法.HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE ...

  5. 234. Palindrome Linked List(判断链表是否回文)

    Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) time ...

  6. uwsgi手动安装时报错ValueError: invalid literal for int() with base 10: '32_1'

    安装uwsgi,安装步骤如下 wget https://projects.unbit.it/downloads/uwsgi-latest.tar.gz tar zxvf uwsgi-latest.ta ...

  7. FlexPaper_1.2.1.swc——Flex在线显示PDF文档(使用FlexPaper)感悟

    http://www.cnblogs.com/wuhenke/archive/2010/03/16/1686885.html 想想自己先前搞PDF转SWF,然后在线浏览功能时,实在是费了不少精力.后来 ...

  8. 使用NodeJS将文件或图像上传到服务器

    原文链接:http://www.codeceo.com/article/nodejs-upload-file-to-server.html

  9. linux内核分析第四周-使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

    本周作业的主要内容就是采用gcc嵌入汇编的方式调用system call.系统调用其实就是操作系统提供的服务.我们平时编写的程序,如果仅仅是数值计算,那么所有的过程都是在用户态完成的,但是我们想将变量 ...

  10. 学习java的一点体会

    在这几天的做实验.读书.写笔记的过程中我发现一个问题,就是我的知识面太窄,就比如说,学的知识都是一块一块的,没有能力去把它串起来,虽然学的很快,也写笔记总结,但马上就忘了,我想java是一个体系,需要 ...