访问图像中的像素[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 ...
随机推荐
- MySQL的安装——源码方式(实验环境下测试用,真实环境请忽略此文)
#虚拟机是最初的的系统,我们在虚拟机里安装scp [root@serv01 ~]# yum install /usr/bin/scp -y #安装过程略 #我们拷贝MySQL的源码包到目标机的/roo ...
- MyEclipse与Mysql数据库的连接
1.载入MySql驱动程序 Class.forName("com.mysql.jdbc.Driver"); // 载入MySql驱动程序 2.建立Connection连接对象 ...
- android驱动[置顶] 我的DIY Android之旅--驱动并控制你的Android开发板蜂鸣器
改章节个人在深圳游玩的时候突然想到的...这几周就有想写几篇关于android驱动的博客,所以回家到之后就奋笔疾书的写出来发布了 这些天一直在想Android驱动框架层的实现,本文借助老罗教师的博客和 ...
- Windows Phone-框架结构和启动过程
上一篇文章介绍了Windows Phone的开发环境和一个简单的Windows Phone程序的演示和结构,这一篇文章要深入一点,介绍Windows Phone的框架结构和程序启动的过程. 一 Win ...
- BZOJ 1878: [SDOI2009]HH的项链 离线树状数组
1878: [SDOI2009]HH的项链 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- [AngularJS + cryptoJS + Gravatar] Provider vs factory
Configurable Bits Need a Provider We want to be able to configure the characterLength before Tweetab ...
- [cocos2dx笔记004] android添加�静态库project
(基于2.2.2版本号) 这步比較麻烦,不像vs2013那样好设置.參考了非常多文章.还是不能解决这个问题.仅仅有慢慢摸索了.在这里贴出来,希望能让大家能少走点弯路. 还是其于前面的文章提到的myli ...
- C 栈顺序存储
// seqstack.h #ifndef _MY_SEQSTACK_H_ #define _MY_SEQSTACK_H_ typedef void SeqStack; SeqStack* SeqSt ...
- 面试题总结之Database
SQL 1. 现有一张学生表,有只有一个列是名字,请选出其中的重名的学生的名字select name from student group by name having count(*) > 1 ...
- 五、Socket之UDP异步传输文件-实现传输中取消传送
上一篇文章四.Socket之UDP异步传输文件中,只实现了传输开始前拒绝接收文件,没有实现文件传输进行的时候取消传送,这篇文章中我们就来介绍怎样实现这个功能. 在传输过程中取消文件的传送,有很多地方要 ...