matlab qtdecomp,Opencv图像识别从零到精通(25)------区域分裂与合并

区域分割一般认为有漫水填充,区域分裂与合并,分水岭,这篇是中间的区域分裂和合并。

区域分裂合并算法的基本思想是先确定一个分裂合并的准则,即区域特征一致性的测度,当图像中某个区域的特征不一致时就将该区域分裂成4个相等的子区域,当相邻的子区域满足一致性特征时则将它们合成一个大区域,直至所有区域不再满足分裂合并的条件为止.当分裂到不能再分的情况时,分裂结束,然后它将查找相邻区域有没有相似的特征,如果有就将相似区域进行合并,最后达到分割的作用。在一定程度上区域生长和区域分裂合并算法有异曲同工之妙,互相促进相辅相成的,区域分裂到极致就是分割成单一像素点,然后按照一定的测量准则进行合并,在一定程度上可以认为是单一像素点的区域生长方法。区域生长比区域分裂合并的方法节省了分裂的过程,而区域分裂合并的方法可以在较大的一个相似区域基础上再进行相似合并,而区域生长只能从单一像素点出发进行生长(合并)。

反复进行拆分和聚合以满足限制条件的算法。

令R表示整幅图像区域并选择一个谓词P。对R进行分割的一种方法是反复将分割得到的结果图像再次分为四个区域,直到对任何区域Ri,有P(Ri)=TRUE。这里是从整幅图像开始。如果P(R)=FALSE,就将图像分割为4个区域。对任何区域如果P的值是FALSE.就将这4个区域的每个区域再次分别分为4个区域,如此不断继续下去。这种特殊的分割技术用所谓的四叉树形式表示最为方便(就是说,每个非叶子节点正好有4个子树),这正如图10.42中说明的树那样。注意,树的根对应于整幅图像,每个节点对应于划分的子部分。此时,只有R4进行了进一步的再细分。

0_12763137789ok0.gif

如果只使用拆分,最后的分区可能会包含具有相同性质的相邻区域。这种缺陷可以通过进行拆分的同时也允许进行区域聚合来得到矫正。就是说,只有在P(Rj∪Rk)=TRUE时,两个相邻的区域Rj和Rk才能聚合。

前面的讨论可以总结为如下过程。在反复操作的每一步,我们需要做:

l.对于任何区域Ri,如果P(Ri)=FALSE,就将每个区域都拆分为4个相连的象限区域。

2.将P(Rj∪Rk)=TRUE的任意两个相邻区域Rj和Rk进行聚合。

3.当再无法进行聚合或拆分时操作停止。

可以对前面讲述的基本思想进行几种变化。例如,一种可能的变化是开始时将图像拆分为一组图象块。然后对每个块进一步进行上述拆分,但聚合操作开始时受只能将4个块并为一组的限制。这4个块是四叉树表示法中节点的后代且都满足谓词P。当不能再进行此类聚合时,这个过程终止于满足步骤2的最后的区域聚合。在这种情况下,聚合的区域可能会大小不同。这种方法的主要优点是对于拆分和聚合都使用同样的四叉树,直到聚合的最后一步。

例10.17拆分和聚合

图10.43(a)显示了一幅简单的图像。如果在区域Ri内至少有80%的像素具有zj-mi≤2σi的性质,就定义P(Ri)=TRUE,这里zj是Ri内第j个像素的灰度级,mi是区域Ri的灰度级均值,σi是区域Ri内的灰度级的标准差。如果在此条件下,P(Ri)=TRUE,则设置Ri内的所有像素的值等于mi。拆分和聚合使用前速算法的要点完成。将这种技术应用于图10.43(a)所得结果示于图10.43(b)。请注意,图像分割效果相当好。示于图10.43(c)中的图像是通过对图10.43(a)进行门限处理得到的,门限值选在直方图中两个主要的尖峰之间的中点。经过门限处理,图像中生成的阴影(和叶子的茎)被错误地消除了。

0_1276313783KA6R.gif

如前面的例子中所使用的属性那样,我们试图使用基于区域中像素的均值和标准差的某些特性对区域的纹理进行量化(见11.3.3节中关于纹理的讨论)。纹理分割的概念是以在谓词P(Ri)中使用有关纹理的量度为基础的。就是说,通过指定基于纹理内容的谓词,我们可以使用本节中讨论的任何方法进行纹理分割。

0_1276313792BScD.gif

1. 把一幅图像分成4份,计算每一份图像的最大灰度值与最小灰度值的差, 如果差在误差范围值外,则该份图像继续分裂。

2. 对于那些不需要分裂的那些份图像可以对其进行阈值切割了,例如某一块图像的最大灰度大于某个值,则该块图像变成255,否则变为0。

// 代码

// 区域分裂合并的图像分割

// nOffSetLne是行偏移量

// 由于分裂的层数太多了, 使用递归将使内存空间堆栈溢出

// 解决方法是使用一个堆栈对要分裂的块入栈

// 使用堆栈的方法类似在"区域生长"的实现方法

#include

struct SplitStruct

{

unsigned int nWidth; // 这一块图像的宽度

unsigned int nHeigh; // 这一块图像的高度

unsigned int nOffSetWidth; // 相对源图像数据的偏移宽度

unsigned int nOffSetHeigh; // 相对源图像数据的偏移高度

};

void AreaSplitCombineEx(BYTE* image0, // 源图像数据

unsigned int nAllWidth, // 源图像的宽度

unsigned int nAllHeigh, // 源图像的高度

unsigned int w, // 这一块图像的宽度

unsigned int h, // 这一块图像的高度

unsigned int nOffSetWidth, // 相对源图像数据的偏移宽度

unsigned int nOffSetHeigh) // 相对源图像数据的偏移高度

{

std::stack nMyStack;

SplitStruct splitStruct, splitStructTemp;

splitStruct.nWidth = w;

splitStruct.nHeigh = h;

splitStruct.nOffSetWidth = nOffSetWidth;

splitStruct.nOffSetHeigh = nOffSetHeigh;

nMyStack.push(splitStruct);

int i, j;

int nValueS[2][2]; // 用于存储块图像的属性值(该属性值= 该块图像的所有像素灰度值之和除以该块图像所有像素点的数量)

int nAV;

int nWidthTemp[3], nHeightTemp[3], nTemp;

int nWidth, nHeigh;

int n, m, l;

double dOver;

while(!nMyStack.empty())

{

splitStruct = nMyStack.top();

nMyStack.pop();

n = (splitStruct.nOffSetHeigh * nAllWidth + splitStruct.nOffSetWidth); // 该块图像的左上角

// 1. 把图像分成2 * 2 块,

nWidthTemp[0] = 0;

nWidthTemp[2] = (splitStruct.nWidth + 1) / 2;

nWidthTemp[1] = splitStruct.nWidth - nWidthTemp[2];

nHeightTemp[0] = 0;

nHeightTemp[2] = (splitStruct.nHeigh + 1) / 2;

nHeightTemp[1] = splitStruct.nHeigh - nHeightTemp[2];

// 计算每一块图像的属性值

int nValue;

int nValueTemp;

nAV = 0;

for(i = 1; i < 3; ++i)

{

for(j = 1; j < 3; ++j)

{

nValue = 0;

m = (n + nAllWidth * nHeightTemp[i - 1] + nWidthTemp[j - 1]);

for(nHeigh = 0; nHeigh < nHeightTemp[i]; ++nHeigh)

{

for(nWidth = 0; nWidth < nWidthTemp[j]; ++nWidth)

{

l = (m + nAllWidth * nHeigh + nWidth) * 4;

nValueTemp = (0.299 * image0[l] + 0.587 * image0[l + 1] + 0.114 * image0[l + 2]);

// 灰度值之和

nValue += nValueTemp;

}

}

if(nHeightTemp[i] * nWidthTemp[j] == 0)

{

continue;

}

if(nHeightTemp[i] * nWidthTemp[j] == 1)

{

l = m * 4;

if((0.299 * image0[l] + 0.587 * image0[l + 1] + 0.114 * image0[l + 2]) < 125)

// 这个值可以动态设定

{

image0[l] = image0[l + 1] = image0[l + 2] = 0;

image0[l + 3] = 255;

}

else

{

image0[l] = image0[l + 1] = image0[l + 2] = 255;

image0[l + 3] = 255;

}

continue;

}

// 各块图像的灰度平均值(每一块图像的属性值)

nValueS[i - 1][j - 1] = nValue / (nHeightTemp[i] * nWidthTemp[j]);

// 2. 对每一块进行判断是否继续分裂(注意分裂的原则)

// 我这里的分裂原则是: 图像的属性值在属性值平均值的误差范围之内就不分裂

if(nValueS[i - 1][j - 1] < 220) // 灰度平均值少于200 需要继续分裂 // 这里就是分裂准则了

{

splitStructTemp.nWidth = nWidthTemp[j];

splitStructTemp.nHeigh = nHeightTemp[i];

splitStructTemp.nOffSetWidth = splitStruct.nOffSetWidth + nWidthTemp[j - 1];

splitStructTemp.nOffSetHeigh = splitStruct.nOffSetHeigh + nHeightTemp[i - 1];

nMyStack.push(splitStructTemp);

}

else // 合并(直接填充该块图像为黑色)

{

// 3. 如果不需要分裂, 则进行合并

for(nHeigh = 0; nHeigh < nHeightTemp[i]; ++nHeigh)

{

for(nWidth = 0; nWidth < nWidthTemp[j]; ++nWidth)

{

l = (m + nAllWidth * nHeigh + nWidth) * 4;

image0[l] = image0[l + 1] = image0[l + 2] = 255;

image0[l + 3] = 255;

}

}

}

}

}

}

return;

}

该代码的效果也不是太好,主要是分裂准则不好确

区域分裂合并中 最初使用每块图像区域中极大与极小灰度值之差是否在允许的偏差范围来作为均匀性测试准则。 后来均匀性测试准则又被不断的发展。目前,统计检验,如均方误差最小, F检测等都是最常用的均匀性测试准侧方法

看均方误差最小的情况

a4e76b0b1287debfe8b238d1b188ce63.png

其中C是区域R中N个点的平均值。

相对于区域生长而言,区域分割于合并技术不再依赖于种子点的选择与生长顺序。但选用合适的均匀性测试准则P对于提高图像分割质量十分重要,当均匀性测试准则P选择不当时,很容易会引起“方块效应”

参考连接;http://blog.csdn.net/bagboy_taobao_com/article/details/5666109

MATLAB

matlab中给出了qtdecomp().qtsetblk(),下面看看效果

I = imread('liftingbody.png');

S = qtdecomp(I,.27);%以阈值ceil(0.27*255)=69对图像I进行四叉分解

blocks = repmat(uint8(0),size(S));%得到一个和I同尺寸的黑色背景blocks

for dim = [512 256 128 64 32 16 8 4 2 1]; %分块全是2的整数次幂,注①

numblocks = length(find(S==dim)); %有numblocks个尺寸为dim的分块,注③

if (numblocks > 0)

values = repmat(uint8(1),[dim dim numblocks]);%产生一个dim x dim x numblocks的三维1值矩阵(或说

% numblocks个尺寸为dim x dim的1值block)

values(2:dim,2:dim,:) = 0;

blocks = qtsetblk(blocks,S,dim,values);%blocks保存了所有块被替换后的结果。注④

end

end

blocks(end,1:end) = 1;

blocks(1:end,end) = 1;

imshow(I), figure, imshow(blocks,[])

69f3123daa9670c8b084176e1e58936a.png

图像识别算法交流 QQ群:145076161,欢迎图像识别与图像算法,共同学习与交流

原文:http://blog.csdn.net/qq_20823641/article/details/52191210

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

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

相关文章

去调频体制下的 rd算法_【技术文章】一次调频工作原理及控制 学习1+1

1、基本概念一次调频&#xff1a;PrimaryFrequencyControl。在电网实际运行中&#xff0c;当电量消耗与电量供给不匹配时&#xff0c;即可引起电网频率出现变化较小、变动周期较短的微小分量&#xff0c;这种频率扰动主要靠汽轮发电机组本身的调节系统直接自动调整汽轮机调门完…

蓝牙版本avrcp怎么选_500元内无线蓝牙耳机测评年轻人的第一款廉价蓝牙耳机怎么选?...

这是马克君的第 90 篇对比测评-建议佩戴耳机体验-?- 10款TWS耳机测评 -TWSTrue Wireless Stereo⇩真无线立体声自AirPods问世以来&#xff0c;真无线耳机的概念开始爆火?。虽然AirPods“真香”&#xff0c;但售价也是真滴贵&#xff0c;所以有没有便宜又好用的真无线蓝牙耳机…

数据库查询语句慢如何优化_常见Mysql的慢查询优化方式

1 概念 MySQL的慢查询&#xff0c;全名是慢查询日志&#xff0c;是MySQL提供的一种日志记录&#xff0c;用来记录在MySQL中响应时间超过阀值的语句。 具体环境中&#xff0c;运行时间超过long_query_time值的SQL语句&#xff0c;则会被记录到慢查询日志中。 long_query_time的默…

c++ 多重背包状态转移方程_Python|动态规划关于0-1背包问题

本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理以下文章来源于腾讯云&#xff0c;作者&#xff1a;算法与编程之美前言对学算法的同学来说&#xff0c;动态规划是其必学且较为重要的问题之一&#xff1b;…

element ui 多个子组件_vue前端UI框架,一点都不圆润,盘它!

面对众多vue前端UI框架&#xff0c;看着它们干干巴巴、麻麻赖赖的样子&#xff0c;一点都不圆润&#xff0c;跟我一起盘它&#xff01;Vue移动端UI框架1、Vux&#xff08;star:15620)VUX&#xff08;读音 [v’ju:z]&#xff0c;同 views&#xff09;是基于WeUI和Vue(2.x)开发的…

python 图像处理_Python中的十大图像处理工具

文章发布于公号【数智物语】 &#xff08;ID&#xff1a;decision_engine&#xff09;&#xff0c;关注公号不错过每一篇干货。来源 | 大数据文摘(BigDataDigest)编译 | 张秋玥、小七、蒋宝尚本文主要介绍了一些简单易懂最常用的 Python 图像处理库。当今世界充满了各种数据&am…

mysqlclient==1.3.7对应mysql版本_「MySQL」CentOs 7 下安装MySQL

MySQLMySQL 是最流行的关系型数据库管理系统&#xff0c;在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一YUM 安装mysql1、下载 YUM 仓库文件打开网址&#xff1a; https://dev.mysql.com/downloads/…

nginx log response_nginx优化配置大全

很多程序员面试被问到nginx优化做过哪些&#xff0c;因此来记录下配置文件样例为生产环境样例。1、nginx基本优化安装方式有2种&#xff1a;1、源码包安装 2、yum&#xff08;apt-get&#xff09;安装区别为如果用yum安装的话&#xff0c;很方便&#xff0c;并且基本不报错。如…

指纹对比软件_iQOO VS 小米9屏幕指纹大对决,这次我为vivo疯狂打Call!

在经历了性能、续航、充电的对比之后&#xff0c;我们今天带来了iQOO和小米9的屏幕指纹对比&#xff0c;看看两者在屏幕指纹方面究竟有何不同的表现。▼屏幕指纹原理目前屏幕指纹技术大致分为光电屏幕指纹和超声波屏幕指纹两种&#xff0c;而iQOO和小米9所采用的都是光电屏幕指…

python绘制3d坐标轴_matplotlib在python上绘制3D散点图实例详解

大家可以先参考官方演示文档&#xff1a; 效果图&#xff1a;3D scatterplotDemonstration of a basic scatterplot in 3D.from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt import numpy as np def randrange(n, vmin, vmax):Helper function to mak…

翻转链表python递归_Python实现链表反转的方法【迭代法与递归法】

导读 这篇文章主要介绍了Python实现链表反转的方法,结合实例形式分析了Python迭代法与递归法实现链表反转的相关操作技巧与注意事项,需要的朋友可以参考下 本文实例讲述了Python实现链表反转的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a; Python实现链表反转 …

python鸡兔同笼编程运行结果_Python少儿编程:鸡兔同笼

Python少儿编程&#xff1a;解决鸡兔同笼问题 一笼鸡和兔子&#xff0c;我们数了一下&#xff0c;咳咳&#xff0c;鸡和兔子的头一共有35个&#xff0c;但是鸡和兔子的脚一共有94只。 好的&#xff0c;那么吃货们我们来好好算一算&#xff0c;到底能做几只德州扒鸡和双流兔头呢…

keil debug如何在watch直接修改变量值_python日志记录系列教程,内置logging模块(一),直接使用logging模块的基础日志记录

前言&#xff1a;成熟的软件开发不可避免的要进行日志记录&#xff0c;python内置模块logging提供了强大的日志记录能力&#xff0c;本文将从多个角度&#xff0c;由浅入深的介绍logging的常见使用方法和一些基本概念&#xff0c;本此系列文章分为两篇&#xff0c;本文为系列文…

linux进程管理子系统分析,linux进程管理子系统简要分析

Linux进程管理&#xff1a;进程与程序&#xff1a;程序&#xff1a;存放在磁盘上的一系列代码和数据的可执行映像&#xff0c;是一个静止的实体。进程&#xff1a;是一个执行中的程序&#xff0c;它是动态的实体进程四要素&#xff1a;1. 有一段程序供其执行&#xff0c;这段程…

c语言变量命名规则_带你学习C语言—变量

在编写程序时&#xff0c;常常需要将数据存储在内存中&#xff0c;以便于使用这个数据或者修改这个数据的值。我们通常使用变量来存储数据&#xff0c;而且使用变量可以引用存储在内存中的数据&#xff0c;并随时根据需要对数据进行处理。变量的概念在程序设计中&#xff0c;允…

html缩进快捷键_Windows IDEA 快捷键终极大全,果断收藏!

作者&#xff1a;JaJian出处&#xff1a;https://www.cnblogs.com/jajian/p/8012603.html话说IDEA对新手来说难&#xff0c;可能其中一个原因就是快捷键组合多而且复杂但是它也很全&#xff0c;基本所有功能都可以通过快捷键来完成&#xff0c;可以这么说&#xff0c;如果你掌握…

安装quartus时弹出错误_Win10 安装arcgis10.2 for desktop需要.net framework 解决方案

有效解决“Win10 安装arcgis10.2 for desktop需要microsoft.net framework 3.5 sp1或等效环境”。台式电脑新装了系统&#xff0c;重新安装arcgis 10.2时弹出“安装arcgis10.2 for desktop需要microsoft.net framework 3.5 sp1或等效环境 ”。在网上百度了很多的相关知识&#…

下面哪个字段是http请求中必须具备的_HTTP 协议报文结构及示例

HTTP 基本架构下面我们用一张简单的流程图来展示 HTTP 协议基本架构&#xff0c;以便大家先有个基本的了解Web Client 可以是浏览器、搜索引擎、机器人等等一切基于HTTP 协议发起 http 请求的工具。Web Server 可以是任何的能解析 HTTP 请求&#xff0c;并返回给Web Client 可识…

文件名为空linux,文件系统:隐匿在Linux背后的机制

原标题&#xff1a;文件系统&#xff1a;隐匿在Linux背后的机制在 Linux 中&#xff0c;最直观、最可见的部分就是 文件系统(file system) 。下面我们就来一起探讨一下关于 Linux 中国的文件系统&#xff0c;系统调用以及文件系统实现背后的原理和思想。这些思想中有一些来源于…

docker安装elasticsearch_Elasticsearch amp; Kibana 部署安装 (Docker)

为什么要使用 Docker来部署 Elasticsearch 和 Kibana 呢&#xff0c;传统使用软件在操作系统上安装和配置的方法过于繁琐&#xff0c;并且受一些跨平台的约束&#xff0c;例如Mac、Windows、Linux等&#xff0c;所以无论安装什么软件&#xff0c;通过 Docker 进行部署是最为简单…