访问图像中的像素[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 ...
随机推荐
- VB操作Excel
在工程中添加引用:Microsoft Office 9.0 Object Library Microsoft Excel 9.0 Object Library ...
- EF如何正确的进行实体中修改
本文转载:http://www.cnblogs.com/Ruiky/archive/2012/12/29/2839011.html 不推荐方式一: 思路:先从ObjectContext取出实体,然后将 ...
- C++容器类的简介
C++容器类的简介 一.原型与构造函数 Vector的原型可定义为 vector<T, allocator <T> > 其构造函数为 vector() ...
- setsockopt()使用方法(參数具体说明)
int setsockopt(SOCKET s,int level,int optname,const char* optval,int optlen); s(套接字): 指向一个打开的套接口描写叙述 ...
- 从零开始学android开发-项目debug
在红框处能看到变量值
- yum -------包安装库
elrepo: http://elrepo.org/tiki/tiki-index.php CentOSPlus: http://wiki.centos.org/zh/AdditionalR ...
- 简洁判断一个byte中有多少位为1的bit?
以下是Brian W. Kernighan公开的一个方法 unsigned bit_count(unsigned v) { unsigned int c; //置位总数累计 ; v; c++) { v ...
- 【转】ubuntu修改IP地址和网关的方法
一.使用命令设置Ubuntu IP地址 1.修改配置文件blacklist.conf禁用IPV6 sudo vi /etc/modprobe.d/blacklist.conf 表示用vi编辑器(也可以 ...
- uiautomator日志文件转换为xml格式文件
如果想把uiautomator的日志文件,转换成漂亮的xml文件,那么可以使用automator-log-converter.jar工具, 工具使用方法: 使用工具automator-log-conv ...
- oracle中decode()函数
简单写写,后续继续补充