visual Studio MFC 平台实现图像增强中Gray-level slicing,Bit-plane slicing,对比度拉伸三种方法

MFC 实现图像增强–分段式变换

本文使用visual Studio MFC 平台实现图像增强中的第三大类分段式变换中的三种方法,包括Gray-level slicing,Bit-plane slicing,对比度拉伸.
关于其他MFC单文档工程可参考
01-Visual Studio 使用MFC 单文档工程绘制单一颜色直线和绘制渐变颜色的直线

02-visual Studio MFC 绘制单一颜色三角形、渐变颜色边框三角形、渐变填充三角形、边框渐变的正方形与填充渐变的正方形实例
03-visual Studio MFC 平台实现对灰度图添加椒盐噪声,并进行均值滤波与中值滤波

文章目录

  • MFC 实现图像增强--分段式变换
    • 一、 Gray-level slicing 灰度级别切片
      • 1.1 灰度级别切片的原理
      • 1.2 灰度级别切片的代码实现
      • 1.3 实现效果
    • 二、 Bit-plane slicing
      • 2.1 Bit-plane slicing 原理
      • 2.2 Bit-plane slicing代码实现
      • 2.3 实现效果
    • 三、 对比度拉伸
      • 3.1 对比度拉伸的原理
      • 3.2 对比度拉伸代码实现
      • 3.3 对比度拉伸的实现图

一、 Gray-level slicing 灰度级别切片

1.1 灰度级别切片的原理

灰度级别切片(Gray-level Slicing)是一种图像处理技术,其目标是增强或突出显示特定灰度范围内的像素值。这通常用于突出感兴趣的目标或特定区域,并抑制其他区域的细节。

以下是灰度级别切片的基本原理:

  1. 选择灰度范围: 定义一个或多个灰度范围,这些范围内的像素将被保留或增强,而其他像素将被抑制。

  2. 设置增强值: 对于选择的灰度范围内的像素,可以将它们的灰度值增强为更高的亮度值,以使其在最终图像中更为突出。

  3. 抑制其他灰度范围: 对于未选择的灰度范围,可以将它们的灰度值设置为较低的亮度值,从而降低它们在最终图像中的显著性。

  4. 生成增强后的图像: 根据上述操作生成最终的图像,其中特定灰度范围内的像素得到了增强,而其他像素则被抑制。

这种方法的应用场景包括:

  • 目标突出显示: 当你想突出显示图像中的某个特定区域或目标时,可以使用灰度级别切片来使该区域更为显著。

  • 降低背景噪声: 如果图像中存在噪声或其他不相关的信息,可以通过灰度级别切片来降低这些不相关信息的影响。

1.2 灰度级别切片的代码实现

void CMFCApplication1View::OnGrayLevelSlicing()
{
    if (gray_data != nullptr) {
        unsigned char* enhanced_data = new unsigned char[bmpWidth * bmpHeight];
        int lower_threshold = 100;  // 定义下限阈值
        int upper_threshold = 200;  // 定义上限阈值

        for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
            if (gray_data[i] >= lower_threshold && gray_data[i] <= upper_threshold) {
                // 在选择的灰度范围内增强像素值
                enhanced_data[i] = 255;
            } else {
                // 在其他范围内抑制像素值
                enhanced_data[i] = 0;
            }
        }

        // 获取绘图设备
        CClientDC dc(this);
        CDC* pDC = &dc;

        // 绘制增强后的灰度图
        m_pBmp->drawGrayBmp(pDC, enhanced_data, bmpWidth, bmpHeight, offset_left + 1100, offset_top);

        // 在图片下方添加文字
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
        {
            Graphics graphics(pDC->m_hDC);
            Gdiplus::Font font(L"Arial", 12);
            SolidBrush brush(Color(255, 128, 0, 128));  // 文字颜色为紫色

            // 文字的位置
            PointF point(offset_left + 1100, offset_top + bmpHeight + 10);

            // 绘制文字
            graphics.DrawString(L"灰度级别切片", -1, &font, point, &brush);
        }
        GdiplusShutdown(gdiplusToken);

        // 释放内存
        delete[] enhanced_data;
    } else {
        // 处理图像未加载的情况
        AfxMessageBox(_T("未加载图片"));
    }
}

上述代码将在图像中选择一个灰度范围进行增强,并在最终图像中突出显示该范围。

1.3 实现效果

在这里插入图片描述

二、 Bit-plane slicing

2.1 Bit-plane slicing 原理

Bit-plane slicing 是一种图像处理技术,它将图像的每个像素的二进制表示按位切割,然后将每个位平面(bit plane)单独显示。这种技术可以用于分析和可视化图像的信息,从而更好地理解图像的结构和特征。

以下是 Bit-plane slicing 的基本原理:

  1. 二进制表示: 对于每个像素,将其灰度值转换为二进制表示。例如,8 位灰度图像的像素值在二进制中有 8 位。

  2. 按位切割: 对每个像素的二进制表示,将其按位进行切割。例如,一个像素的 8 位二进制表示可以分为 8 个位平面,每个平面代表一个二进制位。

  3. 单独显示: 将切割得到的每个位平面单独显示。这意味着显示第一位平面、第二位平面,以此类推。

  4. 可视化: 通过观察每个位平面的图像,可以更好地理解图像的结构和像素之间的关系。低位平面通常包含图像的全局信息,而高位平面包含更多的细节信息。

  5. 合成: 可以选择将其中一些位平面重新合成为新的图像,以突出显示某些特定特征或信息。

Bit-plane slicing 主要用于图像分析、图像压缩和图像增强。在分析中,它可以帮助识别图像中的模式和结构。在压缩中,某些位平面可以舍弃以减小图像的大小。在增强中,选择特定位平面可以突出显示某些特征。

2.2 Bit-plane slicing代码实现

void CMFCApplication1View::OnBitplaneSlicing()
{
    if (gray_data != nullptr) {
        // 获取绘图设备
        CClientDC dc(this);
        CDC* pDC = &dc;

        // 选择要显示的位平面,这里选择第 3 位平面(从右往左数)
        int bit_plane = 3;

        // 创建临时数组用于存储位平面数据
        unsigned char* bit_plane_data = new unsigned char[bmpWidth * bmpHeight];

        // 提取位平面数据
        for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
            bit_plane_data[i] = (gray_data[i] >> bit_plane) & 1;
        }

        // 缩放位平面数据以便显示
        int scale_factor = 255;
        for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
            bit_plane_data[i] *= scale_factor;
        }

        // 绘制位平面图像
        m_pBmp->drawGrayBmp(pDC, bit_plane_data, bmpWidth, bmpHeight, offset_left + 1300, offset_top);

        // 在图片下方添加文字
        GdiplusStartupInput gdiplusStartupInput;
        ULONG_PTR gdiplusToken;
        GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
        {
            Graphics graphics(pDC->m_hDC);
            Gdiplus::Font font(L"Arial", 12);
            SolidBrush brush(Color(255, 128, 0, 128));  // 文字颜色为紫色

            // 文字的位置
            PointF point(offset_left + 1300, offset_top + bmpHeight + 10);

            // 绘制文字
            CString text;
            text.Format(L"Bit-plane Slicing (Bit %d)", bit_plane);
            graphics.DrawString(text, -1, &font, point, &brush);
        }
        GdiplusShutdown(gdiplusToken);

        // 释放内存
        delete[] bit_plane_data;
    } else {
        // 处理图像未加载的情况
        AfxMessageBox(_T("未加载图片"));
    }
}

上述代码演示了如何选择特定位平面进行切割并显示。在示例中,选择了第 3 位平面,并在图像下方显示了相应的文字。请注意,位平面的选择从右向左进行,从 0 开始。

2.3 实现效果

 

三、 对比度拉伸

3.1 对比度拉伸的原理

图像的对比度拉伸是一种调整图像对比度的方法,其原理涉及到像素值的映射。对比度表示图像中不同亮度级别之间的差异程度。拉伸对比度的目的是增强图像中的亮度差异,使图像中的细节更加明显。

对比度拉伸的一般原理如下:

  1. 找到图像的最小和最大像素值: 遍历整个图像,找到最小和最大的像素值。

  2. 定义拉伸函数: 根据找到的最小和最大像素值,定义一个拉伸函数,将原始像素值映射到一个新的范围内。这个映射通常使用线性函数完成,将原始像素值拉伸到一个更广泛的范围。

    公式示例: 新像素值 = ( 原始像素值 − 最小值 最大值 − 最小值 ) × 新范围大小 \text{新像素值} = \left( \frac{\text{原始像素值} - \text{最小值}}{\text{最大值} - \text{最小值}} \right) \times \text{新范围大小} 新像素值=(最大值最小值原始像素值最小值)×新范围大小

  3. 应用拉伸函数: 将拉伸函数应用于整个图像,调整每个像素的值。这样,原始图像中的亮度差异将在新的范围内更为明显。

对比度拉伸常用于增强图像中的细节,特别是在图像中存在大量像素集中在低对比度范围内的情况。拉伸过程不改变图像的相对亮度顺序,只是将亮度范围映射到更广泛的范围,以便更好地显示图像的细节。

3.2 对比度拉伸代码实现

//对比度拉伸代码
void CMFCApplication1View::OnContraststretching()
{
 
 CClientDC dc(this);
 CDC* pDC = &dc;
 if (gray_data != nullptr) {
  // 寻找图像的最小和最大像素值
  unsigned int minPixelValue = gray_data[0];
  unsigned int maxPixelValue = gray_data[0];
  // 创建临时数组用于对比度拉伸处理
  unsigned char* temp_data = new unsigned char[bmpWidth * bmpHeight];
  for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
   if (gray_data[i] < minPixelValue) {
    minPixelValue = gray_data[i];
   }

   if (gray_data[i] > maxPixelValue) {
    maxPixelValue = gray_data[i];
   }
  }

  // 对比度拉伸的参数
  const int newMinPixelValue = 0;
  const int newMaxPixelValue = 255;

  // 应用对比度拉伸公式到每个像素
  for (int i = 0; i < bmpWidth * bmpHeight; ++i) {
   temp_data[i] = static_cast<unsigned char>(
    (gray_data[i] - minPixelValue) * (newMaxPixelValue - newMinPixelValue) /
    (maxPixelValue - minPixelValue) + newMinPixelValue);
  }

  // 绘制拉伸后的灰度图
  m_pBmp->drawGrayBmp(pDC, temp_data, bmpWidth, bmpHeight, offset_left + 450, offset_top);
  // 释放临时数组内存
  delete[] temp_data;
  // 更新视图,显示修改后的图像
  //Invalidate();
  // 在图片下方添加文字---只为方便查看
  GdiplusStartupInput gdiplusStartupInput;
  ULONG_PTR gdiplusToken;
  GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
  {
  Graphics graphics(pDC->m_hDC);
  Gdiplus::Font font(L"Arial", 12);
  SolidBrush brush(Color(255,128, 0, 128));  // 文字颜色为紫色

  // 文字的位置
  PointF point(offset_left + 450, offset_top + bmpHeight + 10);

  // 绘制文字
  graphics.DrawString(L"对比度拉伸后的图", -1, &font, point, &brush);
  }
  GdiplusShutdown(gdiplusToken);

 }
 else {
  // 处理图像未加载的情况
  AfxMessageBox(_T("未加载图片"));
  return;
 }
}

3.3 对比度拉伸的实现图

在这里插入图片描述

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

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

相关文章

android https 证书过期

有的时候 我们android https 证书过期 &#xff0c;或者使用明文等方式去访问服务器 可能会碰到类似的 问题 &#xff1a; javax.net.ssl.SSLHandshakeException: Chain validation failed java.security.cert.CertPathValidatorException: Response is unreliable: its validi…

JavaScript类型判断:解密变量真实身份的神奇技巧

文章目录 1. typeof运算符2. instanceof运算符3. Object.prototype.toString4. Array.isArray5. 使用constructor属性6. 使用Symbol.toStringTag7. 使用is类型判断库8. 谨慎使用隐式类型转换结语 &#x1f389;JavaScript类型判断&#xff1a;解密变量真实身份的神奇技巧 ☆* o…

OpenTSDB(CVE-202035476)漏洞复现及利用

任务一&#xff1a; 复现环境中的命令注入漏洞。 任务二&#xff1a; 利用命令注入执行whoami&#xff0c;使用DNS外带技术获取结果 任务三&#xff1a;使用反弹shell&#xff0c;将漏洞环境中的shell反弹到宿主机或者vps服务器。 任务一&#xff1a; 1.搭建好环境 2.先去了…

Amazon CTO Werner Vogels:2024年及未来四大技术趋势预测

纵观历史&#xff0c;人类已经开发出各种工具和系统来增强自身能力。无论是印刷机还是装配线&#xff0c;这些创新拓宽了我们的能力范围&#xff0c;造就新的工作和职业&#xff0c;我们也不断适应着新生活。这种变化的速度在过去的一年里迅速加快&#xff0c;云技术、机器学习…

整体迁移SVN仓库到新的windows服务器

一、背景 公司原有的SVN服务器年代比较久远经常出现重启情况&#xff0c;需要把SVN仓库重新迁移到新的服务器上&#xff0c;在网上也搜到过拷贝Repositories文件直接在新服务器覆盖的迁移方案&#xff0c;但考虑到原有的操作系统和现有的操作系统版本不一致&#xff0c;SVN版本…

Redis缓存——Spring Cache入门学习

Spring Cache 介绍 Spring Cache 是一个框架&#xff0c;实现了基于注解的缓存功能&#xff0c;只需要简单地加一个注解&#xff0c;就能实现缓存功能。 Spring Cache 提供了一层抽象&#xff0c;底层可以切换不同的缓存实现&#xff0c;例如&#xff1a; EHCacheCaffeineR…

springboot集成邮箱验证功能

准备工作 开启SMTP服务 前往你的邮箱网站&#xff0c;以网易邮箱为例&#xff0c;打开网易邮箱地址&#xff0c;登录你的邮箱&#xff0c;进入邮箱管理后台界面。点击“设置”》》“POP3/SMTP/IMAP”后&#xff0c;点击开启SMTP服务即可。 技术实现 Spring Boot 发送邮件验证…

java审计之java反序列化-CC链

介绍 序列化的本质是内存对象到数据流的一种转换&#xff0c;我们知道内存中的东西不具备持久性&#xff0c;但有些场景却需要将对象持久化保存或传输。 在Java工程中&#xff0c;序列化还广泛应用于JMX&#xff0c;RMI&#xff0c;网络传输&#xff08;协议包对象&#xff09…

vivado实现分析与收敛技巧4

执行建议 满足以下条件时 &#xff0c; 在建议运行轮次期间执行建议 &#xff1a; • 这些建议处于已启用 (ENABLED) 状态。 • 必须运行 APPLICABLE_FOR 阶段。 • 这些建议必须设置为 AUTO 。 执行建议时 &#xff0c; APPLIED 设置将会更新 &#xff0c; 如下图所示…

vue3动态加载音频文件,用于不同场景加载不同的文件

本文主要介绍如何在vue3中动态加载音频文件。 目录 前言静态加载动态加载import函数watch函数使用watch函数和import函数动态加载音频文件 前言 在vue3中&#xff0c;我们通常使用import xxx from xxxxxx来加载文件&#xff0c;但是如果我们需要加载哪些文件&#xff0c;是需要…

java数据结构(哈希表—HashMap)含LeetCode例题讲解

目录 1、HashMap的基本方法 1.1、基础方法&#xff08;增删改查&#xff09; 1.2、其他方法 2、HashMap的相关例题 2.1、题目介绍 2.2、解题 2.2.1、解题思路 2.2.2、解题图解 2.3、解题代码 1、HashMap的基本方法 HashMap 是一个散列表&#xff0c;它存储的内容是键…

Peter算法小课堂—差分与前缀和

差分 Codeforces802 D2C C代码详解 差分_哔哩哔哩_bilibili 一维差分 差分与前缀和可以说成减法和加法的关系、除法和乘法的关系、积分和微分的关系&#xff08;听不懂吧&#xff09; 给定数组A&#xff0c;S为A的前缀和数组&#xff0c;则A为S的差分数组 差分数组构造 现…

电子学会C/C++编程等级考试2021年06月(四级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:数字三角形问题 (图1) 图1给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。 注意:路径上的每一步只能从一个数走到下一层上和它…

Android Studio新版UI介绍

顶部菜单栏 左侧主要菜单入口项目名称分支名称 展开之后&#xff0c;主要功能与原来菜单栏功能一样&#xff0c;最大的变化就是把setting独立出去了。 而项目名称这里&#xff0c;展开就可以看到打开的历史工程列表&#xff0c;可以直接新建工程&#xff0c;原来需要在项目名称…

vivado实现分析与收敛技巧3-面向非工程用户的智能设计运行建议

要使用智能设计运行功能特性 &#xff0c; 需要 Vivado 工程。这是因为需要进行运行管理。以下指示信息解释了创建综合后工程的最简单方法。这些信息适用于以下流程的用户&#xff1a; • 非工程实现运行 • 使用较低版本的 Vivado 或第三方综合工具进行综合 访问智能设计…

Git——分支应用进阶

主要内容包括以下几个方面&#xff1a; 长期分支和短期分支的类型以及用途。多种分支模型&#xff0c;其中包括基于工作流的主题分支。不同分支模型的发布流程。在多个预览版程序中使用分支修复安全问题。远程跟踪分支和refspecs规范&#xff0c;以及默认远程版本库配置。拉取…

测评补单助力亚马逊,速卖通,国际站卖家抢占市场,提升转化和评分

想要快速提升商品的销量&#xff0c;测评补单这种方法见效是最快的。特别是新品上线&#xff0c;缺少用户评价&#xff0c;转化率不好&#xff0c;很多商家新品上线都会做测评补单&#xff0c;搞些商品好评&#xff0c;不但可以提升转化&#xff0c;同时在平台也可以获得更多展…

Redis:主从复制

目录 概念配置步骤通过命令配置主从复制原理薪火相传反客为主哨兵(Sentinel)模式原理配置SpringBoot整合Sentinel模式 概念 主机更新后根据配置和策略&#xff0c;自动同步到备机的master/slave机制&#xff0c;Master以写为主&#xff0c;Slave以读为主。 作用&#xff1a; …

Python+Requests模块添加cookie

请求中添加cookies 对于某些网站&#xff0c;登录然后从浏览器中获取cookies&#xff0c;以后就可以直接拿着cookie登录了&#xff0c;无需输入用户 名密码。 一、在参数中添加cookie 在发送请求时使用cookies 代码示例&#xff1a; import requests # 1&#xff0c;在参数…

ZFPlayer 在tableView列表中播放视频架构设计

需求背景 需要在如图所示的列表中播放视频&#xff0c;并且播放视频在对应的卡片上&#xff0c;滚动结束的时候&#xff0c; 完整露出封面图的第一个视频自动播放 分析 根据需求&#xff0c;是滚动的时候获取符合条件的cell&#xff0c;并且 在cell的封面图上播放视频&#x…