使用VC++设计程序对一幅256级灰度图像进行全局固定阈值分割、自适应阈值分割
图像分割–全局固定阈值分割、自适应阈值分割
获取源工程可访问gitee可在此工程的基础上进行学习。
该工程的其他文章:
01- 一元熵值、二维熵值
02- 图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转
03-邻域平均平滑算法、中值滤波算法、K近邻均值滤波器
04-分段线性变换,直方图均衡化、锐化处理
05-基于拉普拉斯算子、Canny的边缘检测功能、实现Otsu分割方法
06-最近邻插值,双线性插值,立方卷积插值
文章目录
- 图像分割--全局固定阈值分割、自适应阈值分割
- 实验内容
- 一、全局固定阈值分割
- 全局固定阈值分割的原理
- 全局固定阈值分割的实验代码
- 全局固定阈值分割的实验现象
- 二、自适应阈值分割
- 自适应阈值分割的实验原理
- 自适应阈值分割的实验代码
- 自适应阈值分割的实验现象
实验内容
实验目的:
(1)掌握图像分割的原理与相关方法。
(2)能使用VC++开发一些图像分割方法。
实验要求:
A部分:
(1)使用VC++设计程序:对一幅256级灰度图像,进行全局固定阈值分割。
(2)使用VC++设计程序:对一幅256级灰度图像,进行自适应阈值分割。
一、全局固定阈值分割
全局固定阈值分割的原理
全局固定阈值分割是图像处理中一种简单而常用的图像分割方法,主要用于将图像中的目标与背景分开。该方法假设图像的目标和背景在灰度上有较大的差异,因此通过设定一个固定的阈值来将图像分割成两个部分。
具体步骤如下:
-
灰度图像转换: 如果图像不是灰度图像,首先将其转换为灰度图像。
-
选择阈值: 选择一个适当的阈值,该阈值将图像的灰度级别划分为两个部分,一部分属于目标,另一部分属于背景。阈值的选择通常基于图像的直方图分布以及应用场景。
-
分割图像: 将图像中每个像素的灰度值与选定的阈值进行比较,将灰度值大于阈值的像素归为一类,灰度值小于等于阈值的像素归为另一类。这样就得到了分割后的图像。
-
可选的后处理: 分割后的图像可能包含一些噪声或不连续的区域,因此可能需要进行一些后处理步骤,如去噪、连通性分析等。
-
应用领域: 全局固定阈值分割常用于具有清晰目标和背景对比度的图像,例如二值化处理、物体检测等。
虽然全局固定阈值分割简单易用,但对于光照不均匀、目标与背景差异不大的图像,效果可能不佳。在这种情况下,可能需要采用自适应阈值分割方法或其他更复杂的图像分割技术。
全局固定阈值分割的实验代码
/*************************************************************************** \函数名称:* 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;}
}
全局固定阈值分割的实验现象

二、自适应阈值分割
自适应阈值分割的实验原理
自适应阈值分割是一种根据图像局部特性确定阈值的方法,通常用于解决图像中灰度变化较大的情况。自适应阈值分割方法考虑图像中不同区域的灰度分布差异,根据局部信息确定每个像素的阈值。
以下是一些常见的自适应阈值分割方法:
-
局部均值法(Local Mean Method):
- 对于每个像素,使用其邻域的平均灰度值作为阈值。这样可以适应图像中灰度变化较慢的区域。
-
局部中值法(Local Median Method):
- 对于每个像素,使用其邻域的中值作为阈值。对于一些包含噪声的图像,中值法相对于均值法更具鲁棒性。
-
局部方差法(Local Variance Method):
- 使用每个像素邻域的灰度方差作为阈值。适用于图像中包含有纹理或细节的区域。
-
Sauvola’s Method:
- Sauvola提出的方法考虑了局部均值和局部方差,通过权衡这两个因素来确定阈值。适用于具有不同光照条件的图像。
-
Niblack’s Method:
- 类似于Sauvola的方法,Niblack提出的方法使用局部均值和标准差来确定阈值。适用于具有强烈光照变化的图像。
-
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] ;}}
}
自适应阈值分割的实验现象

相关文章:
使用VC++设计程序对一幅256级灰度图像进行全局固定阈值分割、自适应阈值分割
图像分割–全局固定阈值分割、自适应阈值分割 获取源工程可访问gitee可在此工程的基础上进行学习。 该工程的其他文章: 01- 一元熵值、二维熵值 02- 图像平移变换,图像缩放、图像裁剪、图像对角线镜像以及图像的旋转 03-邻域平均平滑算法、中值滤波算法、…...
【ArcGIS Pro微课1000例】0035:栅格影像拼接(dem高程数据)
本实验讲解在ArcGIS Pro中,栅格数据的两种拼接(镶嵌)方法,适用于遥感影像、DOM、DEM、DSM等常见栅格数据。 文章目录 一、加载实验数据二、栅格拼接工具1. 镶嵌2. 镶嵌至新栅格三、注意事项四、拓展阅读一、加载实验数据 加载配套实验数据中的0035.rar中的两个dem数据,如…...
Zynq-7000系列FPGA使用 Video Processing Subsystem 实现图像缩放,提供工程源码和技术支持
目录 1、前言免责声明 2、相关方案推荐FPGA图像处理方案FPGA图像缩放方案自己写的HLS图像缩放方案 3、设计思路详解Video Processing Subsystem 介绍 4、工程代码详解PL 端 FPGA 逻辑设计PS 端 SDK 软件设计 5、工程移植说明vivado版本不一致处理FPGA型号不一致处理其他注意事项…...
【C】内存函数
目录 1. memcpy 使用和模拟实现 2. memmove 使⽤和模拟实现 3. memset 函数的使用 4. memcmp 函数的使用 1. memcpy 使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数memcpy从source的位置开始向后复制num个字节的数据到d…...
windows系统玩游戏找不到d3dx9_35.dll缺失的解决方法
分享一个我们在打开游戏或许软件过程中遇到的问题——“由于找不到d3dx9_35.dll,无法继续执行代码”的五个修复方案。这个问题可能会影响到我们的工作和娱乐效率,甚至可能导致工作的延期。因此,我希望通过今天的文章,能够帮助大家更好地解决这…...
webshell之内置函数免杀
原始webshell 查杀的点在于Runtime.getRuntime().exec非常明显的特征 利用ProcessBuilder替换Runtime.getRuntime().exec(cmd) Runtime.getRuntime().exec(cmd)其实最终调用的是ProcessBuilder这个函数,因此我们可以直接利用ProcessBuilder来替换Runtime.getRunti…...
react高阶成分(HOC)
使用React函数式组件写了一个身份验证的一个功能,示例通过高阶组件实现的一个效果展示: import React, { useState, useEffect } from react;// 定义一个高阶组件,它接受一个组件作为输入,并返回一个新的包装组件 const withAuth…...
<JavaEE> Thread线程类 和 Thread的常用方法
目录 一、Thread概述 二、构造方法 三、常用方法 1.1 getId()、getName()、getState()、getPririty() 1.2 start() 1.3 isDaemon()、setDaemon() 1.4 isAlive() 1.5 currentThread() 1.6 Interrupt()、interrupted()、isInterrupted() 1.6.1 方法一:添加共…...
Linux加强篇004-Vim编辑器与Shell命令脚本
目录 前言 1. Vim文本编辑器 1.1 编写简单文档 1.2 配置主机名称 1.3 配置网卡信息 1.4 配置软件仓库 2. 编写Shell脚本 2.1 编写简单的脚本 2.2 接收用户的参数 2.3 判断用户的参数 3. 流程控制语句 3.1 if条件测试语句 3.2 for条件循环语句 3.3 while条件循环语…...
【shell脚本】常见的shell脚本面试题目
1、请用shell脚本for,while,until这三种方式写出输出1到100的所有偶数的方法。 sum=0;for((i=0;i<=100;i+=2));do let sum+=i;done;echo $sum sum=0;i=0;while [ $i -le 100 ];do let sum+=i;let i+=2;done;echo $sum sum=0;i=0;until [ $i -gt 100 ];do let sum+=i;let i+…...
Android设计模式--外观模式
弈之为术,在人自悟 一,定义 外观模式要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。提供一个高层次的接口,使得子系统更易于使用。 外观模式在开发中的使用频率是非常高的,尤其是在第三方的SDK里面࿰…...
03_MySQL基本SQL语句讲解
#课程目标 能够创建、删除数据表能够对表里的数据记录进行增加、删除、修改、查询操作能够创建、删除用户能够给用户授权并回收权限了解delete和truncate语句的区别 #一、数据库基本操作 ##1、查看数据库相关信息 mysql> show databases; 查看所有数据库 mysql>…...
【C语法学习】28 - 字符测试函数
文章目录 1 isalnum()函数2 isalpha()函数3 islower()函数4 isupper()函数5 isdigit()函数6 isxdigit()函数7 iscntrl()函数8 isgraph()函数9 isspace()函数10 isblank()函数11 isprint()函数12 ispunct()函数13 tolower()函数14 toupper()函数 1 isalnum()函数 isalnum()函数…...
极兔快递查询,极兔快递单号查询,对需要的单号记录进行备注
批量查询极兔快递单号的物流信息,对需要的快递单号记录进行备注。 所需工具: 一个【快递批量查询高手】软件 极兔快递单号若干 操作步骤: 步骤1:运行【快递批量查询高手】软件,并登录 步骤2:点击主界面左…...
树的序列化与反序列化
1 序列化与反序列化 二叉树的序列化与反序列化 1.1 实现思路 方式一:前序遍历 通过前序遍历方式实现二叉树的序列化将结果存入队列中要注意空节点也要存null 方式二:层序遍历 层序遍历也是用队列实现注意从左到右,遇到空节点存null 1.2 …...
定长子网划分和变长子网划分问题_二叉树解法_通俗易懂_配考研真题
引入:定长子网划分和变长子网划分的基本概念 定长子网划分和变长子网划分的基本概念 目前常用的子网划分,是基于CIDR的子网划分,也就是将给定的CIDR地址块划分为若干个较小的CIDR地址块。 定长子网划分: 使用同一个子网掩码来划分子网,因…...
ruoyi 前后分离部署502
ruoyi 前后分离部署502 我使用了nginx部署前端,使用docker部署。nginx文件如下: server {listen 8086; #设置端口listen [::]:8086; #设置端口server_name localhost;#access_log /var/log/nginx/host.access.log main;location / {root /…...
【Python】多年数据分成不同sheet
需求: excel文件中包含多年数据,其中一列列名为“年”,要保存一个新excel,将年数值不同的行保存在不同的sheet文件中,每个sheet文件第一行仍为原数据第一行,并且每个sheet名为对应的年的值。 拆分年份数据…...
Cache学习(3):Cache地址映射(直接映射缓存组相连缓存全相连缓存)
1 Cache的与存储地址的映射 以一个Cache Size 为 128 Bytes 并且Cache Line是 16 Bytes的Cache为例。首先把这个Cache想象成一个数组,数组总共8个元素,每个元素大小是 16 Bytes,如下图: 现在考虑一个问题,CPU从0x0654…...
GIT | 基础操作 | 初始化 | 添加文件 | 修改文件 | 版本回退 | 撤销修改 | 删除文件
GIT | 基础操作 | 初始化 | 添加文件 | 修改文件 | 版本回退 | 撤销修改 | 删除文件 文章目录 GIT | 基础操作 | 初始化 | 添加文件 | 修改文件 | 版本回退 | 撤销修改 | 删除文件前言一、安装git二、git基本操作2.1 初始化git2.2 配置局部生效2.3 配置全局生效 三、认识工作区…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...
