Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于
所有文章 工具

Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于

图像亮度对比度调整

阅读数:次 2018-08-29
字数统计: 1.6k字   |   阅读时长≈ 7分

读写像素

读一个GRAY像素点的像素值(CV_8UC1)

1
2
3
4
//方式一
Scalar intensity = img.at<uchar>(y, x);
//方式二
Scalar intensity = img.at<uchar>(Point(x, y));

读一个BGR像素点的像素值

1
2
3
4
5
6
7
8
9
10
//读取整形
Vec3b intensity = src.at<Vec3b>(x, y);
int b = intensity [0];
int g = intensity [1];
int r = intensity [2];
//读取浮点型
Vec3f intensity = img.at<Vec3f>(y, x);
float blue = intensity.val[0];
float green = intensity.val[1];
float red = intensity.val[2];

Vec3b与Vec3F

  • Vec3b对应三通道的顺序是blue、green、red的uchar类型数据。
  • Vec3f对应三通道的float类型数据
  • 把CV_8UC1转换到CV32F1实现如下:src.convertTo(dst, CV_32F);

修改像素值

灰度图像
img.at(y, x) = 128;

RGB三通道图像
img.at(y,x)[0]=128; // blue
img.at(y,x)[1]=128; // green
img.at(y,x)[2]=128; // red

空白图像赋值
img = Scalar(0);

ROI选择
Rect r(10, 10, 100, 100);
Mat smallImg = img(r);

获取灰度图像素点

接下来用灰度图的反色作为示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{

Mat src = imread("C:\\Users\\Tim\\Desktop\\Image\\a.jpg");
if (src.empty())
{
cout << "load image filed..." << endl;
return -1;
}

namedWindow("src_window", CV_WINDOW_AUTOSIZE);
imshow("src_window", src);

Mat src_gray;
cvtColor(src, src_gray, CV_BGR2GRAY);

namedWindow("src_gray_window", CV_WINDOW_AUTOSIZE);
imshow("src_gray_window", src_gray);

int height = src_gray.rows;
int width = src_gray.cols;

//单通道
for (int row = 0; row < height;row++){
for (int col = 0; col < width; col++) {
//给每一个像素点取反
int gray = src_gray.at<uchar>(row, col);
src_gray.at<uchar>(row, col) = 255 - gray;
}
}
//展示灰度图的反色图
namedWindow("gray_window",CV_WINDOW_AUTOSIZE);
imshow("gray_window", src_gray);
waitKey(0);
return 0;
}

mark

获取三通道图像素点

对于三通道的像素点获取,以获取原图的反色图为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{

Mat src = imread("C:\\Users\\Tim\\Desktop\\Image\\a.jpg");
if (src.empty())
{
cout << "load image filed..." << endl;
return -1;
}

namedWindow("src_window", CV_WINDOW_AUTOSIZE);
imshow("src_window", src);

Mat src_gray;
cvtColor(src, src_gray, CV_BGR2GRAY);

int height = src_gray.rows;
int width = src_gray.cols;

//三通道图像初始化
Mat dst;
dst.create(src.size(), src.type());
height = src.rows;
width = src.cols;

//获取通道数
int cn = src.channels();

for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
if (cn == 1) {
//单通道图的处理,这块也就是上面的代码
int gray = src_gray.at<uchar>(row, col);
src_gray.at<uchar>(row, col) = 255 - gray;
}
else if(cn == 3){
//从原图中读取
int b = src.at<Vec3b>(row, col)[0];
int g = src.at<Vec3b>(row, col)[1];
int r = src.at<Vec3b>(row, col)[2];
//写入目标图像
dst.at<Vec3b>(row, col)[0] = 255 - b;
dst.at<Vec3b>(row, col)[1] = 255 - g;
dst.at<Vec3b>(row, col)[2] = 255 - r;
}
}
}
//使用API进行操作
//bitwise_not(src, dst)
namedWindow("gray_window",CV_WINDOW_AUTOSIZE);
imshow("gray_window", dst);
waitKey(0);
return 0;
}

mark

上面的反色,使用API也可以做到:bitwise_not(src, dst)

三通道图转为灰度图的其他方式

mark

通过把原图中的像素点设定为像素点中的最大或者最小值也是可以达到转换为灰度图的效果!

图像混合

理论-线性混合操作

mark

相关API (addWeighted)

参数1:输入图像Mat – src1
参数2:输入图像src1的alpha值
参数3:输入图像Mat – src2
参数4:输入图像src2的alpha值
参数5:gamma值
参数6:输出混合图像
注意点:两张图像的大小和类型必须一致才可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{

Mat src1 = imread("C:\\Users\\Tim\\Desktop\\Image\\a.jpg");
Mat src2 = imread("C:\\Users\\Tim\\Desktop\\Image\\b.jpg");
Mat ret;//输出图像
if (src1.empty() || src2.empty())
{
cout << "load image filed..." << endl;
return -1;
}

namedWindow("src1", CV_WINDOW_AUTOSIZE);
imshow("src1", src1);
namedWindow("src2", CV_WINDOW_AUTOSIZE);
imshow("src2", src2);

double alpha = 0.5;
//两张图片大小一致、类型一致
if (src1.rows == src2.rows && src1.cols == src2.cols
{
addWeighted(src1, alpha, src2, (1.0 - alpha), 0, ret);
//add(src1, src2, dst, Mat());
//multiply(src1, src2, dst, 1.0);
namedWindow("ret", CV_WINDOW_AUTOSIZE);
imshow("ret", ret);
}
else
{
cout << "Images vary in size or type!" << endl;
return -1;
}

waitKey(0);
return 0;
}

这是两张图片各占50%的权重合成的图像:

mark

对比度和亮度调整

图像亮度本质上图像中每个像素的亮度,每个像素的亮度本质上RGB值的大小,RGB值为0,则像素点为黑色,RGB都为255时像素点最亮,为白色。对比度则是不同像素点之间的差值,差值越大,对比度越明显。
图像变换可以看作如下:

  • 像素变换 – 点操作
  • 邻域操作 – 区域

mark

调整图像亮度和对比度属于像素变换-点操作,搞清楚原理下面开始撸代码:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc, char **argv)
{

Mat src = imread("C:\\Users\\Tim\\Desktop\\Image\\a.jpg");
Mat dst;
if (src.empty())
{
cout << "load image filed..." << endl;
return -1;
}
char *input_win = "input_win";
namedWindow(input_win, CV_WINDOW_AUTOSIZE);
imshow("input_win", src);

int height = src.rows;
int wight = src.cols;

//构建与src同等大小的空白图
dst = Mat::zeros(src.size(), src.type());

//差异倍数
float alpha = 0.4f;
//增益变量
float beta = 0.0f;

for (int row = 0; row < height; row++) {
for (int col = 0; col < wight; col++) {
//根据通道数目来判断处理方式
if (src.channels() == 3){
float b = src.at<Vec3b>(row, col)[0];
float g = src.at<Vec3b>(row, col)[1];
float r = src.at<Vec3b>(row, col)[2];

dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);
}
else if (src.channels() == 1) {
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha + beta);
}
}
}

//输出图像
char *output_win = "output_win";
namedWindow(output_win, CV_WINDOW_AUTOSIZE);
imshow(output_win, dst);

waitKey(0);
return 0;
}

从代码中可以看出:如果将值乘上差异倍数,那么像素点之间的差异倍数(alpha)越大,像素点之间的差异也就越大,这样导致的直接结果就是图像的对比度增强,增益变量越大,那么像素本身的值在增大,导致的结果就是亮度增强

演示效果

mark

重要的API

  • Mat new_image = Mat::zeros(image.size(), image.type()); 创建一张跟原图像大小和类型一致的空白图像、像素值初始化为0
  • saturate_cast(value)确保值大小范围为0~255之间
  • Mat.at(y,x)[index]=value给每个像素点每个通道赋值
赏

谢谢你请我喝咖啡

支付宝
微信
  • 本文作者: Tim
  • 本文链接: https://zouchanglin.cn/2477429062.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!
  • openCV
  • 图像处理

扫一扫,分享到微信

Mat与基本图形绘制
OpenCV矩阵掩模
  1. 1. 读写像素
    1. 1.1. 读一个GRAY像素点的像素值(CV_8UC1)
    2. 1.2. 读一个BGR像素点的像素值
  2. 2. Vec3b与Vec3F
  3. 3. 修改像素值
    1. 3.1. 获取灰度图像素点
    2. 3.2. 获取三通道图像素点
    3. 3.3. 三通道图转为灰度图的其他方式
  4. 4. 图像混合
    1. 4.1. 理论-线性混合操作
    2. 4.2. 相关API (addWeighted)
  5. 5. 对比度和亮度调整
    1. 5.1. 代码
    2. 5.2. 演示效果
    3. 5.3. 重要的API
© 2017-2021 Tim
本站总访问量次 | 本站访客数人
  • 所有文章
  • 工具

tag:

  • 生活
  • Android
  • 索引
  • MySQL
  • 组件通信
  • Nginx
  • JavaSE
  • JUC
  • JavaWeb
  • 模板引擎
  • 前端
  • Linux
  • 计算机网络
  • Docker
  • C/C++
  • JVM
  • 上传下载
  • JavaEE
  • SpringCloud
  • Golang
  • Gradle
  • 网络安全
  • 非对称加密
  • IDEA
  • SpringBoot
  • Jenkins
  • 字符串
  • vim
  • 存储
  • 文件下载
  • Mac
  • Windows
  • NIO
  • RPC
  • 集群
  • 微服务
  • SSH
  • 配置中心
  • XML
  • Chrome
  • 压力测试
  • Git
  • 博客
  • 概率论
  • 排序算法
  • 分布式
  • 异常处理
  • 文件系统
  • 哈希
  • openCV
  • 栈
  • 回溯
  • SpringCore
  • 流媒体
  • rtmp
  • 面向对象
  • Vue
  • ElementUI
  • 软件工程
  • 异步
  • 自定义UI
  • ORM框架
  • 模块化
  • 交互式
  • Jsoup
  • Http Client
  • LRUCache
  • RabbitMQ
  • 消息通信
  • 服务解耦
  • 负载均衡
  • 权限
  • 多线程
  • 单例模式
  • Protobuf
  • 序列化
  • Python
  • m3u8
  • 堆
  • 二叉树
  • 自定义View
  • 观察者模式
  • 设计模式
  • 线程池
  • 动态扩容
  • 高可用
  • GC
  • ffmpeg
  • SpringMVC
  • REST
  • Redis
  • 缓存中间件
  • UML
  • Maven
  • Netty
  • 高性能网络
  • IPC通信
  • IO
  • Stream
  • 发布订阅
  • SQLite
  • Hash
  • 集合框架
  • 链表
  • Lambda
  • 汇编语言
  • 组件化
  • Router
  • 开发工具

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia-plus根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 思维导图
  • PDF工具
  • 无损放大
  • 代码转图
  • HTTPS证书