使用VC++设计程序对一幅256级灰度图像进行全局固定阈值分割、自适应阈值分割

news2024/11/28 10:37:20

图像分割–全局固定阈值分割、自适应阈值分割

获取源工程可访问gitee可在此工程的基础上进行学习。
该工程的其他文章:
01- 一元熵值、二维熵值
02- 图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转
03-邻域平均平滑算法、中值滤波算法、K近邻均值滤波器
04-分段线性变换,直方图均衡化、锐化处理
05-基于拉普拉斯算子、Canny的边缘检测功能、实现Otsu分割方法
06-最近邻插值,双线性插值,立方卷积插值

文章目录

  • 图像分割--全局固定阈值分割、自适应阈值分割
    • 实验内容
    • 一、全局固定阈值分割
      • 全局固定阈值分割的原理
      • 全局固定阈值分割的实验代码
      • 全局固定阈值分割的实验现象
    • 二、自适应阈值分割
      • 自适应阈值分割的实验原理
      • 自适应阈值分割的实验代码
      • 自适应阈值分割的实验现象

实验内容

实验目的:
(1)掌握图像分割的原理与相关方法。
(2)能使用VC++开发一些图像分割方法。
实验要求:
A部分:
(1)使用VC++设计程序:对一幅256级灰度图像,进行全局固定阈值分割。
(2)使用VC++设计程序:对一幅256级灰度图像,进行自适应阈值分割。

一、全局固定阈值分割

全局固定阈值分割的原理

全局固定阈值分割是图像处理中一种简单而常用的图像分割方法,主要用于将图像中的目标与背景分开。该方法假设图像的目标和背景在灰度上有较大的差异,因此通过设定一个固定的阈值来将图像分割成两个部分。

具体步骤如下:

  1. 灰度图像转换: 如果图像不是灰度图像,首先将其转换为灰度图像。

  2. 选择阈值: 选择一个适当的阈值,该阈值将图像的灰度级别划分为两个部分,一部分属于目标,另一部分属于背景。阈值的选择通常基于图像的直方图分布以及应用场景。

  3. 分割图像: 将图像中每个像素的灰度值与选定的阈值进行比较,将灰度值大于阈值的像素归为一类,灰度值小于等于阈值的像素归为另一类。这样就得到了分割后的图像。

  4. 可选的后处理: 分割后的图像可能包含一些噪声或不连续的区域,因此可能需要进行一些后处理步骤,如去噪、连通性分析等。

  5. 应用领域: 全局固定阈值分割常用于具有清晰目标和背景对比度的图像,例如二值化处理、物体检测等。

虽然全局固定阈值分割简单易用,但对于光照不均匀、目标与背景差异不大的图像,效果可能不佳。在这种情况下,可能需要采用自适应阈值分割方法或其他更复杂的图像分割技术。

全局固定阈值分割的实验代码

/*************************************************************************
 *
 * \函数名称:
 *   RegionSegFixThreshold()
 *
 * \输入参数:
 *   CDib * pDib     - 指向CDib类的指针,含有原始图象信息
 *   int nThreshold     - 区域分割的阈值
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   1(逻辑)表示对应象素为前景区域,0表示背景
 *   阈值分割的关键问题在于阈值的选取。阈值的选取一般应该视实际的应用而
 *   灵活设定。
 *
 *************************************************************************
 */
void RegionSegFixThreshold(CDib * pDib, int nThreshold)
{
 //遍历图象的纵坐标
 int y;

 //遍历图象的横坐标
 int x;

 //图象的长宽大小
 CSize sizeImage  = pDib->GetDimensions();
 int nWidth   = sizeImage.cx  ;
 int nHeight   = sizeImage.cy  ;

 //图像在计算机在存储中的实际大小
 CSize sizeImageSave = pDib->GetDibSaveDim();

 //图像在内存中每一行象素占用的实际空间
 int nSaveWidth = sizeImageSave.cx;

 
 //图像数据的指针
 LPBYTE  pImageData = pDib->m_lpImage;

 for(y=0; y<nHeight ; y++ )
  for(x=0; x<nWidth ; x++ )
  {
   if( *(pImageData+y*nSaveWidth+x) < nThreshold)
    *(pImageData+y*nSaveWidth+x) = 0;
   else
    *(pImageData+y*nSaveWidth+x) = 255;
  }
}

全局固定阈值分割的实验现象

在这里插入图片描述

二、自适应阈值分割

自适应阈值分割的实验原理

自适应阈值分割是一种根据图像局部特性确定阈值的方法,通常用于解决图像中灰度变化较大的情况。自适应阈值分割方法考虑图像中不同区域的灰度分布差异,根据局部信息确定每个像素的阈值。

以下是一些常见的自适应阈值分割方法:

  1. 局部均值法(Local Mean Method):

    • 对于每个像素,使用其邻域的平均灰度值作为阈值。这样可以适应图像中灰度变化较慢的区域。
  2. 局部中值法(Local Median Method):

    • 对于每个像素,使用其邻域的中值作为阈值。对于一些包含噪声的图像,中值法相对于均值法更具鲁棒性。
  3. 局部方差法(Local Variance Method):

    • 使用每个像素邻域的灰度方差作为阈值。适用于图像中包含有纹理或细节的区域。
  4. Sauvola’s Method:

    • Sauvola提出的方法考虑了局部均值和局部方差,通过权衡这两个因素来确定阈值。适用于具有不同光照条件的图像。
  5. Niblack’s Method:

    • 类似于Sauvola的方法,Niblack提出的方法使用局部均值和标准差来确定阈值。适用于具有强烈光照变化的图像。
  6. Bernsen’s Method:

    • Bernsen的方法使用局部最大值和最小值之间的差异来确定阈值。对于具有大范围灰度变化的图像比较有效。

在实际应用中,选择合适的自适应阈值分割方法取决于图像的特性以及分割任务的要求。这些方法的性能会受到图像噪声、光照条件和目标特性等因素的影响。因此,需要根据具体情况进行调整和选择。

自适应阈值分割的实验代码

/*************************************************************************
 *
 * \函数名称:
 *   RegionSegAdaptive()
 *
 * \输入参数:
 *   CDib * pDib     - 指向CDib类的指针,含有原始图象信息
 *
 * \返回值:
 *   无
 *
 * \说明:
 *   1(逻辑)表示对应象素为前景区域,0表示背景
 *   阈值分割的关键问题在于阈值的选取。阈值的选取一般应该视实际的应用而
 *   灵活设定。本函数中,阈值不是固定的,而是根据图象象素的实际性质而设定的。
 *   这个函数把图像分成四个子图象,然后计算每个子图象的均值,根据均值设置阈值
 *   阈值只是应用在对应的子图象
 *
 *************************************************************************
 */
void RegionSegAdaptive(CDib * pDib)
{
 //遍历图象的纵坐标
 int y;

 //遍历图象的横坐标
 int x;

 //图象的长宽大小
 CSize sizeImage  = pDib->GetDimensions();
 int nWidth   = sizeImage.cx  ;
 int nHeight   = sizeImage.cy  ;

 //图像在计算机在存储中的实际大小
 CSize sizeImageSave = pDib->GetDibSaveDim();

 //图像在内存中每一行象素占用的实际空间
 int nSaveWidth = sizeImageSave.cx;

 //图像数据的指针
 LPBYTE  lpImage = pDib->m_lpImage;
 // 局部阈值
 int nThd[2][2] ;
 // 子图象的平均值
 int nLocAvg ;
 // 对左上图像逐点扫描:
 nLocAvg = 0 ;
 // y方向
 for(y=0; y<nHeight/2 ; y++ )
 {
  // x方向
  for(x=0; x<nWidth/2 ; x++ )
  {
   nLocAvg += lpImage[y*nSaveWidth + x];
  }
 }
 // 计算均值
 nLocAvg /= ( (nHeight/2) * (nWidth/2) ) ;
 // 设置阈值为子图象的平均值
 nThd[0][0] = nLocAvg ;

 // 对左上图像逐点扫描进行分割:
 // y方向
 for(y=0; y<nHeight/2 ; y++ )
 {
  // x方向
  for(x=0; x<nWidth/2 ; x++ )
  {
   if(lpImage[y*nSaveWidth + x]<nThd[0][0])
    lpImage[y*nSaveWidth + x] = 255 ;
   else
   {
    lpImage[y*nSaveWidth + x] = 0 ;
   }
   
  }
 }
 // =============================================
 // 对左下图像逐点扫描:
 nLocAvg = 0 ;
 // y方向
 for(y=nHeight/2; y<nHeight ; y++ )
 {
  // x方向
  for(x=0; x<nWidth/2 ; x++ )
  {
   nLocAvg += lpImage[y*nSaveWidth + x];
  }
 }
 // 计算均值
 nLocAvg /= ( (nHeight - nHeight/2) * (nWidth/2) ) ;

 // 设置阈值为子图象的平均值
 nThd[1][0] = nLocAvg ;

 // 对左下图像逐点扫描进行分割:
 // y方向
 for(y=nHeight/2; y<nHeight ; y++ )
 {
  // x方向
  for(x=0; x<nWidth/2 ; x++ )
  {
   if(lpImage[y*nSaveWidth + x]<nThd[1][0])
    lpImage[y*nSaveWidth + x] = 255 ;
   else
   {
    lpImage[y*nSaveWidth + x] = 0 ;
   }
   
  }
 }
 // =============================================
 // 对右上图像逐点扫描:
 nLocAvg = 0 ;
 // y方向
 for(y=0; y<nHeight/2 ; y++ )
 {
  // x方向
  for(x=nWidth/2; x<nWidth ; x++ )
  {
   nLocAvg += lpImage[y*nSaveWidth + x];
  }
 }
 // 计算均值
 nLocAvg /= ( (nHeight/2) * (nWidth - nWidth/2) ) ;
 
 // 设置阈值为子图象的平均值
 nThd[0][1] = nLocAvg ;

 // 对右上图像逐点扫描进行分割:
 // y方向
 for(y=0; y<nHeight/2 ; y++ )
 {
  // x方向
  for(x=nWidth/2; x<nWidth ; x++ )
  {
   if(lpImage[y*nSaveWidth + x]<nThd[0][1])
    lpImage[y*nSaveWidth + x] = 255 ;
   else
   {
    lpImage[y*nSaveWidth + x] = 0 ;
   }
   
  }
 }
 // =============================================
 // 对右下图像逐点扫描:
 nLocAvg = 0 ;
 // y方向
 for(y=nHeight/2; y<nHeight ; y++ )
 {
  // x方向
  for(x=nWidth/2; x<nWidth ; x++ )
  {
   nLocAvg += lpImage[y*nSaveWidth + x];
  }
 }
 // 计算均值
 nLocAvg /= ( (nHeight - nHeight/2) * (nWidth - nWidth/2) ) ;

 // 设置阈值为子图象的平均值
 nThd[1][1] = nLocAvg ;

 // 对右下图像逐点扫描进行分割:
 // y方向
 for(y=nHeight/2; y<nHeight ; y++ )
 {
  // x方向
  for(x=nWidth/2; x<nWidth ; x++ )
  {
   if(lpImage[y*nSaveWidth + x]<nThd[1][1])
    lpImage[y*nSaveWidth + x] = 255 ;
   else
   {
    lpImage[y*nSaveWidth + x] = 0 ;
   }
  }
 }
 
 // 为了显示方便显示,逻辑1用黑色显示,逻辑0用白色显示
 for(y=0; y<nHeight ; y++ )
 {
  // x方向
  for(x=0; x<nWidth ; x++ )
  {
   lpImage[y*nSaveWidth + x] = 255 - lpImage[y*nSaveWidth + x] ;
  }
 }
}

自适应阈值分割的实验现象

在这里插入图片描述

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

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

相关文章

线性表,也是Java中数组的知识点!

线性表定义&#xff1a; 由n (n≥0)个数据特性相同的元素构成的有限序列称为线性表&#xff0c;(n0)的时候被称为空表。 线性表的顺序表示 线性表的顺序存储又被称为顺序表 优点 无需为表示表中元素之间的逻辑关系而增加额外的存储空间可以随意读取任意位置的元素 缺点 插入…

Autosar MCAL-RH850P1HC-MCAL配置环境搭建

文章目录 前言下载安装包软件安装安装SIP包安装MCAL文件配置工程配置生成代码测试静态代码路径总结前言 对于RH850P1HC,官网有免费的MCAL,但官网的MCAL没有CAN模块(原厂反馈为Bosch IP,CAN Driver他们没有),也没有FEE模块。如果需要,可以找第三方软件公司,如ETAS.虽然M…

机器学习:攻击方法FGSM系列

任务 FGSM I-FGSM MI-FGSM Ensemble Attack 攻击评价指标 准确率越低表明攻击越好 数据 预训练模型 BaseLine 实践

SpringBoot——LiteFlow引擎框架

优质博文&#xff1a;IT-BLOG-CN 一、LiteFlow 简介 LiteFlow是一个轻量且强大的国产规则引擎框架&#xff0c;可用于复杂的组件化业务的编排领域。帮助系统变得更加丝滑且灵活。利用LiteFlow&#xff0c;你可以将瀑布流式的代码&#xff0c;转变成以组件为核心概念的代码结构…

计算机组成原理-Cache的基本概念和原理

文章目录 存储系统存在的问题Cache的工作原理局部性原理性能分析例题界定何为局部部分问题总结 存储系统存在的问题 增加Cache层来缓和CPU和主存的工作速度矛盾 Cache的工作原理 启动某个程序后&#xff0c;将程序的代码从辅存中取出放入内存中&#xff0c;再从内存中将代码…

nginx反向代理解决跨域前端实践

需求实现 本地请求百度的一个搜索接口&#xff0c;用nginx代理解决跨域思路&#xff1a;前端和后端都用nginx代理到同一个地址8080&#xff0c;这样访问接口就不存在跨域限制 本地页面 查询一个百度搜索接口&#xff0c;运行在http://localhost:8035 index.js const path …

Kanna库代码示例

编写一个使用Kanna库的网络爬虫程序。以下是代码的详细解释&#xff1a; swift import Kanna // 创建一个对象 let proxy Proxy(host: ") // 创建一个Kanna对象 let kanna Kanna(proxy: proxy) // 创建一个请求对象 let request Request(url: "") // 使用…

AIGC ChatGPT4总结Linux Shell命令集合

在Linux中,Shell命令的数量非常庞大,因为Linux提供了各种各样的命令来处理系统任务。这些命令包括GNU核心工具集、系统命令、shell内置命令以及通过安装获得的第三方应用程序命令。以下是一些常见的Linux命令分类及其示例,但请注意,这不是一个全面的列表,因为列出所有命令…

typeof,instanceof

1.typeof typeof运算符返回的结果是以小写的字符串表示的变量的类型 2.instanceof instanceof运算符用于判断右边构造函数的原型对象是否在左边对象的原型链上 let arr[]let obj{}let datenew Dateconsole.log(arr instanceof Array)console.log(arr instanceof Object)conso…

算法竞赛备赛进阶之状态压缩训练

状态压缩 状态压缩DP是一种暴力的算法&#xff0c;它需要遍历每个状态&#xff0c;而每个状态是多个事件的集合。这种算法通常用于小规模问题的求解&#xff0c;因为它的复杂度是指数级别的。 状态压缩DP的两个基本特征包括问题的数据规模特别小&#xff0c;可以通过2的阶乘次…

显示器校准软件BetterDisplay Pro mac中文版介绍

BetterDisplay Pro mac是一款显示器校准软件&#xff0c;可以帮助用户调整显示器的颜色和亮度&#xff0c;以获得更加真实、清晰和舒适的视觉体验。 BetterDisplay Pro mac软件特点 - 显示器校准&#xff1a;可以根据不同的需求和环境条件调整显示器的颜色、亮度和对比度等参数…

Ansible的重用(include和import)

环境 管理节点&#xff1a;Ubuntu 22.04控制节点&#xff1a;CentOS 8Ansible&#xff1a;2.15.6 重用 Ansible提供四种可重用的工件&#xff1a; variable文件&#xff1a;只包含变量的文件task文件&#xff1a;只包含task的文件playbook&#xff1a;可包含play、变量、ta…

HTTP状态码:如何修复 404 Not Found错误?

互联网上各种类型的网站非常多&#xff0c;无论用户还是网站运营者不可避免的会遇到404 Not Found错误&#xff0c;如果遇到404错误&#xff0c;我们应该如何解决呢&#xff1f; 对于用户 检查拼写错误 如果您是遇到错误的用户&#xff0c;请仔细检查 URL 是否有任何拼写错误…

深入探索Linux文件系统:属性、路径与隐藏之谜

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Linux系统理论 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言&#x1f324;️文件的组成☁️文件属性☁️文件内容☁️注意事项 &#x1f324;️路…

JavaFX开发调用AWT创建系统托盘MenuItem菜单中文乱码

打开系统托盘MenuItem只能显示英文字符和中文显示方框 解决办法&#xff1a; 打开Edit Configurations… 选择Mofidy options 勾选Add VM options 在VM optios中填入以下代码 -Dfile.encodingGBK

【Docker】安装Redis 通俗易懂 亲测没有任何问题 只需三步

目录 1.配置redis.conf文件 2.下载镜像 3.运行容器 4.测试 1.配置redis.conf文件 以配置文件启动redis redis配置下载&#xff1a;Index of /releases/ 镜像最好和配置文件版本对应 避免一些不必要的错误 修改文件中以下配置项&#xff1a; 1.将bind 127.0.0.1 -::1注…

YOLOv8改进 | SAConv可切换空洞卷积(附修改后的C2f+Bottleneck)

论文地址&#xff1a;官方论文地址 代码地址&#xff1a;官方代码地址 一、本文介绍 本文给大家带来的改进机制是可切换的空洞卷积&#xff08;Switchable Atrous Convolution, SAC&#xff09;是一种创新的卷积网络机制&#xff0c;专为增强物体检测和分割任务中的特征提取而…

Flutter | TextField长按时选项菜单复制、粘贴显示为英文问题解决

Flutter | TextField长按时选项菜单复制、粘贴显示为英文问题解决 问题描述&#xff1a; 长按TextField后&#xff0c;显示剪切、复制等选项为英文&#xff0c;如下图所示&#xff0c;这是因为问未设置语言本地化&#xff0c;我们需要进行设置。 首先在pubspec.yaml加入以下依赖…

Dempster-Shafer(D-S)证据理论的基本定义和详细分析,优点,缺点,应用!!(系列1)

文章目录 前言一、D-S证据理论的应用&#xff1a;二、D-S证据理论的优点&#xff1a;三、D-S证据理论的缺陷&#xff1a;四、D-S组合规则&#xff1a;总结 前言 Dempster-Shafer&#xff08;D-S&#xff09;证据理论是一种不精确推理理论&#xff0c;也称为Dempster/Shafer证据…