opencv2操作像素的几种方法
来源:互联网 发布:手机淘宝突然打不开了 编辑:程序博客网 时间:2024/05/18 20:50
opencv2 是C++接口,这就让我有了顺便复习C++的机会啊。好吧,一切重头开始来过吧。
opencv所有的操作都是从操作图像开始的,所以就要从图像的组成元素之图像像素说起啦。所以就开始介绍几种处理像素的方法:
1,at
直接访问图像位置的像素 例子就是使用at直接给图像位置(j,i)的像素赋值255,结果就是图像上分布了椒盐噪声。后面会讲到哪种方法处理椒盐噪声效果好了。
#include <opencv2/opencv.hpp>using namespace cv;class class_ch2{private:Mat src;Mat result;public:class_ch2(const Mat& img):src(img),result(img){assert(img.size>0);assert(src.size>0);assert(result.size>0);}void salt_proc(int n){for (int k=0;k<n;k++){int i = rand()%src.cols;int j = rand()%src.rows;if (src.channels() == 1){result.at<uchar>(j,i) = 255;} else{result.at<Vec3b>(j,i)[0] = 255;result.at<Vec3b>(j,i)[1] = 255;result.at<Vec3b>(j,i)[2] = 255;}}}Mat get_result(){return result;}};int main(){Mat src = imread("bridgit.jpg");imshow("src",src);class_ch2 cla_ch2(src);cla_ch2.salt_proc(3000);imshow("result",cla_ch2.get_result());waitKey(0);}
注意哦!!!!!!!!!!!!!!!!!
如果事先知道了图像类型,那么就可以使用
Mat_<uchar> src2 = src;
src2(20,20) = 255; 而不用 img.at<uchar>(j,i) = 255; 简洁了许多,但是很多时候我们不确定我们使用的图像在处理过程中是否会改变类型,所以就先用Mat了,如果已经确定了处理图像的类型,那么请不要介意,尽情的使用Mat_吧!!!
2,指针
在C版本的opencv中,貌似都是指针,因为直接定义就是iplimage* img = 。。。。。所以大部分都是使用指针呢,所以指针并不陌生哦,只是在C++版本中多了类型控制,现在这个例子就是指针处理图像,让图像颜色级数降低为原级数的pow(2,n)分之一;
void colorReduce(const int& n){//div_num = pow(2,n);src.copyTo(result);uchar mask = 0xFF<<n;int height = result.rows;int width = result.cols*result.channels();for (int j= 0;j<height;j++){uchar *pt_data = result.ptr<uchar>(j);for (int i=0;i<width;i++){pt_data[i] = (pt_data[i]&mask) + pow(2.0,n)/2;}}}
好像水彩画的赶脚啊。这个是n=5的效果。因为位运算的效率很高,所以优先使用位运算。
3,isContinuous 判断图像是否在行尾有填补
因为出于效率的考虑,图像的一行经常被填补为4或者8的倍数,利于运算,所以当图像没有被填补的时候,就可以被认为是一个大小为宽X高的一维数组。
void colorReduce(const int& n){//div_num = pow(2,n);src.copyTo(result);uchar mask = 0xFF<<n;int height = result.rows;int width = result.cols*result.channels();<span style="color:#3333ff;">if (result.isContinuous()){width = height * width;height = 1;}</span>for (int j= 0;j<height;j++){uchar *pt_data = result.ptr<uchar>(j);for (int i=0;i<width;i++){pt_data[i] = (pt_data[i]&mask) + pow(2.0,n)/2;}}}效果跟上面一样,就是效率的问题。对于连续图像来说很高效。
4,迭代器
既然是C++版本的,咋么能少了迭代器呢,模板都已经出现了的说。
void colorReduce_it(const int& n){src.copyTo(result);uchar mask = 0xFF<<n;Mat_<Vec3b>::iterator it = result.begin<Vec3b>();Mat_<Vec3b>::iterator end = result.end<Vec3b>();for (;it!=end;it++){(*it)[0] = ((*it)[0]&mask) + pow(2.0,n)/2;(*it)[1] = ((*it)[1]&mask) + pow(2.0,n)/2;(*it)[2] = ((*it)[2]&mask) + pow(2.0,n)/2;}}效果呢,就是跟上面一样,不过速度哦,就慢了。
如果之前对result是这样定义的话:
Mat_<Vec3b> result = src;那么两个迭代器的定义就是这样子的了。
<pre name="code" class="cpp">Mat_<Vec3b>::iterator it = result.begin();Mat_<Vec3b>::iterator end = result.end();
最后对这几个遍历方法做个总结对比:
最具效率的一种方法:
void colorReduce_fastest(int div = 32){src.copyTo(result);int height = result.rows;int width = result.cols;if (result.isContinuous()){width = height * width;height = 1;}int n = static_cast<int>(log(static_cast<double>(div))/log(2.0));uchar mask = 0xFF<<n;for (int j= 0;j<height;j++){uchar *pt_data = result.ptr<uchar>(j);for (int i=0;i<width;i++){*pt_data++ = (*pt_data&mask) + div/2;*pt_data++ = (*pt_data&mask) + div/2;*pt_data++ = (*pt_data&mask) + div/2;}}}
结果跟前面一样,但是速度是最快滴O(∩_∩)O哈哈~
像素的几种方法遍历方法就上面了哦。继续加油↖(^ω^)↗
- opencv2操作像素的几种方法
- opencv2 像素的基本操作
- OPENCV2 访问图像像素值的三种方法
- opencv2-遍历图像像素的14种方法
- OPENCV2 访问图像像素值的三种方法
- 操作像素------OpenCV2.4.11
- 几种常用的像素混合方法
- 几种常用的像素混合方法
- 几种常用的像素混合方法
- openCV2 第二讲 操作像素
- Opencv2 中 Mat 关于图像像素的操作
- opencv2.x中32位图像的像素级操作
- 来自一本国外OpenCV2书籍的示例-遍历图像像素的14种方法
- OpenCV2 访问各个像素点的方法(图像遍历)
- 制作1像素边框表格的几种方法
- Web前端绘制0.5像素的几种方法
- OpenCV像素点邻域遍历效率比较,以及访问像素点的几种方法
- OpenCV2 的像素值读写
- 博客迁移到reetsee.com
- VC++ (MFC)调用 C#生成DLL的两种方法
- navicat如何导入sql文件
- Svn 服务器配置(注意单一项目 多项目都可以)
- UEFI
- opencv2操作像素的几种方法
- C++ static、const和static const 以及它们的初始化
- Linux音频驱动之ASoC架构中的Platform
- C++比C的优势
- iOS 获取手机的型号,系统版本,软件名称,软件版本
- 单链表反序递归版本和迭代版本
- android asmack 注册 登陆 聊天 多人聊天室 文件传输
- zoj_2165
- 即使我有最新