学习OpenCV范例(五)——改变图像的对比度和亮度

来源:互联网 发布:美微柠檬免费网络电视 编辑:程序博客网 时间:2024/05/23 20:51

学习到范例五的时候,发觉虽然范例都很简单,但是做记录的时候,并且把程序里面使用过的类或方法都弄明白,也就不简单了,接下来介绍一下范例五吧。

1、图像处理

一般来说,图像处理算子是带有一幅或多幅输入图像、产生一幅输出图像的函数。

图像变换可分为以下两种:

点算子(像素变换):图像对比度和亮度,等等

邻域(基于区域的)算子:均值滤波,中值滤波,等等,也就是卷积运算

2、亮度和对比度调整

两种常用的点过程(即点算子),是用常数对点进行 乘法 和 加法 运算:

                                                                                                                      g(x) = \alpha f(x) + \beta

两个参数 \alpha > 0 和 \beta 一般称作 增益 和 偏置 参数。我们往往用这两个参数来分别控制 对比度 和 亮度 。

你可以把 f(x) 看成源图像像素,把 g(x) 看成输出图像像素。这样一来,上面的式子就能写得更清楚些:

                                                                                                                  g(i,j) = \alpha \cdot f(i,j) + \beta

其中, i 和 j 表示像素位于 第i行 和 第j列 。

3、运行代码如下:

程序使用三种方式来实现亮度和对比度的调整,并且输出了各自运算的时间。

#include "stdafx.h"#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <iostream>using namespace std;using namespace cv;double alpha; /**< 控制对比度 */int beta;  /**< 控制亮度 */int main( int argc, char** argv ){double t;/// 读入用户提供的图像Mat image = imread( "Lena.jpg" );Mat new_image = Mat::zeros( image.size(), image.type() );Mat new_image1 = Mat::zeros( image.size(), image.type() );Mat new_image2 = Mat::zeros( image.size(), image.type() );/// 初始化cout << " Basic Linear Transforms " << endl;cout << "-------------------------" << endl;cout << "* Enter the alpha value [1.0-3.0]: ";cin >> alpha;cout << "* Enter the beta value [0-100]: ";cin >> beta;    t = (double)getTickCount();/// 执行运算 new_image(i,j) = alpha*image(i,j) + betafor( 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 );}}}t = 1000*((double)getTickCount() - t)/getTickFrequency();cout << ".at+[] Times passed in milliseconds: " << t << endl;    t = (double)getTickCount();int nr= image.rows; // number of rows  int nc= image.cols * image.channels(); // total number of elements per line  for (int y=0; y<nr; y++) {  uchar* data= image.ptr<uchar>(y);  uchar* data1=new_image1.ptr<uchar>(y);for (int x=0; x<nc; x++) {  data1[x]=saturate_cast<uchar>(alpha*data[x]+beta);}}t = 1000*((double)getTickCount() - t)/getTickFrequency();cout << ".ptr+[] Times passed in milliseconds: " << t << endl;t = (double)getTickCount();image.convertTo(new_image2, -1, alpha, beta);t = 1000*((double)getTickCount() - t)/getTickFrequency();cout << "convertTo Times passed in milliseconds: " << t << endl;/// 创建窗口namedWindow("Original Image", 1);namedWindow("New Image", 1);namedWindow("New Image1", 1);namedWindow("New Image2", 1);/// 显示图像imshow("Original Image", image);imshow("New Image", new_image);imshow("New Image1", new_image1);imshow("New Image2", new_image2);/// 等待用户按键waitKey();return 0;}

4、运行结果:

  

           图1、原图                       图2、.at方法

 

          图3、.ptr方法                    图4、convertTo方法


                            图5、运行时间

5、结论

从运行时间可以看出,使用OpenCV自带的函数运行效率最高,而使用.ptr方法比.at方法好,这也印证了前面博客学习OpenCV范例(二)——OpenCV如何扫描图像、利用查找表和计时所说的。

6、用到的类

convertTo:

功能:通过缩放比例将数组变换成其他类型

结构:

void Mat::convertTo(OutputArray m, int rtype, double alpha=1, double beta=0 ) const
m:输出图像

rtype:输出图像的类型

alpha:比例因子α,决定对比度

beta:附加值β,决定亮度

函数原理如下:

                  m(x,y) = saturate \_ cast<rType>( \alpha (*this)(x,y) +  \beta )

saturate_cast:

功能:防止数据溢出

为什么上面的函数会用到saturate_cast呢,因为无论是加是减,乘除,都会超出一个像素灰度值的范围(0~255)所以,所以当运算完之后,结果为负,则转为0,结果超出255,则为255。


1 0
原创粉丝点击