使用VC++实现分段线性变换,直方图均衡化、锐化处理(使用拉普拉斯算子)
图像锐化1
实验要求
5.1实验目的、要求
实验目的:
(1)掌握图像增强的原理与相关方法。
(2)能使用VC++实现图像增强的一些相关功能。
实验要求:
A部分:
(1)对一幅256级灰度图像,使用VC++实现分段线性变换,直方图均衡化。
(2)对一幅256级灰度图像,使用VC++实现锐化处理(使用拉普拉斯算子)。
一、 分段线性变换
1. 分段线性变换的原理
灰度图像分段线性变换是一种调整图像灰度级别的方法,它通过将灰度范围划分为多个分段,然后对每个分段应用线性变换来调整图像的对比度和亮度。这种方法的主要目的是增强或减弱图像中特定灰度范围的细节,以改善图像的视觉效果。
下面是该方法的基本原理:
-
分段划分: 将整个灰度范围划分为多个不重叠的分段。每个分段代表图像中的一个灰度范围。这些分段由一个或多个分界点定义,这些分界点将整个灰度范围划分成不同的区域。
-
线性变换: 对每个分段应用线性变换。线性变换由斜率和截距两个参数定义。斜率决定了线的倾斜程度,而截距则控制了线的位置。通过调整这两个参数,可以实现对分段内灰度级别的调整。
-
像素更新: 对图像的每个像素应用上述的分段线性变换。首先,确定像素所属的分段,然后使用该分段对应的线性变换来更新像素的灰度值。这样,每个像素都会根据其原始灰度值和所属分段的线性变换进行调整。
通过灰度图像分段线性变换,可以实现对图像不同灰度范围的灰度级别进行差异化的调整。例如,可以增强图像中的低对比度区域或减弱过曝区域,从而更好地展现图像细节。这种方法在图像增强和调整方面具有一定的灵活性,但需要根据具体的应用场景和图像特性来选择适当的分段和线性变换参数。
2. 分段线性变换的实验代码
3. 分段线性变换的实验现象
左:原灰度图
右:灰度图像分段线性变换后
二、直方图均衡化
1. 直方图均衡化的原理
直方图均衡化是一种用于增强图像对比度的图像处理技术。其基本原理是将图像的灰度直方图变换成一个均匀分布的直方图,从而拉伸图像的灰度范围,使得亮度水平更加均匀,细节更为突出。
具体的步骤如下:
-
计算直方图: 统计图像中每个灰度级别的像素数量,形成直方图。
-
计算累积分布函数(CDF): 将直方图进行归一化,得到每个灰度级别对应的累积概率。
C D F ( i ) = ∑ j = 0 i P ( j ) CDF(i) = \sum_{j=0}^{i} P(j) CDF(i)=j=0∑iP(j)
其中, P ( j ) P(j) P(j) 是灰度级别 j j j 的概率。
-
直方图均衡化变换函数: 将CDF的值映射到新的灰度级别范围。
H ( i ) = round ( C D F ( i ) × ( L − 1 ) N ) H(i) = \text{round}\left(\frac{CDF(i) \times (L-1)}{N}\right) H(i)=round(NCDF(i)×(L−1))
其中, H ( i ) H(i) H(i) 是新的灰度级别, L L L 是灰度级别的最大值, N N N 是图像的总像素数量。 r o u n d ( ) round() round() 是一个数学函数,通常用于将一个浮点数四舍五入为最接近的整数
-
应用变换: 将变换函数应用于图像的每个像素,更新图像的灰度级别。
通过直方图均衡化,原始图像中灰度分布不均匀的区域会被映射到更广泛的灰度范围,从而提高了图像的对比度,使细节更加清晰。
2. 直方图均衡化的实验代码
BOOL HistogramEqualize(CDib* pDib){// 指向源图像的指针unsigned char* lpSrc;// 临时变量int nTemp;// 循环变量int i,j;// 累积直方图,即灰度映射表BYTE byMap[256];// 直方图int nCount[256];// 图象的高度和宽度CSize sizeImage;sizeImage = pDib->GetDimensions();// 获得图象数据存储的高度和宽度CSize SizeSaveImage;SizeSaveImage = pDib->GetDibSaveDim();// 重置计数为0for (i = 0; i < 256; i ++){// 清零nCount[i] = 0;}// 计算各个灰度值的计数,即得到直方图for (i = 0; i < sizeImage.cy; i ++){for (j = 0; j < sizeImage.cx; j ++){lpSrc = (unsigned char *)pDib->m_lpImage + SizeSaveImage.cx * i + j;//表示从图像数据的起始位置开始,跳过 i 行,再移动 j 列,最终指向了图像中第 i 行、第 j 列的像素的位置,获取图像中第 i 行、第 j 列的像素的灰度值// 计数加1nCount[*(lpSrc)]++;//以灰度值的大小为下坐标,进行计数}}// 计算累积直方图for (i = 0; i < 256; i++){// 初始为0nTemp = 0;for (j = 0; j <= i ; j++){nTemp += nCount[j];}// 计算对应的新灰度值---公式byMap[i] = (BYTE) (nTemp * 255 / sizeImage.cy / sizeImage.cx);}// 每行for(i = 0; i < sizeImage.cy; i++){// 每列for(j = 0; j < sizeImage.cx; j++){// 指向DIB第i行,第j个象素的指针lpSrc = (unsigned char*)pDib->m_lpImage + pDib->GetPixelOffset(i,j);// 计算新的灰度值x*lpSrc = byMap[*lpSrc];//找到当前像素的原始灰度值,并将其映射为新的灰度值。}}// 返回return TRUE;}
3. 直方图均衡化的实验现象
左:原图
右:直方图均衡化增强后
三、 拉普拉斯算子实现锐化
拉普拉斯算子的原理
拉普拉斯算子(Laplacian operator)是一种用于图像处理的滤波器,主要用于检测图像中的边缘和细节。它通过计算图像中每个像素点的二阶导数来实现。
拉普拉斯算子的一维形式为:
L ( x ) = d 2 d x 2 L(x) = \frac{d^2}{dx^2} L(x)=dx2d2
而在二维图像上的应用是通过以下离散形式的卷积核:
[ 0 1 0 1 − 4 1 0 1 0 ] \begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \\ \end{bmatrix} 0101−41010
应用拉普拉斯算子的过程是将这个卷积核与图像进行卷积运算。具体而言,对于图像中的每个像素,将其与卷积核中的对应元素相乘,然后将所有相乘的结果相加。这个过程可以用以下的数学表达式表示:
L ( x , y ) = ∑ i = − 1 1 ∑ j = − 1 1 kernel ( i , j ) × image ( x + i , y + j ) L(x, y) = \sum_{i=-1}^{1} \sum_{j=-1}^{1} \text{kernel}(i, j) \times \text{image}(x + i, y + j) L(x,y)=i=−1∑1j=−1∑1kernel(i,j)×image(x+i,y+j)
其中, kernel ( i , j ) \text{kernel}(i, j) kernel(i,j) 是卷积核中的元素, image ( x + i , y + j ) \text{image}(x + i, y + j) image(x+i,y+j) 是图像中对应位置的像素值。
拉普拉斯算子对图像进行了高通滤波,强调了图像中的高频细节和边缘。应用拉普拉斯算子后,边缘部分的像素值将发生变化,使得图像中的边缘更加明显。然而,拉普拉斯算子也会增加图像中的噪声。因此,在实际应用中,通常会结合其他技术,如平滑(低通滤波)来减少噪声的影响。
拉普拉斯算子的实验代码
/*************************************************************************** \函数名称:* LinearSharpen()** \输入参数:* LPBYTE lpImage - 指向图象数据得指针* int nWidth - 图象数据宽度* int nHeight - 图象数据高度** \返回值:* 无** \说明:* 线性锐化图象增强* 本函数采用拉普拉斯算子对图象进行线性锐化* 在原来图象上加上拉普拉斯算子锐化的信息***************************************************************************/
void LinearSharpen (LPBYTE lpImage, int nWidth, int nHeight)
{// 遍历图象的纵坐标int y;// 遍历图象的横坐标int x;double * pdGrad ;pdGrad = new double[nWidth*nHeight];//用于存储图像的梯度信息。// 初始化为0memset(pdGrad, 0, nWidth*nHeight*sizeof(double)) ;// 设置模板系数--设置拉普拉斯算子的卷积核,这是一个 3x3 的矩阵,用于计算图像中每个像素点的梯度。static int nWeight[3][3] ;nWeight[0][0] = -1 ; nWeight[0][1] = -1 ; nWeight[0][2] = -1 ; nWeight[1][0] = -1 ; nWeight[1][1] = 8 ; nWeight[1][2] = -1 ; nWeight[2][0] = -1 ; nWeight[2][1] = -1 ; nWeight[2][2] = -1 ; //这个变量用来表示Laplacian算子象素值int nTmp[3][3];// 临时变量double dGrad;// 模板循环控制变量int yy ;int xx ;for(y=1; y<nHeight-1 ; y++ )for(x=1 ; x<nWidth-1 ; x++ ){dGrad = 0 ; // Laplacian算子需要的各点象素值// 模板第一行nTmp[0][0] = lpImage[(y-1)*nWidth + x - 1 ] ; nTmp[0][1] = lpImage[(y-1)*nWidth + x ] ; nTmp[0][2] = lpImage[(y-1)*nWidth + x + 1 ] ; // 模板第二行nTmp[1][0] = lpImage[y*nWidth + x - 1 ] ; nTmp[1][1] = lpImage[y*nWidth + x ] ; nTmp[1][2] = lpImage[y*nWidth + x + 1 ] ; // 模板第三行nTmp[2][0] = lpImage[(y+1)*nWidth + x - 1 ] ; nTmp[2][1] = lpImage[(y+1)*nWidth + x ] ; nTmp[2][2] = lpImage[(y+1)*nWidth + x + 1 ] ; // 计算梯度for(yy=0; yy<3; yy++)for(xx=0; xx<3; xx++){dGrad += nTmp[yy][xx] * nWeight[yy][xx] ;}// 梯度值写入内存*(pdGrad+y*nWidth+x)=dGrad;}//将计算得到的梯度值加到原始图像上,实现锐化效果。for(y=0; y<nHeight ; y++ ){for(x=0 ; x<nWidth ; x++ ){lpImage[y*nWidth+x] = (unsigned char)max(0,min(255,(lpImage[y*nWidth+x] + (int)pdGrad[y*nWidth+x]) ));}}//释放申请的内存delete []pdGrad ;pdGrad = NULL ;
}
拉普拉斯算子的实验现象
左:原图
右:经过拉普拉斯锐化
相关文章:

使用VC++实现分段线性变换,直方图均衡化、锐化处理(使用拉普拉斯算子)
图像锐化1 实验要求 5.1实验目的、要求 实验目的: (1)掌握图像增强的原理与相关方法。 (2)能使用VC实现图像增强的一些相关功能。 实验要求: A部分: (1)对一幅256级灰度…...
react class改hooks写法
类头修改 export default class EditUseTable extends Component 改为 export default function EditUseTable({})参数修改 constructor(props) {super(props)const {dbRecord, type, currentRecord, readOnly, updateTaxAmount} this.props改为(主函数的参数&a…...

桂院校园导航 | 云上高校导航 云开发项目 二次开发教程 1.3
Gitee代码仓库:桂院校园导航小程序 GitHub代码仓库:GLU-Campus-Guide 演示视频 中国大学生计算机设计大赛-移动应用与开发-云上高校导航 升级日志 1.3 优化了小程序的数据存储方式,对部分页面进行了调整,调整了功能和代码。 引…...

sscanf提取相应字符到数组
代码如下 #include<stdio.h> #include<string.h>int main(int argc, char const *argv[]) {char buf[128] {0};int m1 0, m2 0;int s1 0, s2 0;char lrc[128] "";sscanf("[02:16.33][04:11.44]我想大声宣布对你恋恋不舍","[%*1d%d…...

本地开发环境和服务器传输数据的几种方法
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...

LeetCode之二叉树
发现更多计算机知识,欢迎访问Cr不是铬的个人网站 最近数据结构学到二叉树,就刷了刷力扣,写这篇文章也是辅助记忆。 103二叉树锯齿形遍历 要解出本道题,首先要会层次遍历。层次遍历我们都知道用一个队列去实现就行。但是力扣这里…...

论文学习——THE USTC SYSTEM FOR ADRESS-M CHALLENGE
文章目录 引言正文Abstract模型基本结构模型效果汇总 Introduction介绍跨语言任务的独特性思路启发和变化如何使用预定义好的音频特征如何使用预定义好的语言模型——语言模型中获取韵律信息结果说明 Dataset数据集Mthods方法使用设计好的特征进行AD检测使用的特征分类和训练方…...

第一百七十五回 如何创建放射形状渐变背景
文章目录 1. 概念介绍2. 实现方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在 上一章回中介绍了"如何创建扇形渐变背景"相关的内容,本章回中将介绍" 如何创建放射形状渐变背景"。闲话休提,让我们一起Talk Flutter吧…...
vue实现调用手机拍照、录像功能
目录 前言 准备工作 在这个示例中,我们将使用Vue.js框架来实现我们的目标。如果你还不熟悉Vue.js,推荐先学习一下Vue.js的基础知识。 接下来,我们需要创建一个基于Vue.js的项目。你可以使用Vue CLI来创建一个全新的Vue项目:# 安…...
WPF播放视频
在WPF中,你可以使用MediaElement来播放本地视频。下面是一个简单的例子: <Window x:Class"WPFVideoPlayer.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsof…...

交换机如何配置BGP协议
环境: 华为交换机 华三交换机 问题描述: 交换机如何配置BGP协议 解决方案: 华三交换机上配置案例 1.配置BGP协议,可以按照以下步骤进行: 登录交换机:使用SSH、Telnet或控制台等方式登录到华三交换…...
精通Nginx(14)-配置HTTPS
HTTPS是在 HTTP 协议的基础上使用 TLS/SSL 加密,其主要目标是提高数据传输的安全性。从HTTP2.0开始,HTTPS已经是网站的标准协议,很多开放平台非HTTPS不能访问。Nginx为HTTPS提供了强大的支持,且对应用服务器是完全透明的。 目录 SSL/TLS基础 发展历史 TLS握手过程 加密…...
封装一个简单的table组件
子组件 <template> <el-table :data"tableData" :headers"tableHeaders" style"width: 100%"> <el-table-column v-for"header in tableHeaders" :key"header.prop" :label"header.label" :pro…...
Avalonia UI框架介绍
Avalonia UI是一个跨平台的UI框架,它允许开发者使用XAML和C#语言创建可在多个平台上运行的应用程序,包括Windows、Linux、macOS等。Avalonia UI与WPF非常相似,但是它是开源的,并且更加灵活。 下面是一个简单的Avalonia UI应用程序…...

【入门篇】1.3 redis客户端之 jedis 高级使用示例
文章目录 0.前言1. 发布和订阅消息2. 事务操作3. 管道操作4. jedis 支持哨兵模式5. jedis 支持集群模式5. 参考链接 0.前言 Jedis是Redis的Java客户端,它支持所有的Redis原生命令,使用方便,且可以与Java项目无缝集成。 该库的最新版本支持Re…...

使用CXF调用WSDL(二)
简介 本篇文章主要解决了上篇文章中遗留的对象嵌套问题,要想全面解析无限极的对象嵌套需要使用递归去解决 上文链接: 使用CXF调用WSDL(一) 上文回顾 上文使用了单方法“ call() ”解决了List和基本类型(含String&…...
list.toArray
直接去看原文 原文链接:List的toArray()方法_list.toarray-CSDN博客 -------------------------------------------------------------------------------------------------------------------------------- toArray()介绍 toArray()方法是List接口中提供的方法ÿ…...

2013年11月10日 Go生态洞察:Go语言四周年回顾
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
Ubuntu上使用SSH连接到CentOS系统
确保CentOS系统上的SSH服务器已安装并正在运行: 在CentOS上,默认情况下,SSH服务器(sshd)应该已安装并正在运行。如果不确定,可以通过以下方式检查: sudo systemctl status sshd如果未安装&…...

【知识增强】A Survey of Knowledge-Enhanced Pre-trained LM 论文笔记
A Survey of Knowledge-Enhanced Pre-trained Language Models Linmei Hu, Zeyi Liu, Ziwang Zhao, Lei Hou, Liqiang Nie, Senior Member, IEEE and Juanzi Li 2023年8月的一篇关于知识增强预训练模型的文献综述 论文思维导图 思维导图网页上看不清的话,可以存…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...