【opencv/core module】(六)Changing the contrast and brightness of an image!

说在前面

Theory

  • Image Process(图像处理)

    • 将一张或多张图像作为输入,输出另外一张图像 (广义的定义?)
    • 图像变换包括两种:
      • 点的操作(pixel transform) [Point operators (pixel transforms)]
      • 区域的操作 [Neighborhood (area-based) operators]
  • Pixels Transform(像素变换)

    • 每个输出像素的值只取决于相关输入像素点的值(可能也会有其他全局信息或者参数)
  • Brightness and contrast adjustments(亮度&对比度调整)

    • 公式 g ( x ) = α f ( x ) + β g(x) = \alpha f(x) + \beta g(x)=αf(x)+β
      f ( x ) f(x) f(x)作为输入图像的像素点, g ( x ) g(x) g(x)作为输出图像的像素点,那么有
      g ( i , j ) = α ⋅ f ( i , j ) + β g(i,j) = \alpha \cdot f(i,j) + \beta g(i,j)=αf(i,j)+β
      f ( i , j ) f(i,j) f(i,j)为输入图像第 i i i 行第 j j j 列的像素点, g ( i , j ) g(i,j) g(i,j)同理。
    • 参数 α > 0 \alpha > 0 α>0 称为增益(gain)参数,用来控制对比度;参数 β \beta β 称为偏置(bias)参数,用来控制亮度。解释一下控制的原理,假设一张 灰度图(单通道) 某部分的像素值如下:
      20 50 20 10 60 10 0 10 10 \begin{matrix} 20 & 50 & 20 \\ 10 & 60 & 10 \\ 0 & 10 & 10 \\ \end{matrix} 20100506010201010
      假设 α = 2 \alpha=2 α=2 β = 0 \beta=0 β=0,那么上述像素值变为如下:
      40 100 40 20 120 20 0 20 20 \begin{matrix} 40 & 100 & 40 \\ 20 & 120 & 20 \\ 0 & 20 & 20 \\ \end{matrix} 4020010012020402020
      可以看到,像素之间的差异变大,(比如60-50=10,120-100=20),也就表现出对比度增大
      对于亮度,同样我们来考虑灰度图(单通道),像素值0是黑色、255是白色,当 β \beta β越来越大,像素值就越接近255,也就越白,表现出来就是亮度提高
      多通道同理。

Code

#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

// we're NOT "using namespace std;" here, 
//to avoid collisions between the beta variable and std::beta in c++17
using std::cin;
using std::cout;
using std::endl;
using namespace cv;

int alpha;
int beta;
Mat image;

void on_trackbar(int, void*)
{
	double alpha_t = alpha / 100.0;
	Mat new_image = Mat::zeros(image.size(), image.type());
	for (int y = 0; y < image.rows; y++) {
		for (int x = 0; x < image.cols; x++) {
			for (int c = 0; c < image.channels(); c++) {
				new_image.at<Vec3b>(y, x)[c] =
					saturate_cast<uchar>(alpha_t*image.at<Vec3b>(y, x)[c] + beta);
			}
		}
	}

	//或者使用opencv提供的方法
	//image.convertTo(new_image, -1, alpha_t, beta);

	imshow("Original Image", image);
	imshow("bright&contrast", new_image);
}

int main()
{
	
	image = imread("lena.jpg");
	if (image.empty())
	{
		cout << "Could not open or find the image!\n" << endl;
		return -1;
	}

	alpha = 100; /*< Simple contrast control */
	beta = 0;       /*< Simple brightness control */

	namedWindow("bright&contrast");

	createTrackbar("contrast:", "bright&contrast", &alpha, 300, on_trackbar);
	createTrackbar("bright:  ", "bright&contrast", &beta, 100, on_trackbar);
	
	on_trackbar(alpha, 0);
	on_trackbar(beta, 0);

	while (char(waitKey(1)) != 'q') { }

	return 0;
}
  • 这部分应该好理解,对每个像素每个通道应用一遍上面那个公式:
for (int y = 0; y < image.rows; y++) {
		for (int x = 0; x < image.cols; x++) {
			for (int c = 0; c < image.channels(); c++) {
				new_image.at<Vec3b>(y, x)[c] =
					saturate_cast<uchar>(alpha_t*image.at<Vec3b>(y, x)[c] + beta);
					//saturate_cast,这个讲过,防止值溢出
					//at<Vec3b>也讲过
			}
		}
	}
  • 然后就是这部分,创建一个滑动条(createTrackBar)
namedWindow("bright&contrast");

//在窗口“bright&contrast”上创建一个名叫“contrast”的滑动条;
//滑动条改变的值是全局变量alpha,改变的最大值是300,在每次值改变后调用函数on_trackbar
createTrackbar("contrast:", "bright&contrast", &alpha, 300, on_trackbar);

createTrackbar("bright:  ", "bright&contrast", &beta, 100, on_trackbar);

Result

在这里插入图片描述

Practical example(重点)

  • 引出问题

    • 在上述调整对比度与亮度的方法中,我们使用了 saturate_cast 来防止值溢出,但是,这种方式可能会导致:
    • 在调整亮度降低图像的对比度
      这里我的理解是这样的,以下面这部分原始像素为例
      200 250 200 200 250 200 200 200 200 \begin{matrix} 200 &amp; 250 &amp; 200 \\ 200 &amp; 250 &amp; 200 \\ 200 &amp; 200 &amp; 200 \\ \end{matrix} 200200200250250200200200200
      α = 1 , β = 50 \alpha=1,\beta=50 α=1,β=50,那么就有
      250 255 250 250 255 250 250 250 250 \begin{matrix} 250 &amp; 255 &amp; 250 \\ 250 &amp; 255 &amp; 250 \\ 250 &amp; 250 &amp; 250 \\ \end{matrix} 250250250255255250250250250
      可以看到,像素之间的差异变小,也就是对比度降低
    • 在调整对比度的时候使图片在原本就很亮的地方失去一些细节
      我们同样以上面那部分像素为例:
      200 250 200 200 250 200 200 200 200 \begin{matrix} 200 &amp; 250 &amp; 200 \\ 200 &amp; 250 &amp; 200 \\ 200 &amp; 200 &amp; 200 \\ \end{matrix} 200200200250250200200200200
      α = 1.2 , β = 0 \alpha=1.2,\beta=0 α=1.2,β=0,那么就有
      255 255 255 255 255 255 255 255 255 \begin{matrix} 255 &amp; 255 &amp; 255 \\ 255 &amp; 255 &amp; 255 \\ 255 &amp; 255 &amp; 255 \\ \end{matrix} 255255255255255255255255255
      全是255,很明显,原来的细节没有了。(ง •_•)ง
  • Gamma correction

    • theory
      用于亮度调整,使用非线性变换(之前用的是线性变换)
      O = ( I 255 ) γ × 255 O = \left( \frac{I}{255} \right)^{\gamma} \times 255 O=(255I)γ×255
      I I I为输入图像(或者像素值), O O O为输出图像(或者像素值)
      γ &lt; 1 \gamma&lt;1 γ<1时,亮度提高;当 γ &gt; 1 \gamma&gt;1 γ>1时,亮度降低。
      偷一张官方图
      在这里插入图片描述

    • code
      使用了LUT,之前有讲过

      image = imread("gamma.jpg");
      if (image.empty())
      {
      	cout << "Could not open or find the image!\n" << endl;
      	return -1;
      }
      
      Mat lookUpTable(1, 256, CV_8U);
      uchar* p = lookUpTable.ptr();
      for (int i = 0; i < 256; ++i)
      	p[i] = saturate_cast<uchar>(pow(i / 255.0, 0.4) * 255.0);
      
      Mat res = image.clone();
      LUT(image, lookUpTable, res);
      
      imshow("source", image);
      imshow("gamma", res);
      
      waitKey();
      
    • result
      这里使用的测试图片也是官方文档里那张,没找到合适的
      在这里插入图片描述

    • 找到张好点的图
      在这里插入图片描述
      在这里插入图片描述
      上面的是gamma校正,下面直接调亮度,可以看框起来的区域的对比。


END-(CSDN)2019.6.29
(。・∀・)ノ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值