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

RGB图像,矩阵的列会包含多个子列

因为内存足够大,可以实现连续存储,因此,图像中的各行就能一行一行地连接起来,形成一个长行。连续存储,有助于提高图像扫面速度,可以使用isContinuous()来判断矩阵是否是连续存储。
颜色空间缩减
对于三通道图像,一个像素对应的颜色有一千六百多万种,用如此多的颜色可能会影响算法性能。颜色空间缩减即用颜色中具有代表性的一部分表示相近颜色,做法是:将现有颜色空间值除以某个输入值,以获得较少的颜色数。对每个像素进行乘除操作也需要浪费一定的时间(加,减,赋值等代价较低),对于较大的图像,可以预先计算所有可能的值,建立 look up table,
int divideWidth = ;
uchar table[];
for (int i = ; i < ; ++i)
table[i] = divideWidth * (i/divideWidth);
然后遍历图像矩阵的每个像素,对像素应用公式:
p[j] = table[p[j]];
OpenCV官方提供了函数进行图像元素查找、扫描与操作图像
void cv::LUT ( InputArray src,
InputArray lut,
OutputArray dst
)
进行look-up table转换操作,输出矩阵将被赋值为
dst(I)<-lut(src(I)+d)
其中,当src为CV_8U时,d=0,src为CV_8S时,d=128(用于把look up table输入转换到0~255)
- src:矩阵输入,矩阵元素为8-bit色彩值。
- lut:256个色彩值的look-up table,如果src为多通道函数,lut可为单通道(src每通道的处理方式相同)或与src的通道数相同。
- dst:与输入矩阵大小、通道数相同的输出矩阵src, 类型与lut相同(CV_8U或CV_8S)
用法示例如下,
Mat lookUpTable(, , CV_8U);
uchar* p = lookUpTable.data;
for(int i = ; i < ; ++i)
p[i] = table[i];
for(int i=; i < times; ++i)
LUT(Input,lookUpTable, Output);
计时函数
int64 getTickCount()
返回CPU自某个事件(如启动电脑)以来走过的时钟周期
double getTickFrequency()
返回CPU一秒钟所走过的时钟周期数,这样我们就可以以秒为单位对某运算计时
double time0 = stactic_cast<double>(getTickCount());
time0 = ((double) getTickCount() - time0) / getTickFrequency();
cout << "Runing time: " << time0 << "s" << endl;
访问图像中像素的三类方法
用指针访问像素
利用C中的操作符[]或*,这种方法最快,但比较抽象。
用迭代器操作像素
类似于STL中的用法,只需获取图像矩阵的begin和end,然后迭代从begin直至end。比前一种方法安全,不会越界,但速度慢。
动态地址计算
简单明了,直接用at(y,x)找到像素点,但是速度最慢。
上述三种方法的事例程序如下:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream> // function
void colorReduce(cv::Mat& inputImage, cv::Mat& outputImage, int div); // main
int main( int argc, char** argv )
{
// Load image
cv::Mat srcImage = cv::imread("1.jpg");
imshow("orginal image", srcImage); // alocate space for output image
cv::Mat dstImage;
dstImage.create(srcImage.rows, srcImage.cols, srcImage.type()); // get the starting time
double time0 = static_cast<double>(cv::getTickCount()); // call color space reduction function
colorReduce(srcImage, dstImage, ); // estimate runing time
time0 = ((double)cv::getTickCount() - time0)/cv::getTickFrequency();
std::cout << "Running time for this method: " << time0 << "s." << std::endl; imshow("Lab Space", dstImage);
cv::waitKey(); return ;
} #define USESUBS
#ifdef USEPOINTER
void colorReduce(cv::Mat& inputImage, cv::Mat& outputImage, int div)
{
// set parameters
outputImage = inputImage.clone();
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols*outputImage.channels(); for(int i = ;i < rowNumber;i++)
{
uchar* data = outputImage.ptr<uchar>(i);
// get the address of the ith row
for(int j=; j<colNumber; j++)
{
data[j] = data[j]/div*div + div/;
}
} }
#endif
#ifdef USEITERATOR
void colorReduce(cv::Mat& inputImage, cv::Mat& outputImage, int div)
{
// set parameters
outputImage = inputImage.clone(); // get the iterator
cv::Mat_<cv::Vec3b>::iterator it = outputImage.begin<cv::Vec3b>();
cv::Mat_<cv::Vec3b>::iterator itend = outputImage.end<cv::Vec3b>(); // save new pixel colors
for(;it != itend; ++it)
{
(*it)[] = (*it)[]/div*div + div/; // B
(*it)[] = (*it)[]/div*div + div/; // G
(*it)[] = (*it)[]/div*div + div/; // R
} }
#endif
#ifdef USESUBS
void colorReduce(cv::Mat& inputImage, cv::Mat& outputImage, int div)
{
// set parameters
outputImage = inputImage.clone();
int rowNumber = outputImage.rows;
int colNumber = outputImage.cols; // save new pixel colors
for(int i=; i<rowNumber; i++)
{
for(int j=; j<colNumber; j++)
{
outputImage.at<cv::Vec3b>(i,j)[] = outputImage.at<cv::Vec3b>(i,j)[]/div*div + div/; // B
outputImage.at<cv::Vec3b>(i,j)[] = outputImage.at<cv::Vec3b>(i,j)[]/div*div + div/; // G
outputImage.at<cv::Vec3b>(i,j)[] = outputImage.at<cv::Vec3b>(i,j)[]/div*div + div/; // R
}
} }
#endif
/*
Outputs:
USEPOINTER
Running time for this method: 0.0162628s.
USEITERATOR
Running time for this method: 0.0362183s.
USESUBS
Running time for this method: 0.0518141s.
*/
访问图像中的像素[OpenCV 笔记16]的更多相关文章
- 【opencv学习笔记七】访问图像中的像素与图像亮度对比度调整
今天我们来看一下如何访问图像的像素,以及如何改变图像的亮度与对比度. 在之前我们先来看一下图像矩阵数据的排列方式.我们以一个简单的矩阵来说明: 对单通道图像排列如下: 对于双通道图像排列如下: 那么对 ...
- opencv 3 core组件进阶(1 访问图像中的像素)
访问图像像素的三类方法 ·方法一 指针访问:C操作符[ ]; ·方法二 迭代器iterator; ·方法三 动态地址计算. #include <opencv2/core/core.hpp> ...
- 查找并绘制轮廓[OpenCV 笔记XX]
好久没有更新了,原谅自己放了个假最近又在赶进度,所以...更新的内容是很靠后的第八章,因为最近工作要用就先跳了,后面会更新笔记编号...加油加油! 在二值图像中寻找轮廓 void cv::findCo ...
- 图像显示 imshow()[OpenCV 笔记5]
void imshow(const string& winname InputArray mat); winname 窗口表识名称 mat 需要显示的图像.InputArray类型,声明如下 ...
- 视频处理简单实例 [OpenCV 笔记2]
VideoCapture是OpenCV 2.X中新增的类,提供从摄像机或视频文件捕获视频的C++接口.利用它读入视频的方法一般有两种: // method 1 VideoCapture capture ...
- 【OpenCV】访问图像中每个像素的值
http://blog.csdn.net/xiaowei_cqu/article/details/7557063
- 图像储存容器Mat[OpenCV 笔记11]
IplImage 与 Mat IplImage是OpenCV1中的图像存储结构体,基于C接口创建.在退出之前必须release,否则就会造成内存泄露.在一些只能使用C语言的嵌入式系统中,不得不使用. ...
- 图像载入 imread()[OpenCV 笔记4]
Mat imread( ); filename 载入的图像名: flags 指定加载图像的颜色类型,默认载入三通道彩色图像, 如果取枚举类型 (OpenCV3中暂时失效),则定义如下 enum{ CV ...
- 实例:图像载入、显示、混合与输出[OpenCV 笔记8]
是的是的,忍着尿意努力更新,就是为了更到wuli男神的部分,当然要把男神放在前面镇楼,欢迎下载配图,具体操作见code wuliEddie.jpg logo.png results.jpg LoadS ...
随机推荐
- 二、JSP的3个编译指令,7个动作指令,9个内置对象
JSP 3个编译指令 1) page指令(基本不需要用到,使用默认即可) 主要属性: 1.Language:指定脚本所采用的语言类型,现在只支持java 2.Extends:定义当前jsp产生的se ...
- 【转】二叉树 VS hashtable
hash_table和二叉搜索树都经常被用来构建符号表(或者字典)以及相关的结构,并且他们都表现出了很高的效率.最近也在不同的程序中使用了这两种数据结构,实现完毕后思考一下,对两者做了一个简单的比较: ...
- UART与USART的差别
UART与USART都是单片机上的串口通信,他们之间的差别例如以下: 首先从名字上看: UART:universal asynchronous receiver and transmitter通用异步 ...
- 【50】了解new和delete的合理替换时机
1.有时候,我们替换掉编译器提供的new或者delete.首先思考,为什么想要替换?下面是三个常见理由: a.用来检测运用上的错误,超额分配一些内存,再额外的空间放置一些内存: b.为了强化效能,编译 ...
- [React] Set up React apps with zero configuration
The React team has an official Command Line Interface (CLI) for building React projects called " ...
- linux上安装ftp
1.安装 rpm -ivh vsftpd-2.2.2-11.el6_4.1.x86_64.rpm 2.启动 service vsftpd start 3.连接 windows 命令行输入 ftp ww ...
- 深入理解Binder(二),Binder是什么?
上篇文章深入理解Binder(一),从AIDL谈起我们介绍了AIDL的基本使用,用AIDL两个App的通信是实现了,可是又有小伙伴疑惑了,为什么使用AIDL就能够实现两个App之间的通信?本文我们就来 ...
- Linux下编译安装redis,详细教程
话不多说,直接开工 准备工作: 本人测试环境:Win10 虚拟机:VM Linux:CentOS5.5 (已搭建好LNMP环境) 软件包:redis-2.6.14.tar.gz (Linux下redi ...
- 深入理解计算机系统第二版习题解答CSAPP 2.13
从20世纪70年代末到80年代末,Digital Equipment的VAX计算机是一种非常流行的机型.它没有布尔运算AND和OR指令,只有bis(位设置)和bic(位清除)这两种指令.两种指令的输入 ...
- VS版本下载
tfs2012:BVGTF-T7MVR-TP46H-9Q97G-XBXRB http://www.microsoft.com/zh-cn/download/details.aspx?id=30658 ...