[OpenCV学习笔记]Qt+OpenCV实现图像灰度反转、对数变换和伽马变换
目录
- 1、介绍
- 1.1 灰度反转
- 1.2 图像对数变换
- 1.3 图像伽马变换
- 2、效果图
- 3、代码实现
- 4、源码展示
1、介绍
1.1 灰度反转
灰度反转是一种线性变换,是将某个范围的灰度值映射到另一个范围内,一般是通过灰度的对调,突出想要查看的灰度区间。
S = L − 1 − r ( r ⊂ [ 0 , L − 1 ] ) S = L -1-r (r \subset [0,L-1]) S=L−1−r(r⊂[0,L−1])
比如在以下胸片图像中提取白色絮状形状,在黑色背景下看的不太明显,就可以使用灰度反转增强图像的可视化效果。

output_img = input_img.clone();
for(int i = 0; i < input_img.rows; i++)
{for(int j = 0; j < input_img.cols; j++){output_img.at<uchar>(i, j) = 255 - input_img.at<uchar>(i, j)}
}
1.2 图像对数变换
对数变换可以将图像中低灰度值的部分进行提升,显示出低灰度部分的特征,对高灰度值部分进行抑制,减少高灰度值部分的细节,从而实现增项图像俺不细节,优化图像的对比度。
S = c log ( 1 + r ) S=c\log(1+r) S=clog(1+r)
其原理就是,对数曲线在像素值低的区域斜率大,在像素值高的地方斜率小。

对数变换后图像的灰度值可能会超出0~255的区间,所以在对数变换后要进行归一化处理,将图像灰度值调节回0-255的区间。

Mat LogarithmImg = grayImg.clone();for(int i=0;i<grayImg.rows;i++){for(int j=0;j<grayImg.cols;j++){LogarithmImg.at<uchar>(i,j) = 6*log((double)grayImg.at<uchar>(i,j) + 1);}}normalize(LogarithmImg, LogarithmImg, 0, 255,NORM_MINMAX);convertScaleAbs(LogarithmImg,LogarithmImg);
1.3 图像伽马变换
图像的伽马变换其实就是通过非线性变换将图像中较暗区域的灰度值进行增强,对较亮区域的灰度值进行抑制,从而获得图像比较好的细节特征。
s = c r γ ( r ∈ [ 0 , 1 ] ) s=cr^\gamma (r\in[0, 1]) s=crγ(r∈[0,1])
r为灰度的输入值,c为灰度缩放系数,伽马因子控制整个变换的缩放程度。

Mat gammaImg = grayImg.clone();for(int i=0;i<grayImg.rows;i++){for(int j=0;j<grayImg.cols;j++){gammaImg.at<uchar>(i,j) = 6*pow((double)grayImg.at<uchar>(i,j), 0.5);}}normalize(gammaImg, gammaImg, 0, 255,NORM_MINMAX);convertScaleAbs(gammaImg,gammaImg);
2、效果图
使用lena图进行灰度反转、对数变换、伽马变化测试,在Qt上实现加载和变换。

3、代码实现
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include "opencv2/opencv.hpp"
#include <QResizeEvent>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEusing namespace cv;
class Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_btn_loadPic_clicked();void on_btn_InversionTrans_clicked();void on_btn_logarithmTrans_clicked();void on_btn_gammaTrans_clicked();void on_btn_resetPic_clicked();private:Ui::Widget *ui;// 灰度图像Mat grayImg;// Mat图像类型转换为QImageQImage cvMat2QImage(const cv::Mat &mat);
};
#endif // WIDGET_H
widget.cpp
#pragma execution_character_set("utf-8")
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);this->setWindowTitle("OpenCV图像变换");
}Widget::~Widget()
{delete ui;
}void Widget::on_btn_loadPic_clicked()
{Mat Img = imread("lena.png");cvtColor(Img, grayImg, COLOR_BGR2GRAY);QImage qImg_Gray = cvMat2QImage(grayImg);ui->lbl_grayPic->setPixmap(QPixmap::fromImage(qImg_Gray.scaled(ui->lbl_grayPic->size())));
}void Widget::on_btn_InversionTrans_clicked()
{Mat InversionImg = grayImg.clone();for(int i=0;i<grayImg.rows;i++){for(int j=0;j<grayImg.cols;j++){InversionImg.at<uchar>(i,j) = 255 - grayImg.at<uchar>(i,j);}}QImage qImg_Inversion = cvMat2QImage(InversionImg);ui->lbl_InversionPic->setPixmap(QPixmap::fromImage(qImg_Inversion.scaled(ui->lbl_InversionPic->size())));
}void Widget::on_btn_logarithmTrans_clicked()
{Mat LogarithmImg = grayImg.clone();for(int i=0;i<grayImg.rows;i++){for(int j=0;j<grayImg.cols;j++){LogarithmImg.at<uchar>(i,j) = 6*log((double)grayImg.at<uchar>(i,j) + 1);}}normalize(LogarithmImg, LogarithmImg, 0, 255,NORM_MINMAX);convertScaleAbs(LogarithmImg,LogarithmImg);QImage qImg_Logarithm = cvMat2QImage(LogarithmImg);ui->lbl_LogPic->setPixmap(QPixmap::fromImage(qImg_Logarithm.scaled(ui->lbl_LogPic->size())));
}void Widget::on_btn_gammaTrans_clicked()
{Mat gammaImg = grayImg.clone();for(int i=0;i<grayImg.rows;i++){for(int j=0;j<grayImg.cols;j++){gammaImg.at<uchar>(i,j) = 6*pow((double)grayImg.at<uchar>(i,j), 0.5);}}normalize(gammaImg, gammaImg, 0, 255,NORM_MINMAX);convertScaleAbs(gammaImg,gammaImg);QImage qImg_Gamma = cvMat2QImage(gammaImg);ui->lbl_GammaPic->setPixmap(QPixmap::fromImage(qImg_Gamma.scaled(ui->lbl_GammaPic->size())));
}void Widget::on_btn_resetPic_clicked()
{ui->lbl_grayPic->clear();ui->lbl_InversionPic->clear();ui->lbl_LogPic->clear();ui->lbl_GammaPic->clear();
}QImage Widget::cvMat2QImage(const cv::Mat &mat)
{switch ( mat.type() ){// 8-bit 4 channelcase CV_8UC4:{QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB32 );return image;}// 8-bit 3 channelcase CV_8UC3:{QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB888 );return image.rgbSwapped();}// 8-bit 1 channelcase CV_8UC1:{static QVector<QRgb> sColorTable;// only create our color table onceif ( sColorTable.isEmpty() ){sColorTable.resize( 256 );for ( int i = 0; i < 256; ++i ){sColorTable[i] = qRgb( i, i, i );}}QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_Indexed8 );image.setColorTable( sColorTable );return image;}default:qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels());qWarning() << "cvMatToQImage - cv::Mat image type not handled in switch:" << mat.type();break;}return QImage();
}
4、源码展示
本小例程的代码放到我的开源gitte项目里,欢迎一起学习交流,也希望能收获你的小星星。
项目源码GrayTrans
相关文章:
[OpenCV学习笔记]Qt+OpenCV实现图像灰度反转、对数变换和伽马变换
目录 1、介绍1.1 灰度反转1.2 图像对数变换1.3 图像伽马变换 2、效果图3、代码实现4、源码展示 1、介绍 1.1 灰度反转 灰度反转是一种线性变换,是将某个范围的灰度值映射到另一个范围内,一般是通过灰度的对调,突出想要查看的灰度区间。 S …...
【大数据】Flink学习笔记
文章目录 认识FlinkDocker安装Flink基本概念Flink的特点Flink 和 Spark Streaming 对比 基本使用WordCount实现依赖 批模式代码流模式代码网络流模式代码在web UI上提交代码创建项目[^1]编写代码配置打包在Web UI上提交 Flink 架构系统架构核心概念并行度算子链(Opeartor Chain…...
社交网络的未来:Facebook如何塑造数字社交的下一章
引言 社交网络已成为我们生活中不可或缺的一部分,而Facebook作为其领军者,一直在塑造着数字社交的未来。本文将深入探讨Facebook在未来如何塑造数字社交的下一章,并对社交网络的发展趋势进行展望和分析。 1. 引领虚拟社交的潮流 Facebook将…...
RabbitMQ 延时消息实现
1. 实现方式 1. 设置队列过期时间:延迟队列消息过期 死信队列,所有消息过期时间一致 2. 设置消息的过期时间:此种方式下有缺陷,MQ只会判断队列第一条消息是否过期,会导致消息的阻塞需要额外安装 rabbitmq_delayed_me…...
【Django】枚举类型数据
模型 在模型里主要增加两项内容: 枚举表字段增加choices class Snort(CoreModel):PAGE_TYPE_CHOICES [(1, 失陷主机检测), # 1是保存到数据库里的数据,失陷主机检测是显示在前端的(2, 远程漏洞攻击检测),(3, 可疑流量行为),(4, WEB检测),]page_type…...
java实现https连接总是要报no cipher suites in common
遇到“no cipher suites in common”这样的错误通常意味着客户端和服务器之间没有共同支持的加密套件(Cipher Suite)。这个问题可能由多个原因引起,包括但不限于SSL/TLS配置错误、Java安全策略限制、客户端或服务器不支持的加密算法等。解决这…...
[C++初阶] 爱上C++ : 与C++的第一次约会
🔥个人主页:guoguoqiang 🔥专栏:我与C的爱恋 本篇内容带大家浅浅的了解一下C中的命名空间。 在c中,名称(name)可以是符号常量、变量、函数、结构、枚举、类和对象等等。工程越大,名称…...
STM32技术打造:智能考勤打卡系统 | 刷卡式上下班签到自动化解决方案
文章目录 一、简易刷卡式打卡考勤系统(一)功能简介原理图设计程序设计 哔哩哔哩: https://www.bilibili.com/video/BV1NZ421Y79W/?spm_id_from333.999.0.0&vd_sourcee5082ef80535e952b2a4301746491be0 一、简易刷卡式打卡考勤系统 &…...
module ‘numpy‘ has no attribute ‘int‘
在 NumPy 中,如果遇到了错误提示 "module numpy has no attribute int",这通常意味着正在尝试以错误的方式使用 NumPy 的整数类型。从 NumPy 1.20 版本开始,numpy.int 已经不再是一个有效的属性,因为 NumPy 不再推荐使用…...
MFC(一)搭建空项目
安装MFC支持库 创建空白桌面程序 项目相关设置 复制以下代码 // mfc.h #pragma once #include <afxwin.h>class MyApp : public CWinApp { public:virtual BOOL InitInstance(); };class MyFrame : public CFrameWnd { public:MyFrame();// 消息映射机制DECLARE_…...
OKCC的API资源管理平台怎么用?
API资源管理平台,重点是“资源”管理平台,不是API接口管理平台。 天天讯通推出的API资源管理平台,类似昆石的VOS系统,区别是VOS是SIP资源管理系统,我们的API资源管理平台是API资源管理系统(AXB、AX、回拨AP…...
CentOS 7 安装python 3.7 需要必要的依赖。
在 CentOS 7 上部署 Python 3.7 可以通过源代码编译安装来实现。以下是大致的步骤: 安装必要的依赖: bashCopy Code sudo yum install gcc openssl-devel bzip2-devel libffi-devel 下载 Python 3.7 源代码并进行编译安装: bashCopy Code wg…...
美术馆设计方案优化布局与设施提升观众体验!
如今,美术馆不仅仅是作为展示艺术作品的平台,也是吸引公众参与和创造独特体验的数字艺术体验空间,因此许多传统美术馆在进行翻修改造时,都会更加注重用户体验,并在其中使用大量的多媒体互动,让参观者能够在…...
数据库基础原理
宏观 数据库的实现原理分为四个部分: 网络通信 网络协议 硬盘存储 内存分配 微观 硬盘存储 数据库是持久化的,而持久化如何实现的,我们不难想到磁盘可以持久化存储,所以数据库所有持久化的数据都是以文件形式存在磁盘中的…...
Pandas操作MultiIndex合并行列的Excel,写入读取以及写入多余行及Index列处理,插入行,修改某个单元格的值,多字段排序
Pandas操作MultiIndex合并行列的excel,写入读取以及写入多余行及Index列处理,多字段排序尽量保持原来的顺序 1. 效果图及问题2. 源码参考 今天是谁写Pandas的 复合索引MultiIndex,写的糊糊涂涂,晕晕乎乎。 是我呀… 记录下&#…...
工作总结5
1.taro框架使用map标签出现的错误 这个问题困扰很长时间,在频繁切换页面渲染的时候出现左边不显示,我理解的是变量没有到达map标签的属性上,那我就想是不是setState太慢了,然后又用了变量,本地缓存等,都没有…...
速通汇编(二)汇编mov、addsub指令
一,mov指令 mov指令的全称是move,从字面上去理解,作用是移动(比较确切的说是复制)数据,mov指令可以有以下几种形式 无论哪种形式,都是把右边的值移动到左边 mov 寄存器,数据&#…...
软考 - 系统架构设计师 - 构件组装技术
概念 构件组装是将库中的构件经修改后相互连接,或者将它们和当前开发项目中的软件元素进行连接,最终构成新的目标构件。 构件组装技术是基于构件的软件开发的核心技术,也是构件技术研究的重点和难点。构件组装的目的是利用现有的构件组装成新…...
2010年之前电脑ubuntu安装nvidia驱动黑屏处理
装好驱动 仿真fps直接到60Hz 陈旧设备 都是非常老旧的电脑,没钱换新电脑,就这么穷…… 电脑详细配置: 冲动 想装显卡驱动提升一下性能,结果……黑了 黑习惯了也无所谓,几分钟就能解决,关键还是太穷&…...
类与对象中C++
加油!!! 文章目录 前言 一、类的6个默认成员函数 编辑 二、构造函数 1.概念 三、析构函数 1.概念 2.特性 四、拷贝构造函数 1.概念 2.特征 拷贝构造函数典型调用场景 五、赋值运算符重载 1.运算符重载 2.赋值运算符重载 赋值运算符重载格式…...
CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)
漏洞概览 漏洞名称:Apache Flink REST API 任意文件读取漏洞CVE编号:CVE-2020-17519CVSS评分:7.5影响版本:Apache Flink 1.11.0、1.11.1、1.11.2修复版本:≥ 1.11.3 或 ≥ 1.12.0漏洞类型:路径遍历&#x…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...
Monorepo架构: Nx Cloud 扩展能力与缓存加速
借助 Nx Cloud 实现项目协同与加速构建 1 ) 缓存工作原理分析 在了解了本地缓存和远程缓存之后,我们来探究缓存是如何工作的。以计算文件的哈希串为例,若后续运行任务时文件哈希串未变,系统会直接使用对应的输出和制品文件。 2 …...
解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...
DeepSeek越强,Kimi越慌?
被DeepSeek吊打的Kimi,还有多少人在用? 去年,月之暗面创始人杨植麟别提有多风光了。90后清华学霸,国产大模型六小虎之一,手握十几亿美金的融资。旗下的AI助手Kimi烧钱如流水,单月光是投流就花费2个亿。 疯…...
41道Django高频题整理(附答案背诵版)
解释一下 Django 和 Tornado 的关系? Django和Tornado都是Python的web框架,但它们的设计哲学和应用场景有所不同。 Django是一个高级的Python Web框架,鼓励快速开发和干净、实用的设计。它遵循MVC设计,并强调代码复用。Django有…...
Yii2项目自动向GitLab上报Bug
Yii2 项目自动上报Bug 原理 yii2在程序报错时, 会执行指定action, 通过重写ErrorAction, 实现Bug自动提交至GitLab的issue 步骤 配置SiteController中的actions方法 public function actions(){return [error > [class > app\helpers\web\ErrorAction,],];}重写Error…...
