OpenCV2马拉松第3圈——改变对比度和亮度
来源:互联网 发布:网络草花机 编辑:程序博客网 时间:2024/05/18 01:46
收入囊中
- 访问每个像素点
- 了解saturate_cast如何防溢出
- 初步懂得像素变换
在这之前先介绍点数据结构和方法。
首先是定义在core.hpp中的
typedef Vec<uchar, 2> Vec2b;typedef Vec<uchar, 3> Vec3b;typedef Vec<uchar, 4> Vec4b;typedef Vec<short, 2> Vec2s;typedef Vec<short, 3> Vec3s;typedef Vec<short, 4> Vec4s;typedef Vec<ushort, 2> Vec2w;typedef Vec<ushort, 3> Vec3w;typedef Vec<ushort, 4> Vec4w; typedef Vec<int, 2> Vec2i;typedef Vec<int, 3> Vec3i;typedef Vec<int, 4> Vec4i;typedef Vec<int, 6> Vec6i;typedef Vec<int, 8> Vec8i;typedef Vec<float, 2> Vec2f;typedef Vec<float, 3> Vec3f;typedef Vec<float, 4> Vec4f;typedef Vec<float, 6> Vec6f;typedef Vec<double, 2> Vec2d;typedef Vec<double, 3> Vec3d;typedef Vec<double, 4> Vec4d;typedef Vec<double, 6> Vec6d;Vec类就先不要管了,这是个模板类,特别要关注这里的Vec3b,为什么呢,因为他特别适合放三通道RGB,每一个都是uchar,也就是0-255
下面我们来看Mat.hpp文件
有个很重要的方法叫at
- C++: template<typename T> T& Mat::at(int i) const
- C++: template<typename T> const T& Mat::at(int i) const
- C++: template<typename T> T& Mat::at(int i, int j)
- C++: template<typename T> const T& Mat::at(int i, int j) const
- C++: template<typename T> T& Mat::at(Point pt)
- C++: template<typename T> const T& Mat::at(Point pt) const
- C++: template<typename T> T& Mat::at(int i, int j, int k)
- C++: template<typename T> const T& Mat::at(int i, int j, int k) const
- C++: template<typename T> T& Mat::at(const int* idx)
- C++: template<typename T> const T& Mat::at(const int* idx) const
Parameters: - i – Index along the dimension 0
- j – Index along the dimension 1
- k – Index along the dimension 2
- pt – Element position specified as Point(j,i) .
- idx – Array of Mat::dims indices.
template<typename _Tp> inline _Tp& Mat::at(int i0, int i1){ CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); return ((_Tp*)(data + step.p[0]*i0))[i1];}image.at<Vec3b>(y,x)[0] 就可以访问y行x列的red值
image.at<Vec3b>(y,x)[1] 就可以访问y行x列的green值
image.at<Vec3b>(y,x)[2] 就可以访问y行x列的blue值
另外Mat还有类似MATLAB和Octave的初始化方法
Use MATLAB-style array initializers, zeros(), ones(), eye(), for example:
- 下面要用到zeros,就介绍下zeros的接口
- C++: static MatExpr Mat::zeros(int rows, int cols, int type)
- C++: static MatExpr Mat::zeros(Size size, int type)
- C++: static MatExpr Mat::zeros(int ndims, const int* sz, int type)¶
Parameters: - ndims – Array dimensionality.
- rows – Number of rows.
- cols – Number of columns.
- size – Alternative to the matrix size specification Size(cols, rows) .
- sz – Array of integers specifying the array shape.
- type – Created matrix type.
The method returns a Matlab-style zero array initializer. It can be used to quickly form a constant array as a function parameter, part of a matrix expression, or as a matrix initializer.
比如我要用第二种方法,就可以这样来写
Mat image = imread( argv[1] );Mat new_image = Mat::zeros( image.size(), image.type() );
另外一个很有用的模板函数是saturate_cast,可以有效防止溢出
uchar a = saturate_cast<uchar>(-100); // a = 0 (UCHAR_MIN)short b = saturate_cast<short>(33333.33333); // b = 32767 (SHORT_MAX)
下面,我们就可以来看这个代码了#include "opencv2/highgui/highgui.hpp"
#include <iostream>using namespace cv;double alpha; /**< Simple contrast control */int beta; /**< Simple brightness control */int main( int, char** argv ){ /// Read image given by user Mat image = imread( argv[1] ); Mat new_image = Mat::zeros( image.size(), image.type() ); std::cout<<" Basic Linear Transforms "<<std::endl; std::cout<<"-------------------------"<<std::endl; std::cout<<"* Enter the alpha value [1.0-3.0]: ";std::cin>>alpha; std::cout<<"* Enter the beta value [0-100]: "; std::cin>>beta; /// Do the operation new_image(i,j) = alpha*image(i,j) + beta /// Instead of these 'for' loops we could have used simply: /// image.convertTo(new_image, -1, alpha, beta); /// but we wanted to show you how to access the pixels :) for( int y = 0; y < image.rows; y++ ) { for( int x = 0; x < image.cols; x++ ) { for( int c = 0; c < 3; c++ ) { new_image.at<Vec3b>(y,x)[c] = saturate_cast<uchar>( alpha*( image.at<Vec3b>(y,x)[c] ) + beta ); } } } namedWindow("Original Image", 1); namedWindow("New Image", 1); imshow("Original Image", image); imshow("New Image", new_image); waitKey(); return 0;}有了上面的知识打底,是不是感觉一下子就看懂了~~
如同注释说的,我们有函数可以直接达到目的,不需要我们去遍历。
C++: void Mat::convertTo(OutputArray m, int rtype, double alpha=1, double beta=0 ) const
这儿的const就是说这个函数操作不会对变量或是对象之类的值有影响
rtype为-1表示input和output的类型一致,非常方便。
变换公式:
下面是一个有控制条的对比度变换
#include "opencv2/highgui/highgui.hpp"#include <iostream>using namespace cv;int alpha = 50;Mat image,new_image;static void change_color(int, void*){for( int y = 0; y < image.rows; y++ )for( int x = 0; x < image.cols; x++ )for( int c = 0; c < 3; c++ ) new_image.at<Vec3b>(y,x)[c] = saturate_cast<uchar>( alpha/50.0 *( image.at<Vec3b>(y,x)[c] )); imshow("Image", new_image);}int main( int, char** argv ){ image = imread( argv[1] ); new_image = Mat::zeros( image.size(), image.type() ); namedWindow("Image", 1);createTrackbar( "pick:", "Image", &alpha, 100, change_color);change_color(0, 0);waitKey();return 0;}关于控制条,你可以暂时不管(其实非常简单),相信你能非常容易看懂
举一反三
公式:
Computer Vision: Algorithms and Applications 有介绍
alpha可以认为是控制contrast,beta控制brightness,alpha和beta也可以是空间的函数而不是固定的,我在image processing也讲过
- OpenCV2马拉松第3圈——改变对比度和亮度
- OpenCV2马拉松第9圈——再谈对比度(对比度拉伸,直方图均衡化)
- OpenCV2马拉松第4圈——图片混合
- OpenCV2马拉松第1圈——纵观全局
- OpenCV2马拉松第2圈——读写图片
- OpenCV2马拉松第5圈——线性滤波
- OpenCV2马拉松第6圈——非线性滤波
- OpenCV2马拉松第7圈——图像金字塔
- OpenCV2马拉松第8圈——绘制直方图
- OpenCV2马拉松第12圈——直方图比较
- OpenCV2马拉松第13圈——模版匹配
- openCV2马拉松第18圈——坐标变换
- OpenCV2马拉松第24圈——轮廓提取
- OpenCV2马拉松第10圈——直方图反向投影(back project)
- OpenCV2马拉松第11圈——meanshift与直方图反向投影
- OpenCV2马拉松第14圈——边缘检测(Sobel,prewitt,roberts)
- OpenCV2马拉松第15圈——边缘检测(Laplace算子,LOG算子)
- OpenCV2马拉松第16圈——边缘检测(形态学梯度)
- 【PyQt实例6】渐变效果
- iOS 沙盒 理解 文件系统
- AS3.0 Bitmap类实现图片3D旋转效果
- 用cmd来运行java
- 汉字的编码与字模点阵小结
- OpenCV2马拉松第3圈——改变对比度和亮度
- MVC 帮助类/公共方法
- 在Jenkins 运行 cucumber(ruby+watir)
- java--多线程通信
- SQL Server 2012 Evaluation下载和安装小问题
- 刘恺威透露杨幂怀孕6个月 已留港待产
- 网页数据采集:[3]python如何利用抓包数据
- IE bug集锦
- 08 交通灯管理系统