OpenCV_tutorials 05 core module-Changing the contrast and brightness of an image

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	//载入源图像,彩色图
	cv::Mat src = cv::imread("C:\\Users\\dell\\Desktop\\xin1.jpg", IMREAD_COLOR);

	//检查源图像的有效性
	if (src.empty() || src.channels() != 3)
	{
		cout << "source image load failed!" << endl;
		return -1;
	}

	//用户指定变量alpha和beta的值
	float alpha = 0.0f;
	int beta = 0;
	cout << "please input alpah(1.0 - 3.0) and beta(0 - 100): " << endl;
	cin >> alpha;
	cin >> beta;

	//初始化目标图像
	cv::Mat dst = cv::Mat::zeros(src.size(), src.type());

	//对每个像素值进行变化 Dst(i,j) = Src(i,j)*alpha + beta
	for (int j = 0; j < src.rows; j++)
	{
		for (int i = 0; i < src.cols; i++)
		{
			for (int c = 0; c < 3; c++)
			{
				dst.at<Vec3b>(j, i)[c] = saturate_cast<uchar>((src.at<Vec3b>(j, i))[c] * alpha + beta);
			}
		}
	}
	
	cv::imshow("src", src);
	cv::imshow("dst", dst);

	cv::waitKey(0);

	return 0;
}

输入alpha = 1.5  beta = 30 ,因此变换公式为Dst(i,j) = alpha * Src(i,j) + beta = 1.5 * Src(i,j) + 30

源图像

目标图像

来验证一下是否按照公式Dst(i,j) = alpha * Src(i,j) + beta = 1.5 * Src(i,j) + 30变换的??

源图像中(0,0)处B | G | R = 161 | 198 | 96

按照公式计算目标图像(0,0)处:

Dst(0,0)[B] = 161 * 1.5 + 30 = 271.5

Dst(0,0)[G] = 198 * 1.5 + 30 = 327

Dst(0,0)[R] = 96 * 1.5 + 30 = 174

注意,程序中用了saturate_cast<uchar>限制了像素值的范围为0-255.因此 Dst(0,0)[B] = 255, Dst(0,0)[G] = 255, Dst(0,0)[R] = 174.

看一下目标图像中是否如此??

目标图像中像素值确实如公式计算那样。(#^.^#)

官方教程提到可以利用函数convertTo快速完成上述功能。下面研究一下convertTo函数。

先看一下函数说明:

再看一下函数声明:

    //! converts matrix to another datatype with optional scalng. See cvConvertScale.
    void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;


    /*!
      \param rtype The output matrix data type. When it is =-1, the output array will have the same data type as (*this)
      \param alpha The scale factor
      \param beta The optional delta added to the scaled values before the conversion
    */
    void convertTo( Mat& m, int rtype, double alpha=1, double beta=0 ) const;

下面用convertTo函数实现对比度和亮度调整功能:

#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	//载入源图像,彩色图
	cv::Mat src = cv::imread("C:\\Users\\dell\\Desktop\\xin1.jpg", IMREAD_COLOR);

	//检查源图像的有效性
	if (src.empty() || src.channels() != 3)
	{
		cout << "source image load failed!" << endl;
		return -1;
	}

	cv::imshow("src", src);

	//用户指定变量alpha和beta的值
	float alpha = 0.0f;
	int beta = 0;
	cout << "please input alpah(1.0 - 3.0) and beta(0 - 100): " << endl;
	cin >> alpha;
	cin >> beta;

	//初始化目标图像
	cv::Mat dst1 = cv::Mat::zeros(src.size(), src.type());
	cv::Mat dst2 = cv::Mat::zeros(src.size(), src.type());

	//方法一
	//对每个像素值进行变化 Dst(i,j) = Src(i,j)*alpha + beta
	double tc1 = (double)getTickCount();
	for (int j = 0; j < src.rows; j++)
	{
		for (int i = 0; i < src.cols; i++)
		{
			for (int c = 0; c < 3; c++)
			{
				dst1.at<Vec3b>(j, i)[c] = saturate_cast<uchar>((src.at<Vec3b>(j, i))[c] * alpha + beta);
			}
		}
	}
	double t1 = ((double)getTickCount() - tc1) / getTickFrequency();
	cout << "method1 cost time : " << t1 << endl;
	cv::imshow("dst1", dst1);


	//方法二
	//利用函数convertTo()
	double tc2 = (double)getTickCount();
	src.convertTo(dst2, -1, alpha, beta);
	double t2 = ((double)getTickCount() - tc2) / getTickFrequency();
	cout << "method2 cost time : " << t2 << endl;
	cv::imshow("dst2", dst2);

	cv::waitKey(0);

	return 0;
}

可以看出,利用函数convertTo确实比对单个像素进行变换速度更快。

最后,关于saturate_cast防止数据溢出,以后经常会用到,本文涉及的知识用到的相关的是:

template<> inline uchar saturate_cast<uchar>(int v)
{ return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0); }

template<> inline uchar saturate_cast<uchar>(float v)
{ int iv = cvRound(v); return saturate_cast<uchar>(iv); }

template<> inline uchar saturate_cast<uchar>(double v)
{ int iv = cvRound(v); return saturate_cast<uchar>(iv); }

可以看到,对于float和double类型,先是利用cvRound转换为int型,然后对于int型,利用选择运算符将像素值限定在0和UCHAR_MAX之间。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值