使用VC++实现分段线性变换,直方图均衡化、锐化处理(使用拉普拉斯算子)

图像锐化1

获取源工程可访问huiningLi的gitee可在此工程的基础上进行学习。

实验要求

5.1实验目的、要求
实验目的:
(1)掌握图像增强的原理与相关方法。
(2)能使用VC++实现图像增强的一些相关功能。
实验要求:
A部分:
(1)对一幅256级灰度图像,使用VC++实现分段线性变换,直方图均衡化。
(2)对一幅256级灰度图像,使用VC++实现锐化处理(使用拉普拉斯算子)。

一、 分段线性变换

1. 分段线性变换的原理

灰度图像分段线性变换是一种调整图像灰度级别的方法,它通过将灰度范围划分为多个分段,然后对每个分段应用线性变换来调整图像的对比度和亮度。这种方法的主要目的是增强或减弱图像中特定灰度范围的细节,以改善图像的视觉效果。

下面是该方法的基本原理:

  1. 分段划分: 将整个灰度范围划分为多个不重叠的分段。每个分段代表图像中的一个灰度范围。这些分段由一个或多个分界点定义,这些分界点将整个灰度范围划分成不同的区域。

  2. 线性变换: 对每个分段应用线性变换。线性变换由斜率和截距两个参数定义。斜率决定了线的倾斜程度,而截距则控制了线的位置。通过调整这两个参数,可以实现对分段内灰度级别的调整。

  3. 像素更新: 对图像的每个像素应用上述的分段线性变换。首先,确定像素所属的分段,然后使用该分段对应的线性变换来更新像素的灰度值。这样,每个像素都会根据其原始灰度值和所属分段的线性变换进行调整。

通过灰度图像分段线性变换,可以实现对图像不同灰度范围的灰度级别进行差异化的调整。例如,可以增强图像中的低对比度区域或减弱过曝区域,从而更好地展现图像细节。这种方法在图像增强和调整方面具有一定的灵活性,但需要根据具体的应用场景和图像特性来选择适当的分段和线性变换参数。

2. 分段线性变换的实验代码

3. 分段线性变换的实验现象

在这里插入图片描述

左:原灰度图
右:灰度图像分段线性变换后
在这里插入图片描述

二、直方图均衡化

1. 直方图均衡化的原理

直方图均衡化是一种用于增强图像对比度的图像处理技术。其基本原理是将图像的灰度直方图变换成一个均匀分布的直方图,从而拉伸图像的灰度范围,使得亮度水平更加均匀,细节更为突出。

具体的步骤如下:

  1. 计算直方图: 统计图像中每个灰度级别的像素数量,形成直方图。

  2. 计算累积分布函数(CDF): 将直方图进行归一化,得到每个灰度级别对应的累积概率。

    C D F ( i ) = ∑ j = 0 i P ( j ) CDF(i) = \sum_{j=0}^{i} P(j) CDF(i)=j=0iP(j)

    其中, P ( j ) P(j) P(j) 是灰度级别 j j j 的概率。

  3. 直方图均衡化变换函数: 将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)×(L1))

    其中, H ( i ) H(i) H(i) 是新的灰度级别, L L L 是灰度级别的最大值, N N N 是图像的总像素数量。 r o u n d ( ) round() round() 是一个数学函数,通常用于将一个浮点数四舍五入为最接近的整数

  4. 应用变换: 将变换函数应用于图像的每个像素,更新图像的灰度级别。

通过直方图均衡化,原始图像中灰度分布不均匀的区域会被映射到更广泛的灰度范围,从而提高了图像的对比度,使细节更加清晰。

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} 010141010

应用拉普拉斯算子的过程是将这个卷积核与图像进行卷积运算。具体而言,对于图像中的每个像素,将其与卷积核中的对应元素相乘,然后将所有相乘的结果相加。这个过程可以用以下的数学表达式表示:

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=11j=11kernel(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   ;
}

拉普拉斯算子的实验现象

左:原图
右:经过拉普拉斯锐化
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/147822.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【python】均值、中值和高斯滤波详解和示例

本文对均值、中值和高斯滤波进行详解&#xff0c;以帮助大家理解和使用。 这里写目录标题 均值滤波中值滤波高斯滤波核大小为&#xff08;9,9&#xff09;核大小为&#xff08;51,51&#xff09; 小结 下面是示例中使用的原图。 均值滤波 均值滤波是一种简单的平滑滤波器&…

PyTorch微调权威指南3:使用数据增强

如果你曾经参与过 PyTorch 模型的微调&#xff0c;可能会遇到 PyTorch 的内置变换函数&#xff0c;这使得数据增强变得轻而易举。 即使你之前没有使用过这些功能&#xff0c;也不必担心。 在本文中&#xff0c;我们将深入研究 PyTorch 变换换函数的世界。 我们将探索你可以使用…

CTFhub-RCE-过滤目录分隔符 /

根据源代码信息可知&#xff0c;过滤掉了/ <?php $res FALSE; if (isset($_GET[ip]) && $_GET[ip]) { $ip $_GET[ip]; $m []; if (!preg_match_all("/\//", $ip, $m)) { $cmd "ping -c 4 {$ip}"; exec($cmd,…

【开源】基于Vue.js的高校实验室管理系统的设计和实现

项目编号&#xff1a; S 015 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S015&#xff0c;文末获取源码。} 项目编号&#xff1a;S015&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实…

数据结构与集合源码

我是南城余&#xff01;阿里云开发者平台专家博士证书获得者&#xff01; 欢迎关注我的博客&#xff01;一同成长&#xff01; 一名从事运维开发的worker&#xff0c;记录分享学习。 专注于AI&#xff0c;运维开发&#xff0c;windows Linux 系统领域的分享&#xff01; 本…

【数据结构与算法】线性表 - 顺序表

目录 1. 线性表2.顺序表3.顺序表的优缺点4.实现&#xff08;C语言&#xff09;4.1 头文件 seqList.h4.2 实现 seqList.c 1. 线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见…

音视频转换软件Permute mac中文板特点介绍

Permute mac是一款Mac平台上的媒体格式转换软件&#xff0c;由Chaotic Software开发。它可以帮助用户快速地将各种音频、视频和图像文件转换成所需格式&#xff0c;并提供了一些常用工具以便于用户进行编辑和处理。 Permute mac软件特点 - 支持大量格式&#xff1a;支持几乎所…

汇编-指针

一个变量如果包含的是另一个变量的地址&#xff0c; 则该变量就称为指针(pointer) 。指针是操作数组和数据结构的极好工具&#xff0c;因为它包含的地址在运行时是可以修改的。 .data arrayB byte 10h, 20h, 30h, 40h ptrB dword arrayB ptrB1 dword OFFSET arrayBarray…

Linux:权限篇 (彻底理清权限逻辑!)

shell命令以及运行原理&#xff1a; Linux严格意义上说的是一个操作系统&#xff0c;我们称之为“核心&#xff08;kernel&#xff09;“ &#xff0c;但我们一般用户&#xff0c;不能直接使用kernel。而是通过kernel的“外壳”程序&#xff0c;也就是所谓的shell&#xff0c;来…

YOLOV5部署Android Studio安卓平台NCNN

坑非常多&#xff0c;兄弟们&#xff0c;我已经踩了三天的坑了&#xff0c;我这里部署了官方的yolov5s和我自己训练的yolov5n的模型 下载Android Studio&#xff0c;配置安卓开发环境&#xff0c;这个过程比较漫长。 安装cmake&#xff0c;注意安装的是cmake3.10版本。 根据手机…

LeetCode——字符串(Java)

字符串 简介[简单] 344. 反转字符串[简单] 541. 反转字符串 II[中等] 151. 反转字符串中的单词 简介 记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录。会附上一些个人的思路&#xff0c;如果有错误&#xff0c;可以在评论区提醒一下。 [简单] 344. 反转字符串…

【IPC】消息队列

1、IPC对象 除了最原始的进程间通信方式信号、无名管道和有名管道外&#xff0c;还有三种进程间通信方式&#xff0c;这 三种方式称之为IPC对象 IPC对象分类&#xff1a;消息队列、共享内存、信号量(信号灯集) IPC对象也是在内核空间开辟区域&#xff0c;每一种IPC对象创建好…

15分钟,不,用模板做数据可视化只需5分钟

测试显示&#xff0c;一个对奥威BI软件不太熟悉的人来开发数据可视化报表&#xff0c;要15分钟&#xff0c;而当这个人去套用数据可视化模板做报表&#xff0c;只需5分钟&#xff01; 数据可视化模板是奥威BI上的一个特色功能板块。用户下载后更新数据源&#xff0c;立即就能获…

windows安装wsl2以及ubuntu

查看自己系统的版本 必须运行 Windows 10 版本 2004 及更高版本&#xff08;内部版本 19041 及更高版本&#xff09;或 Windows 11 才能使用以下命令 在设置&#xff0c;系统里面就能看到 开启windows功能 直接winQ搜 开启hyber-V、使用于Linux的Windows子系统、虚拟机平…

群晖7.2版本安装CloudDriver2(套件)挂载alist(xiaoya)到本地

CloudDrive是一个强大的多云盘管理工具&#xff0c;为用户提供包含云盘本地挂载的一站式的多云盘解决方案。挂载到本地后&#xff0c;可以像本地文件一样进行操作。 一、套件库添加矿神源 二、安装CloudDriver2 1、搜索安装 搜索框输入【clouddrive】&#xff0c;搜索到Clou…

获取文章分类详情

CategoryController GetMapping("/detail")public Result<Category> detail(Integer id){Category c categoryService.findById(id);return Result.success(c);} CategoryService //根据id查询分类信息Category findById(Integer id); CategoryServiceImpl …

山西电力市场日前价格预测【2023-11-20】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-20&#xff09;山西电力市场全天平均日前电价为255.39元/MWh。其中&#xff0c;最高日前电价为436.50元/MWh&#xff0c;预计出现在18:00。最低日前电价为21.61元/MWh&#xff0c;预计出…

【DevOps】Git 图文详解(三):常用的 Git GUI

Git 图文详解&#xff08;三&#xff09;&#xff1a;常用的 Git GUI 1.SourceTree2.TortoiseGit3.VSCode 中的 Git 如果不想用命令行工具&#xff0c;完全可以安装一个 Git 的 GUI 工具&#xff0c;用的更简单、更舒服。不用记那么多命令了&#xff0c;极易上手&#xff0c;不…

Rocket如何实现顺序消费

RocketMQ 支持两种消息模式 集群消费&#xff08; Clustering &#xff09;和广播消费&#xff08; Broadcasting &#xff09;。 集群消费&#xff1a;同一 Topic 下的一条消息只会被同一消费组中的一个消费者消费。也就是说&#xff0c;消息被负载均衡到了同一个消费组的多…

OpenCV技术应用(4)— 如何改变图像的透明度

前言&#xff1a;Hello大家好&#xff0c;我是小哥谈。本节课就手把手教你如何改变图像的透明度&#xff0c;希望大家学习之后能够有所收获~&#xff01;&#x1f308; 目录 &#x1f680;1.技术介绍 &#x1f680;2.实现代码 &#x1f680;1.技术介绍 改变图像透明度的实…