opencv学习笔记——访问图像中的像素
来源:互联网 发布:网络通信有哪些 编辑:程序博客网 时间:2024/06/07 15:34
1、图像的存储方式
图像矩阵的大小取决于所用的颜色模型,确切的说取决于所用通道数。
灰度图像模型的矩阵排列
灰度图像按行列存储,每列仅含一个通道。
RGB颜色模型的矩阵排列
对于多通道图像,矩阵中的列会包含多个子列,子列个数与通道数相等。子列的通道顺序是反过来的BGR。
因为内存足够大,图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行。有助于提升图像扫描速度。
2、颜色空间缩减
颜色空间缩减:将现有颜色空间值初一某个输入值,以获得较少的颜色数。
例如uchar类型的三通道图像,有256*256*256个不同的值。使用公式将颜色取值降低为26*26*26种情况。
处理图像时每个像素需要进行一遍上述计算,要花费一定的时间。可以把计算好的结果提前存在表table中。取值方法
P[j] = table[P[j]]
。 颜色空间缩减的两个步骤:
- 遍历图像矩阵的每一个像素。
- 对像素应用缩减公式。
运算时尽可能用代价较低的加、减、赋值等运算代替乘除运算。
3、LUT函数
对于Look up table操作,官方推荐使用operationsOnArrays::LUT()的函数进行图像元素查找、扫描与操作图像。
//建立一个Mat型用于查表Mat lookUpTable(1, 256, CV_8U);uchar *p = lookUpTable.data;for (int i = 0; i < 256; ++i) p[i] = table[i];//调用函数(I是输入,J是输出)for (int i = 0; i < times; ++i) LUT(I, lookUpTable, J);
4、计时函数
计时函数:getTickCount()和getTickFrequency()。
getTickCount()函数返回CPU自某个事件以来走过的时钟周期数。
getTickFrequency()函数返回CPU一秒钟所走的时钟周期数。
double time0 = static_cast<double>(getTickCount()); //记录起始时间//进行图像处理操作time0 = ((double)getTickCount() - time0) / getTickFrequency();
5、访问像素的方法
OpenCV提供三种访问每个像素的方法:
- 指针访问:C操作符[];
- 迭代器iterator。
- 动态地址计算
debug模式下,三种方法访问速度差异明显,release模式下不明显。
主程序代码:
#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <iostream>using namespace std;using namespace cv;void colorReduce(Mat& inputImage, Mat& outputImage, int div);int main(){ //1.创建原始图并显示 Mat srcImage = imread("1.jpg"); imshow("原始图像", srcImage); //2.按原始图的参数规格来创建效果图 Mat dstImage; dstImage.create(srcImage.rows, srcImage.cols, srcImage.type()); //效果图大小、类型与原图片相同 //3.记录起始时间 double time0 = static_cast<double>(getTickCount()); //4.调用颜色空间缩减函数 colorReduce(srcImage, dstImage, 4); //5.计算运行时间并输出 time0 = ((double)getTickCount() - time0) / getTickFrequency(); cout << "此方法运行时间为: " << time0 << "秒" << endl; //6.显示效果图 imshow("效果图", dstImage); waitKey(0);}
5.1 用指针访问像素
函数代码:
void colorReduce(Mat& inputImage, Mat& outputImage, int div){ //参数准备 outputImage = inputImage.clone(); //复制实参到临时变量 int rowNumber = outputImage.rows; //行数 int colNumber = outputImage.cols * outputImage.channels(); //列数*通道数=每一行元素的个数 //双重循环,遍历所有的像素值 for (int i = 0; i < rowNumber; i++) { uchar *data = outputImage.ptr<uchar>(i); //获取第i行的首地址 for (int j = 0; j < colNumber; j++) { //处理每个像素 data[j] = data[j] / div * div + div / 2; } }}
运行结果:
5.2 迭代器操作像素
获取图像的begin和end,然后增加迭代直至从begin到end。将*
操作符添加在迭代指针前,即可访问当前指向的内容。
相比用指针直接访问可能出现越界问题,迭代器是非常安全的方法。
函数代码:
void colorReduce(Mat& inputImage, Mat& outputImage, int div){ //参数准备 outputImage = inputImage.clone(); //复制实参到临时变量 //获取迭代器 //8U 类型的 RGB 彩色图像可使用<Vec3b> Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>(); //初始位置的迭代器 Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>(); //终止位置的迭代器 //存取彩色图像像素 for (; it != itend; it++) { //处理每个像素 (*it)[0] = (*it)[0] / div * div + div / 2; (*it)[1] = (*it)[1] / div * div + div / 2; (*it)[2] = (*it)[2] / div * div + div / 2; }}
运行结果:
迭代器的相关知识可以使用关键字“STL 迭代器”进行搜索。
5.3 动态地址计算
函数代码:
void colorReduce(Mat& inputImage, Mat& outputImage, int div){ //参数准备 outputImage = inputImage.clone(); //复制实参到临时变量 int rowNumber = outputImage.rows; //行数 int colNumber = outputImage.cols; //列数 //存取彩色图像像素 for (int i = 0; i < rowNumber; i++) { for (int j = 0; j < colNumber; j++) { //处理每个像素 outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div * div + div / 2; outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div * div + div / 2; outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div * div + div / 2; } }}
运行结果:
成员函数at(int y, int x)
用来存取图像元素。指定的数据类型要和矩阵中的数据路诶性相符合。
彩色图像每个像素由三个部分构成:蓝色通道、绿色通道和红色通道(BGR)。一个包含彩色图像的Mat会返回一个由三个unsigned char组成的向量。OpenCV将此类型的向量定义为Vec3b,含义为由三个unsigned char组成的向量。
彩色图像像素的代码可以写为:
image.at<Vec3b>(j, i)[channel] = value;
- OpenCV学习笔记九——访问图像中的像素
- opencv学习笔记——访问图像中的像素
- 【OpenCV学习笔记】十、访问图像像素
- OpenCV:访问图像中的像素
- opencv学习笔记(十四)——图像像素的访问
- Opencv学习笔记——绘制图像的像素直方图
- opencv技术访问图像中的像素
- opencv访问图像像素
- opencv访问图像像素
- Opencv访问图像像素
- OpenCV学习笔记——使用OpenCV访问图像数据
- 【OpenCV学习笔记】【函数学习】二十(访问图像像素)
- Opencv学习笔记2--像素的访问
- OpenCV 2 学习笔记(5): 像素的访问:给图像加入椒盐噪声
- OpenCV学习笔记(七):访问图像中像素的三类方法
- OpenCV 2 访问图像像素
- OpenCV 访问图像像素点
- opencv(8)---访问图像像素
- Android Money测试基础一
- CentOS 7中创建新用户并授权
- 快速查找Maven依赖的库
- 根据年月日来判断其所对应的星期
- POJ 3159 差分约束+SPFA
- opencv学习笔记——访问图像中的像素
- HDU 2896 病毒侵袭(AC自动机)
- 机器学习缺失值处理方法汇总
- Python学习笔记——字符串
- 算法进阶3-6
- maven项目中jsp不能编译情况(Unable to compile class for JSP)
- 大数据:随机生成10万个整数找出出现次数前一百的数
- 2017年11月26日训练总结
- oracle---高级查询(二)