visual Studio MFC 平台实现拉普拉斯和拉普拉斯与直方图均衡化与中值滤波相结合实现比较

拉普拉斯变换的原理与应用

本文使用visual Studio MFC 平台实现图像增强中的拉普拉斯变换,同时拉普拉斯一般不会单独使用,与其他平滑操作相结合,本文使用了拉普拉斯与直方图均衡化以及与中值滤波相结合,也对三种方式进行了对比

关于基础工程的创建可以参考
01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线

02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边框三角形、渐变填充三角形、边框渐变的正方形与填充渐变的正方形实例
03-visual Studio MFC 平台实现图像增强中的线性变换(负变换)和非线性变换(对数与幂律)
04-MFC实现图像增强–分段式变换(灰度级切片,对比度拉伸,Bit-plane slicing)
05-visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波

文章目录

  • 拉普拉斯变换的原理与应用
    • 一、 拉普拉斯变换的原理
    • 二、 拉普拉斯实现
      • 2.1单独拉普拉斯实现代码
      • 单独拉普拉斯实现效果
      • 2.2 拉普拉斯与直方图均衡化相结合实现代码
      • 拉普拉斯与直方图均衡化相结合实现效果
      • 2.3 拉普拉斯与中值滤波相结合实现
      • 中值滤波与拉普拉斯相结合实现效果

一、 拉普拉斯变换的原理

拉普拉斯变换的原理如下:

拉普拉斯变换是图像处理中一种用于增强图像边缘的技术。它可以通过高通滤波来突出图像中的边缘特征。拉普拉斯变换的离散形式通常通过卷积运算实现。

  1. 离散拉普拉斯运算符: 在离散图像中,拉普拉斯运算符可以表示为:

∇ 2 f ( x , y ) = f ( x + 1 , y ) + f ( x − 1 , y ) + f ( x , y + 1 ) + f ( x , y − 1 ) − 4 f ( x , y ) \nabla^2 f(x, y) = f(x+1, y) + f(x-1, y) + f(x, y+1) + f(x, y-1) - 4f(x, y) 2f(x,y)=f(x+1,y)+f(x1,y)+f(x,y+1)+f(x,y1)4f(x,y)

其中, f ( x , y ) f(x, y) f(x,y) 是图像在位置 ( x , y ) (x, y) (x,y)处的灰度值。

对于离散图像,拉普拉斯变换可以使用以下的卷积核来实现:

  0  -1   0
 -1   4  -1
  0  -1   0

这个卷积核对图像进行卷积运算,计算每个像素与其周围像素的差异,从而强调了图像中的边缘。在卷积运算中,将卷积核与图像的每个像素进行乘法,然后将结果相加。这个过程在整个图像上进行,产生一个新的图像,其中强调了边缘。
2. 连续拉普拉斯运算符: 在连续图像中,拉普拉斯运算符可以表示为:

∇ 2 f ( x , y ) = ∂ 2 f ∂ x 2 + ∂ 2 f ∂ y 2 \nabla^2 f(x, y) = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2} 2f(x,y)=x22f+y22f

它表示图像中各个点的强度与其周围点的强度之差的二阶导数。

  1. 应用: 对图像应用拉普拉斯变换将突出显示图像中的边缘和细节,因为这些区域通常具有灰度变化。拉普拉斯变换后的图像可以通过以下公式得到:

LaplacianImage = OriginalImage − SmoothedImage \text{LaplacianImage} = \text{OriginalImage} - \text{SmoothedImage} LaplacianImage=OriginalImageSmoothedImage

这里, SmoothedImage \text{SmoothedImage} SmoothedImage 是原始图像经过平滑处理(如高斯模糊)后的图像。
在实际应用中,拉普拉斯变换通常用于边缘检测或图像锐化。然而,由于它对噪声敏感,常常需要与其他技术一起使用,例如高斯滤波,以减小噪声的影响。

在数字图像处理中,通常使用卷积操作来实现拉普拉斯变换。卷积核的选择影响着变换的效果。拉普拉斯变换对于边缘检测和图像增强等任务非常有用。

二、 拉普拉斯实现

2.1单独拉普拉斯实现代码

 // 定义拉普拉斯核
 int laplacianKernel[3][3] = {
  { -1, -1, -1 },
  { -1,  8, -1 },
  { -1, -1, -1 }
 };

 // 应用卷积运算
 for (int y = 1; y < bmpHeight - 1; ++y) {
  for (int x = 1; x < bmpWidth - 1; ++x) {
   int sum = 0;
   for (int i = -1; i <= 1; ++i) {
    for (int j = -1; j <= 1; ++j) {
     sum += laplacianKernel[i + 1][j + 1] * gray_data[(y + i) * bmpWidth + (x + j)];
    }
   }
   laplacian_data[y * bmpWidth + x] = static_cast<unsigned char>(sum);
  }
 }
 CClientDC dc(this);
 CDC* pDC = &dc;
 
 m_pBmp->drawGrayBmp(pDC, laplacian_data, bmpWidth, bmpHeight, offset_left, offset_top +4 * bmpHeight+30);

 // 释放临时数组内存
 delete[] laplacian_data;

单独拉普拉斯实现效果

在这里插入图片描述

2.2 拉普拉斯与直方图均衡化相结合实现代码

// 计算直方图
int histogram[256] = { 0 };
for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
 histogram[gray_data[i]]++;
}

// 计算累积分布函数(CDF)
int cdf[256] = { 0 };
cdf[0] = histogram[0];
for (int i = 1; i < 256; ++i) {
 cdf[i] = cdf[i - 1] + histogram[i];
}

// 映射灰度级别到临时变量
unsigned char* temp_data = new unsigned char[bmpWidth * bmpHeight];
int min_cdf = cdf[0];
for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
 temp_data[i] = static_cast<unsigned char>(255 * (cdf[gray_data[i]] - min_cdf) / (bmpWidth * bmpHeight - min_cdf));
}

// 应用拉普拉斯变换
unsigned char* laplacian_data = new unsigned char[bmpWidth * bmpHeight];
int laplacianKernel[3][3] = {
 { -1, -1, -1 },
 { -1,  8, -1 },
 { -1, -1, -1 }
};
for (int y = 1; y < bmpHeight - 1; ++y) {
 for (int x = 1; x < bmpWidth - 1; ++x) {
  int sum = 0;
  for (int i = -1; i <= 1; ++i) {
   for (int j = -1; j <= 1; ++j) {
    sum += laplacianKernel[i + 1][j + 1] * temp_data[(y + i) * bmpWidth + (x + j)];
   }
  }
  laplacian_data[y * bmpWidth + x] = static_cast<unsigned char>(sum);
 }
}

// 绘制均衡化后的图像
//m_pBmp->drawGrayBmp(pDC, temp_data, bmpWidth, bmpHeight, offset_left + 900, offset_top);

// 绘制经拉普拉斯变换后的图像
m_pBmp->drawGrayBmp(pDC, laplacian_data, bmpWidth, bmpHeight, offset_left+bmpWidth, offset_top + 4* bmpHeight + 30);

拉普拉斯与直方图均衡化相结合实现效果

在这里插入图片描述

2.3 拉普拉斯与中值滤波相结合实现

// 中值滤波
for (int y = 1; y < bmpHeight - 1; ++y) {
 for (int x = 1; x < bmpWidth - 1; ++x) {
  // 获取3x3邻域内的像素值
  unsigned char neighborhood[9] = {
   gray_data[(y - 1) * bmpWidth + x - 1], gray_data[(y - 1) * bmpWidth + x], gray_data[(y - 1) * bmpWidth + x + 1],
   gray_data[y * bmpWidth + x - 1], gray_data[y * bmpWidth + x], gray_data[y * bmpWidth + x + 1],
   gray_data[(y + 1) * bmpWidth + x - 1], gray_data[(y + 1) * bmpWidth + x], gray_data[(y + 1) * bmpWidth + x + 1]
  };

  // 对邻域内像素值进行排序
  std::sort(neighborhood, neighborhood + 9);

  // 取中值作为当前像素值
  temp_data[y * bmpWidth + x] = neighborhood[4];
 }
}

// 拉普拉斯变换
int laplacianKernel[3][3] = {
 { -1, -1, -1 },
 { -1,  8, -1 },
 { -1, -1, -1 }
};

// 应用卷积运算
for (int y = 1; y < bmpHeight - 1; ++y) {
 for (int x = 1; x < bmpWidth - 1; ++x) {
  int sum = 0;
  for (int i = -1; i <= 1; ++i) {
   for (int j = -1; j <= 1; ++j) {
    sum += laplacianKernel[i + 1][j + 1] * temp_data[(y + i) * bmpWidth + (x + j)];
   }
  }
  median_laplacian_data[y * bmpWidth + x] = static_cast<unsigned char>(sum);
 }
}

CClientDC dc(this);
CDC* pDC = &dc;

// 显示结果
//m_pBmp->drawGrayBmp(pDC, temp_data, bmpWidth, bmpHeight, offset_left, offset_top);
m_pBmp->drawGrayBmp(pDC, median_laplacian_data, bmpWidth, bmpHeight, offset_left + 2*bmpWidth, offset_top + 4 * bmpHeight + 30);

中值滤波与拉普拉斯相结合实现效果

在这里插入图片描述

可以观看出在添加一些平滑操作后,与单独进行拉普拉斯变换还是有一些区别的,当然最后实现的效果可以调节拉普拉斯算子进行调节,以达到相应的效果。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MIT6S081-Lab2总结

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/xjintong。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 Lab2就是了解一下xv6的系统调用流程&…

Python 进阶(十三):JSON 序列化和反序列化(json 模块)

大家好&#xff0c;我是水滴~~ 本篇文章主要介绍json模块的功能&#xff0c;包括将Python对象序列化到文件、将Python对象序列化为字符串、序列化时类型的对照表、将文件中JSON数据反序列化为Python对象&#xff0c;将JSON字符串反序列化为Python对象、反序列化时类型的对照表…

Kafka使用指南

Kafka简介架构设计Kafka的架构设计关键概念Kafka的架构设计关键机制 Partition介绍Partition工作机制 应用场景ACK机制介绍ACK机制原理ACK机制对性能的影响ACK控制粒度Kafka分区数对集群性能影响调整分区优化集群性能拓展Kafka数据全局有序 Kafka简介 Kafka是由Apache软件基金…

Spring Boot学习随笔-SpringBoot的引言,回顾传统SSM开发

学习视频&#xff1a;【编程不良人】2021年SpringBoot最新最全教程 第一章、传统SSM开发回顾以及问题 Spring SpringMVC Mybatis SSM 实现一个简单功能 员工添加、查询… SSM项目简单实现 项目 需求分析 —>概要设计 —>&#xff08;库表设计&#xff09; —> 详细…

Linux进程解析(冯诺依曼体系结构,操作系统,进程初步解析)

冯诺依曼体系结构&#xff1a; 我们常见的计算机&#xff0c;如笔记本。我们常见的计算机&#xff0c;服务器&#xff0c;大部分都遵守冯诺依曼体系。 截至目前&#xff0c;我们所认识的计算机&#xff0c;都是有一个个的硬件组件组成&#xff1a; 中央处理器(CPU)&am…

MIT6.5840-2023-Lab1: MapReduce

前置知识 MapReduce&#xff1a;Master 将一个 Map 任务或 Reduce 任务分配给一个空闲的 worker。 Map阶段&#xff1a;被分配了 map 任务的 worker 程序读取相关的输入数据片段&#xff0c;生成并输出中间 k/v 对&#xff0c;并缓存在内存中。 Reduce阶段&#xff1a;所有 ma…

Linux socket编程(12):Unix套接字之socketpair、sendmsg和recvmsg详解

在上一篇文章Unix套接字编程及通信例子中&#xff0c;我们对Unix套接字编程有一个基本的了解。但在Unix套接字编程的领域中&#xff0c;有一组特殊而强大的工具&#xff1a;socketpair、sendmsg 和 recvmsg&#xff0c;它们为实现本地进程间通信提供了便捷的方式。 文章目录 1 …

python二维数组创建赋值问题:更改单个值却更改了所有项的值

test_list [] dic1 {} test_list [dic1 for _ in range(3)] ll [1, 2, 3]for i in range(3):test_list[i][value] ll[i]print(test_list)运行结果&#xff1a;每次赋值都更改了所有项 原因&#xff1a;python的二位数据创建方式就是这样&#xff0c;官方文档中有描述Wha…

大话数据结构-查找-线性索引查找

注&#xff1a;本文同步发布于稀土掘金。 4 线性索引查找 4.1 概述 索引就是把一个关键字与它对应的记录相关联的过程&#xff0c;一个索引由若干个索引项构成&#xff0c;每个索引项至少应包含关键字和其对应的记录在存储器中的位置等信息。 索引按照结构可分为线性索引、树…

【SpringBoot】在SpringBoot中配置序列化的Redis

文章目录 前言展示包结构在SpringBoot中配置Redis测试总结 前言 在使用Java操作Redis时&#xff0c;如果不对Redis进行序列化操作&#xff0c;可能会导致存储的key和value与原来的数据不一致的问题 本文也借此机会来详细讲解一下SpringBoot中配置序列化Redis的步骤 展示包结构 …

AI助力智慧农业,基于YOLOv7【tiny/yolov7/yolov7x】开发构建不同参数量级农田场景下庄稼作物、杂草智能检测识别系统

智慧农业随着数字化信息化浪潮的演变有了新的定义&#xff0c;在前面的系列博文中&#xff0c;我们从一些现实世界里面的所见所想所感进行了很多对应的实践&#xff0c;感兴趣的话可以自行移步阅读即可&#xff1a; 《自建数据集&#xff0c;基于YOLOv7开发构建农田场景下杂草…

绘图 Seaborn 10个示例

绘图 Seaborn 是什么安装使用显示中文及负号散点图箱线图小提琴图堆叠柱状图分面绘图分类散点图热力图成对关系图线图直方图 是什么 Seaborn 是一个Python数据可视化库&#xff0c;它基于Matplotlib。Seaborn提供了高级的绘图接口&#xff0c;可以用来绘制各种统计图形&#xf…

nodejs+vue+微信小程序+python+PHP新闻发布系统的设计与实现-计算机毕业设计推荐

根据现实需要&#xff0c;此系统我们设计出一下功能&#xff0c;主要有以下功能模板。 &#xff08;1&#xff09;新闻发布系统前台&#xff1a;首页、时事新闻、公告资讯、个人中心。 &#xff08;2&#xff09;管理员功能&#xff1a;首页、个人中心、用户管理、新闻分类管理…

文本编辑软件:Ulysses mac介绍说明

Ulysses mac是面向 Mac、iPhone 和 iPad 的一站式写作环境。Ulysses 提供令人愉悦、专注的写作体验&#xff0c;加上高效文稿管理、无缝同步以及灵活导出。markdown 可以直接对于文本进行不同类型的分类、编辑&#xff0c;比如标题、注解、评论之类的内容。 Ulysses让注意力专…

rpm安装gitlab

1.rpm包下载 https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 2.进行安装 rpm -ivh gitlab-ce-15.9.7-ce.0.el7.x86_64.rpm --nodeps --force 3.配置访问地址 vim /etc/gitlab/gitlab.rb 4.重新加载配置以及重启服务 gitlab-ctl reconfiguregitlab-ctl resta…

Ubuntur编译ROS报错:error PCL requires C++14 or above

ubuntu20.04 编译ROS包 报错&#xff1a; error&#xff1a; PCL requires C14 or above&#xff1a; 修改Cmakelists.txt文件&#xff1a; set&#xff08;CMAKE_CXX_STANDARD 14&#xff09; 再次编译成功.

2023 IoTDB 用户大会成功举办,深入洞察工业互联网数据价值

2023 年 12 月 3 日&#xff0c;中国通信学会作为指导单位&#xff0c;Apache IoTDB Community、清华大学软件学院、中国通信学会开源技术委员会联合主办&#xff0c;“科创中国”开源产业科技服务团和天谋科技&#xff08;北京&#xff09;有限公司承办的 2023 IoTDB 用户大会…

AI 绘画 | Stable Diffusion 动漫人物真人化

前言 如何让一张动漫人物变成真实系列人物?Stable Diffusion WebUI五步即可实现。快来使用AI绘画打开异世界的大门吧!!! 动漫真人化 首先在图生图里上传一张二次元动漫人物图片,然后选择一个真实系人物画风的大模型,最后点击DeepBooru 反推,自动填充提示词,调整重绘…

【MySQL】:数据库基本认识

数据库基础 一.什么是数据库1.mysql是什么2.为什么要有数据库3.服务器&#xff0c;数据库&#xff0c;表关系4.Mysql架构5.SQL语句分类 二.存储引擎 一.什么是数据库 1.mysql是什么 1.mysql是数据库服务的客户端。 2.mysqld是数据库服务的服务器端。 3.mysql本质&#xff1a;基…

【Python】logging模块函数详解和示例

在Python中&#xff0c;LOGGER通常是指一个用于记录日志的模块或对象。它可以帮助你在程序中跟踪和记录事件&#xff0c;以便于调试、错误跟踪和日志分析。Python的标准库中包含了一个名为logging的模块&#xff0c;它提供了一个灵活且功能强大的日志记录系统。本文对相应的函数…