Refs: https://docs.opencv.org/4.3.0/d3/dc1/tutorial_basic_linear_transform.html

目录

Goal

Brightness and contrast adjustments

Note

Notice the following (C++ code only):

C++

Python

Practical example

Additional resources


Goal

In this tutorial you will learn how to:

  • Access pixel values
  • Initialize a matrix with zeros
  • Learn what cv::saturate_cast does and why it is useful
  • Get some cool info about pixel transformations
  • Improve the brightness of an image on a practical example

Brightness and contrast adjustments

  • Two commonly used point processes are multiplication and addition with a constant:

    g(x)=αf(x)+β

  • The parameters α>0 and β are often called the gain and bias parameters; sometimes these parameters are said to control contrast and brightness respectively.
  • You can think of f(x) as the source image pixels and g(x) as the output image pixels. Then, more conveniently we can write the expression as:

    g(i,j)=α⋅f(i,j)+β

    where i and j indicates that the pixel is located in the i-th row and j-th column.

Note

Instead of using the for loops to access each pixel, we could have simply used this command:

image.convertTo(new_image, -1, alpha, beta);

where cv::Mat::convertTo would effectively perform *new_image = a*image + beta*. However, we wanted to show you how to access each pixel. In any case, both methods give the same result but convertTo is more optimized and works a lot faster.

to perform the operation g(i,j)=α⋅f(i,j)+β we will access to each pixel in image. Since we are operating with BGR images, we will have three values per pixel (B, G and R), so we will also access them separately. Here is the piece of code:

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*image.at<Vec3b>(y,x)[c] + beta );}}}

Notice the following (C++ code only):

  • To access each pixel in the images we are using this syntax: image.at<Vec3b>(y,x)[c] where y is the row, x is the column and c is B, G or R (0, 1 or 2).
  • Since the operation α⋅p(i,j)+β can give values out of range or not integers (if α is float), we use cv::saturate_cast to make sure the values are valid.

C++

#include <iostream>
#include <opencv.hpp>using namespace cv;// 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;namespace
{/** Global Variables */int alpha = 100;int beta = 100;int gamma_cor = 100;Mat img_original, img_corrected, img_gamma_corrected;void basicLinearTransform(const Mat &img, const double alpha_, const int beta_){Mat res;img.convertTo(res, -1, alpha_, beta_);hconcat(img, res, img_corrected);imshow("Brightness and contrast adjustments", img_corrected);}void gammaCorrection(const Mat &img, const double gamma_){CV_Assert(gamma_ >= 0);//! [changing-contrast-brightness-gamma-correction]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, gamma_) * 255.0);Mat res = img.clone();LUT(img, lookUpTable, res);//! [changing-contrast-brightness-gamma-correction]hconcat(img, res, img_gamma_corrected);imshow("Gamma correction", img_gamma_corrected);}void alpha_beta_value(const Mat &image, const double alpha_, const int beta_){//Mat new_image = Mat(img_original.rows, img_original.cols, img_original.type());Mat new_image = Mat(img_original.size(), img_original.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_*image.at<Vec3b>(y, x)[c] + beta_);}}}hconcat(image, new_image, img_corrected);imshow("Brightness and contrast adjustments", img_corrected);}void on_linear_transform_alpha_trackbar(int, void *){double alpha_value = alpha / 100.0;int beta_value = beta - 100;//basicLinearTransform(img_original, alpha_value, beta_value);alpha_beta_value(img_original, alpha_value, beta_value);}void on_linear_transform_beta_trackbar(int, void *){double alpha_value = alpha / 100.0;int beta_value = beta - 100;//basicLinearTransform(img_original, alpha_value, beta_value);alpha_beta_value(img_original, alpha_value, beta_value);}void on_gamma_correction_trackbar(int, void *){double gamma_value = gamma_cor / 100.0;gammaCorrection(img_original, gamma_value);}
}int main(int argc, char** argv)
{img_original = imread("Grass.jpg", IMREAD_COLOR);//Mat image_grass = imread("Grass.jpg", IMREAD_GRAYSCALE);if (img_original.empty()){printf("No data\n");return -1;}//pyrDown(img_original, img_original, Size(img_original.cols / 3, img_original.rows / 3));pyrDown(img_original, img_original);resize(img_original, img_original, Size(img_original.cols / 1.5, img_original.rows / 1.5), 0, 0, 0);img_corrected = Mat(img_original.rows, img_original.cols * 2, img_original.type());img_gamma_corrected = Mat(img_original.rows, img_original.cols * 2, img_original.type());hconcat(img_original, img_original, img_corrected);hconcat(img_original, img_original, img_gamma_corrected);// 类似于hconcat()水平连接两张图, 也会有垂直连接的函数//Mat img_vtest = Mat(img_original.rows * 2, img_original.cols, img_original.type());//vconcat(img_original, img_original, img_vtest);//imshow("image1", img_corrected);//imshow("image2", img_vtest);//waitKey();namedWindow("Brightness and contrast adjustments");namedWindow("Gamma correction");createTrackbar("Alpha gain (contrast)", "Brightness and contrast adjustments", &alpha, 500, on_linear_transform_alpha_trackbar);createTrackbar("Beta bias (brightness)", "Brightness and contrast adjustments", &beta, 200, on_linear_transform_beta_trackbar);createTrackbar("Gamma correction", "Gamma correction", &gamma_cor, 200, on_gamma_correction_trackbar);on_linear_transform_alpha_trackbar(0, 0);on_gamma_correction_trackbar(0, 0);waitKey();imwrite("linear_transform_correction.png", img_corrected);imwrite("gamma_correction.png", img_gamma_corrected);return 0;
}

Python

https://github.com/opencv/opencv/blob/master/samples/python/tutorial_code/imgProc/changing_contrast_brightness_image/BasicLinearTransforms.py

from __future__ import print_function
from builtins import input
import cv2 as cv
import numpy as np
import argparse# Read image given by user
## [basic-linear-transform-load]
parser = argparse.ArgumentParser(description='Code for Changing the contrast and brightness of an image! tutorial.')
parser.add_argument('--input', help='Path to input image.', default='lena.jpg')
args = parser.parse_args()image = cv.imread(cv.samples.findFile(args.input))
if image is None:print('Could not open or find the image: ', args.input)exit(0)
## [basic-linear-transform-load]## [basic-linear-transform-output]
new_image = np.zeros(image.shape, image.dtype)
## [basic-linear-transform-output]## [basic-linear-transform-parameters]
alpha = 1.0 # Simple contrast control
beta = 0    # Simple brightness control# Initialize values
print(' Basic Linear Transforms ')
print('-------------------------')
try:alpha = float(input('* Enter the alpha value [1.0-3.0]: '))beta = int(input('* Enter the beta value [0-100]: '))
except ValueError:print('Error, not a number')
## [basic-linear-transform-parameters]# Do the operation new_image(i,j) = alpha*image(i,j) + beta
# Instead of these 'for' loops we could have used simply:
# new_image = cv.convertScaleAbs(image, alpha=alpha, beta=beta)
# but we wanted to show you how to access the pixels :)
## [basic-linear-transform-operation]
for y in range(image.shape[0]):for x in range(image.shape[1]):for c in range(image.shape[2]):new_image[y,x,c] = np.clip(alpha*image[y,x,c] + beta, 0, 255)
## [basic-linear-transform-operation]## [basic-linear-transform-display]
# Show stuff
cv.imshow('Original Image', image)
cv.imshow('New Image', new_image)# Wait until user press some key
cv.waitKey()

Practical example

https://docs.opencv.org/4.3.0/d3/dc1/tutorial_basic_linear_transform.html

Additional resources

  • Gamma correction in graphics rendering

https://learnopengl.com/Advanced-Lighting/Gamma-Correction

Improving Opencv 6: The Core Functionality :Changing the contrast and brightness of an image!相关推荐

  1. opencv回顾之Core module

    该篇围绕Core Functionality模块进行展开 该模块的主要作用是成为构建opencv更多高级功能的基础核心层. Mat基础图像存储数据结构 将Mat对象赋值给其他Mat变量将会共享一个地址 ...

  2. 【opencv 官方教程】翻译2 核心功能 中 图像操作 线性变换 亮度调整 简单绘图

    核心功能 The Core Functionality (core module) Here you will learn the about the basic building blocks of ...

  3. OpenCV 之 Mat 类

    数字图像可看作一个数值矩阵, 其中的每个元素代表一个像素点,如下图所示: OpenCV 中,用 Mat 来表示该数值矩阵,它是很关键的一种数据结构,因为 OpenCV 中的大部分函数都和 Mat 有关 ...

  4. 【python】OpenCV—Brightness and Contrast adjustments

    英文原文: https://docs.opencv.org/master/d3/dc1/tutorial_basic_linear_transform.html 中文翻译: https://www.j ...

  5. opencv计算图像亮度调节_opencv调整图像亮度对比度

    图像处理 图像变换就是找到一个函数,把原始图像矩阵经过函数处理后,转换为目标图像矩阵. 可以分为两种方式,即像素级别的变换和区域级别的变换 Point operators (pixel transfo ...

  6. Opencv--Mat图像基本操作

    Opencv图像处理基本操作 1基本数据类型 图像有若干个通道,灰度图像只有一个通道,而彩色具有红,绿,蓝组成,但是OpenCv以逆序的方式来存储三个分量,还可以使用第四个透明度(alpha),可以使 ...

  7. (4)图像增强- Part1. 对比度增强

    Image Enhancement 导读: 本章主要总结了图像增强技术中的点处理技术,包括灰度直方图的获取.直方图均衡化.直方图规范化和对比度调整等内容.C++和Python语言环境下,使用OpenC ...

  8. 使用 OpenCV4 和 C++ 构建计算机视觉项目:1~5

    原文:Building Computer Vision Projects with OpenCV 4 and C++ 协议:CC BY-NC-SA 4.0 译者:飞龙 本文来自[ApacheCN 计算 ...

  9. OpenCV 1.x 2.x 编程简介(矩阵/图像/视频的基本读写操作)

    OpenCV 编程简介(矩阵/图像/视频的基本读写操作) Introduction to programming with OpenCV OpenCV编程简介 作者: Gady Agam Depart ...

  10. OpenCV 编程简单介绍(矩阵/图像/视频的基本读写操作)

    PS. 因为csdn博客文章长度有限制,本文有部分内容被截掉了. 在OpenCV中文站点的wiki上有可读性更好.而且是完整的版本号,欢迎浏览. OpenCV Wiki :<OpenCV 编程简 ...

最新文章

  1. 自学考试计算机实践课,自学考试的计算机实践课怎么考大神们帮帮忙
  2. css背景上能添加文字,CSS3怎么为文字添加背景?
  3. C++ STL 中提供的算法
  4. 数据结构之串:基本概念
  5. 探讨 | SpringBoot + MyBatis 多数据源事物问题
  6. 综合项目:Keepalived+Redis+Haproxy实现主从热备、负载均衡、秒级切换
  7. JDK1.8之Stream
  8. 关于python的垃圾回收机制_Python中的垃圾回收机制
  9. java读取某个文件夹下的所有文件
  10. IDM下载器使用教程
  11. 苏联W ndows视频,俄罗斯大神win10精简版32位
  12. 关于帧差法的想法(opencv)
  13. 《炬丰科技-半导体工艺》 砷化硼热管理
  14. 华三路由器ER3260 ipsec配置
  15. 成语小秀才云开发代码 成语答题小程序源码
  16. 常微分方程求解器ODE solver
  17. java中以yyyyMMddHHmmss格式取得系统时间
  18. Building dependency tree… Done Package aptitude is not available, but is referred to by another pac
  19. Java 序列化对象为json字符串,属性首字母大写,并按照属性首字母排序
  20. python怎么实现直播_Python实现直播推流效果

热门文章

  1. 重装服务器,解决怪问题
  2. C# WinForm 开软件窗口居中 任意时刻窗体居中
  3. centos7 mysql5.6.35_Centos7.2.1511 编译安装Mysql5.6.35
  4. c语言编程ppt免费下载,概述C语言编程.ppt
  5. NGN学习笔记1——NGN的基本概念和体系结构
  6. 【钛坦白】榛杏科技CEO周开宇:ICO和区块链的创新方向选择
  7. 我带上你 你带上钱,我们去班加罗尔
  8. CHIL-SQL-服务器 - RDBMS
  9. [李景山php]每天TP5-20161206|Loader.php-4
  10. mysql 判断指定条件数据存不存在,不存在则插入