当前位置:首页 » 操作系统 » 骨架化算法

骨架化算法

发布时间: 2022-10-20 01:03:24

❶ 女生怎么判断自己是大骨架还是小骨架

如上图所示测量手腕围,再用身高除于手腕围 (cm 对 cm),得到的数字比对下表:

大骨架: <9.6

中骨架: 9.6-10.4

小骨架: >10.4

大骨架: <9.9

中骨架: 9.9-10.9

小骨架: >10.9

参考了以上两个方法后你是否对自己的骨架大小有了个概念呢?

迷思 2: 骨架大会比较重?

这点也是正确的,因人的骨头占了总体重的 10-20%,若骨架大理应体重会稍重个 2-4kg,因此也会看起来稍微大只。

迷思 3: 骨架大会看起来比较胖?

这是错误的观念,骨架大虽然会比较重,但体重其实无法真正的反应出一个人的体态胖瘦,

就好像西方女星,骨架虽然比我们东亚女性大上许多,但身材却一样苗条,

所以说想减肥的朋友们,就别再纠结自己的骨架大小及骨头重量,

只要好好的锻炼肌肉,减少脂肪,就算体重变化不大,体态上也会慢慢变好看的哟!

看完了小编的分享后是不是对自己骨架大小有点头绪了呢?

无论骨架大小想减肥都必须从增肌减脂着手,有了正确的观念好身材就离你不远了,继续加油吧!

-THE END-

❷ 什么样的图像可以进行细化

二值的当然不行。

快速zhang并行算法,很好的一种常用方法
具体细化方法:
满足下列四个条件的点可以删除
p3 p2 p9
p4 p1 p8
p5 p6 p7

细化删除条件为: (1)、2 < Nz(p1) <= 6 Nz为八邻域中黑点的数目
(2)、Zo(p1)=1,指中心为黑点
(3)、p2*p4*p8=0 or Zo(p1)!=1 避免黑线被打断
(4)、p2*p4*p6=0 or Zo(p4)!=1

细化算法的分类:
依据是否使用迭代运算可以分为两类:第一类是非迭代算法,一次即产生骨架,如基于距离变换的方法。游程长度编码细化等。第二类是迭代算法,即重复删除图像边缘满足一定条件的像素,最终得到单像素宽带骨架。迭代方法依据其检查像素的方法又可以再分成串行算法和并行算法,在串行算法中,是否删除像素在每次迭代的执行中是固定顺序的,它不仅取决于前次迭代的结果,也取决于本次迭代中已处理过像素点分布情况,而在并行算法中,像素点删除与否与像素值图像中的顺序无关,仅取决于前次迭代的结果。在经典细化算法发展的同时,起源于图像集合运算的形态学细化算法也得到了快速的发展。
Hilditch、Pavlidis、Rosenfeld细化算法:这类算法则是在程序中直接运算,根据运算结果来判定是否可以删除点的算法,差别在于不同算法的判定条件不同。
其中Hilditch算法使用于二值图像,比较普通,是一般的算法; Pavlidis算法通过并行和串行混合处理来实现,用位运算进行特定模式的匹配,所得的骨架是8连接的,使用于0-1二值图像 ;Rosenfeld算法是一种并行细化算法,所得的骨架形态是8-连接的,使用于0-1二值图像 。 后两种算法的效果要更好一些,但是处理某些图像时效果一般,第一种算法使用性强些。
索引表细化算法:经过预处理后得到待细化的图像是0、1二值图像。像素值为1的是需要细化的部分,像素值为0的是背景区域。基于索引表的算法就是依据一定的判断依据,所做出的一张表,然后根据魔鬼要细化的点的八个邻域的情况查询,若表中元素是1,若表中元素是1,则删除该点(改为背景),若是0则保留。因为一个像素的8个邻域共有256中可能情况,因此,索引表的大小一般为256。

❸ matlab 图像骨架化问题请教

可以用函数 bwmorph() 来解决,查看一下 bwmorph() 里面的选项

BW2 = bwmorph(BW1,'remove'); %提取边缘
BW3 = bwmorph(BW2,'skel',Inf); %骨架化

❹ 168的身高的女生合理的体重是多少

我国正常成年男性的身高与体重的关系(女性的体重相应减少2.5Kg) 单位:Kg
之前有研究称,腰围和臀围的比例是性感的最重要因素。
但是通过深入调查分析,健康专家认为,体重指数是一个评定性感指数的关键数字,它比腰围和臀围的比例更能灵敏反映女性身材的变化。
腰臀比 = 腰围/臀围
男性 > 0.90、女性> 0.80就表明已经存在局部肥胖了,黄金腰臀比例是:维纳斯:0.68;玛丽莲·梦露:0.66。
一般认为,正常的体重指数为18到25之间,超重的体重指数为25到30之间,肥胖的体重指数为30以上。当这个描述身高和体重比例的体重指数为20.85时,就意味着这位女性的身材最性感。“因此,减肥的女性就一定要注意自己减肥的尺度了。”专家建议说。但是上面这个标准对于男性来说就并不适用了。
研究人员还表示,对于不同国家的人来说这个性感指数略微有一些差别,但没有本质上的区别。BMI = 体重(公斤)/[身高(米)]2
例如:1个人身高176厘米,体重75公斤,他的BMI=75/(1.76)2 = 24.2。

女子标准体重对照表 附加三围标准

中国母性美体曲线对照表

身高 胸部 腰部 臀部 大腿 小腿 标准体重kg 美体重kg

150 79.5 55.5 81.0 46.8 28.1 48.0 43.2

151 80.0 55.9 81.5 47.1 28.2 48.5 43.7

152 80.6 56.2 82.1 47.3 28.4 49.0 44.1

153 81.1 56.6 82.6 47.6 28.5 49.5 44.6

154 81.6 57.0 83.2 47.8 28.7 50.0 45.0

155 82.2 57.4 83.7 48.1 28.9 50.5 45.5

156 82.7 57.7 84.2 48.4 29.0 51.0 45.9

157 83.2 58.1 84.8 48.6 29.2 51.5 46.4

158 83.7 58.5 85.3 48.9 29.3 52.0 46.8

159 84.3 58.8 85.9 49.1 29.5 52.5 47.3

160 84.8 59.2 86.4 49.4 29.6 53.0 47.7

161 85.3 59.6 86.9 49.7 29.8 53.5 48.2

162 85.9 59.9 87.5 49.9 30.0 54.0 48.6

163 86.4 60.3 88.0 50.2 30.1 54.5 49.1

164 86.9 60.7 88.6 50.4 30.3 55.0 49.5

165 87.5 61.1 89.1 50.7 30.4 55.5 50.0

166 88.0 61.4 89.6 51.0 30.6 56.0 50.4

167 88.5 61.8 90.2 51.2 30.7 56.5 50.9

168 89.0 62.2 90.7 51.5 30.9 57.0 51.3

169 89.6 62.5 91.3 51.7 31.0 57.5 51.8

170 90.1 62.9 91.8 52.0 31.2 58.0 52.2

171 90.6 63.3 92.3 52.3 31.4 58.5 52.7

172 91.2 63.6 92.9 52.5 31.5 59.0 53.1

173 91.7 64.0 93.4 52.8 31.7 59.5 53.6

174 92.2 64.4 94.0 53.0 31.8 60.0 54.0

175 92.8 64.8 94.5 53.3 32.0 60.5 54.5
很费劲,请采纳,谢谢!

❺ grassfire算法

这个算法是做图像处理的抽骨架处理(文后附抽骨架的简介),目的是求出图像的骨架,可以想象一片与物体形状相同的草,沿其外围各点同时点火。当火势向内蔓延,向前推进的火线相遇处各点的轨迹就是中轴。

该处理有很多种不同的算法,从你提供的程序来看,它属于距离矩阵的算法。它要求计算对象必须是体表示的模型(对平面来说,就是二维矩阵),通过计算每个体元素到边界的最小距离来求取模型的脊点、骨架点.

程序中freespace是输入矩阵,freespaceX和freespaceY是输入矩阵的宽和高,navi用来保存输出矩阵(既矩阵每个元素记录的是该点到达边界的最小距离。

freespace输入矩阵中,值-1代表障碍物边界,值0代表空白空间。

基本算法:

1.建立一个用矩形边界包裹freespace的新临时矩阵tmpNavi。注意,对于边界节点,其值仍然为-1,而

对于非边界节点,给予了一个固定增量(freespaceX*freespaceY*d1)。

2.用多重处理算法处理临时矩阵tmpNavi,直至tmpNavi稳定下来,不再发生改变。

3.多重处理中的每次处理的算法:遍历每个非边界节点,计算它经由它的8个相邻节点分别到达边界的距离值(既到相邻节点的距离+相邻节点自身值),取其中最小值作为它自身新值。这样周而复始,就能得到一个稳定的数值矩阵。

(程序中用了一些优化的手法,但基本的算法原理就是这样的)

4.将临时矩阵tmpNavi的内容拷贝到输出矩阵navi,并统计其中的骨点值(最大值)到m_maxValue。

希望以上回答对你有帮助。

抽骨架(Skeletonization)

一个与细化有关的运算是抽骨架,也称为中轴变换(Medialaxistransform)或焚烧草地技术(grass-firetechnigue)。中轴是所有与物体在两个或更多非邻接边界点处相切的圆心的轨迹。但抽骨架很少通过在物体内拟合圆来实现。

概念上,中轴可设想成按如下方式形成。想象一片与物体形状相同的草,沿其外围各点同时点火。当火势向内蔓延,向前推进的火线相遇处各点的轨迹就是中轴。

抽骨架的实现与细化相似,可采用一个两步有条件腐蚀实现,但是删除像素的规则略有不同。

下图将细化与抽骨架进行比较。二者的主要的差别在于抽骨架在拐角处延伸到了边界,而由细化得到的骨架却没有。

上面图a是细化的效果,下面的图b是抽骨架的效果。

(左边是处理一个均匀的矩形区域,右边是处理一个均匀的圆形区域)

❻ 基于opencv采用C++或java语言选择一个二值图像骨架提取算法实现并对实验结果进行评价。

这和什么语言没关系。如果想用现成的你可以到directory.fsf.org下载gimp,有很多图像处理工具的源代码可以使用,包括C,C++和java。

如果纯粹是你个人想尝试一下,那么这里纯粹是算法的问题。任何图像都是以矩阵方式存储的,不论是文件形式和内存形式。处理之前你首先要清楚这个矩阵的大小,尺寸,每个字节对应为止的像素含义。搞清楚之后,才是算法操作。我理解你的“骨架提取”就是将位图向量化的过程,简单的说,就是由点阵转换为一系列直线,并记录每段直线的起点和终点,甚至转换为连续直线、贝泽尔曲线,或者圆弧。这是个非常高级的数学问题,并不是所有的位图都有解,这也是为什么像手写笔识别、脸谱识别和车牌识别迄今为止尚有一些误差,不可能做到100%成功,识别的过程采用了人工神经网络、前馈网络、多层网络等相当水平的数学方法。举个例子来说,如果你偶尔看到了某个医生的处方,可能只能勉强认出一部分文字,这就是为什么说不是所有位图都有解的一个最简单的解释。

❼ 如何做人体骨架模型

本文提供一种将骨架动作矢量映射到人体骨架模型的一种方法,通过输入各个骨骼的当前方向,反馈给骨架模型,这样就实现了动画的效果。实验开发工具是VC6.0在OpenGL平台上开发完成。

阅读对象:

假定读者已经熟悉OpenGL编程,就算不熟悉,只要了解基本的旋转,平移,堆栈操作就好。
假定读者已经了解基本的c++编程,其中需要了解递归的算法,递归的方法请参考一下数据结构吧。

制作过程:

第一步,3D模型准备

这一步骤的目的是提供分解的骨骼模型,它需要导出多个组成身体结构的文件,模型可以不用自己制作,只要到网上找找吧,应该很多,最好是是人体模型,如果用动物的模型也可以,不过需要自己定义映射骨架了,比如图中的骷髅模型是我从人体动画软件poser 5.0找到的。然后使用3d max 将身体的各个部位导出为3ds文件,这个步骤很简单,也不需要有什么3d max的基础。这里有一个小的技巧就是可以选中多个部分作为一个3ds模型导出,比如我需要将左右肩胛骨与脊椎骨肋骨作为同一个部分导出,这样可以将它命名为身体躯干(body)。这样我们就准备了各个3ds文件了,分别是:

身体躯干 BODY.3DS
头部 HEAD.3DS
左臂 LSHOULDER.3DS
右臂 RSHOULDER.3DS
左小臂 LELBOW.3DS
右小臂 RELBOW.3DS
左大腿 LTHIGH.3DS
右大腿 RTHIGH.3DS
左小腿 LFEET.3DS
右小腿 RFEET.3DS

这样这些组成部分就可以灵活的拼接出一个人体来了。

第二步,定义相关的核心数据结构

为了得到运动的各个身体部分数据信息,我们需要存储一些运动信息,主要有:
骨骼ID
骨骼关节的当前位置;r_x,r_y,r_z
骨骼之间的关系,例如手臂是躯干的延伸,而左小臂是左臂的延伸;PID,CID

我们可以通过下图来了解骨骼之间的结构关系

存放3ds文件位置;file_name_3ds
3ds模型的初始化方向;这个是比较抽象一点的概念,它是指从父节点指向子节点的方向,例如左小臂的初始位置是平放向下,那么对应的矢量就是 (-0.2,-1,0)

以下是数据结构部分:
class bone
{
public:
int y;
int x;
int r_z; //现实世界z坐标
int r_y;
int r_x;
int rotated_X; //旋转后的坐标
int rotated_Y;
int is_marked; //是否已经标记
int PID; //父节点
int CID; //子节点,目前针对轴关节和膝盖有效
float start_arc_x,end_arc_x; //相对父节点的x 左右方向转动角度限制
float start_arc_y,end_arc_y; //相对父节点的y 上下方向转动角度限制
float start_arc_z,end_arc_z; //相对父节点的z 前后方向转动角度限制
double LengthRatio;
char name[80]; //名称
char file_name_3ds[180]; //3ds文件名称
int ID;
bone(int ID,char *name,int PID);
virtual ~bone();
float bone_init_x,bone_init_y,bone_init_z; //初始化骨骼的矢量方向,3d max 模型
};

第三步,初始化骨架结构

在定义了bone的结构以后,我们定义一个skeleton类来在第一次初始化时加载这些结构,

obone = bone (2,"head",1); //定义一个bone
strcpy(obone.file_name_3ds,"head.3DS"); //设置它的3ds文件名
obone.bone_init_x = 0; //初始化骨骼的矢量方向
obone.bone_init_y = 1;
obone.bone_init_z = 0;
bonevec.push_back (obone); //放入vector结构,这里用到了STL编程技术中的vector

以下是实现的部分代码:
skelecton::skelecton()
{
float fy = 0.56f ;
float ftx = 0.19f;
float ffx = 0.08f;
bone obone = bone (1,"neck",0);
bonevec.push_back (obone);

obone = bone (2,"head",1);
strcpy(obone.file_name_3ds,"head.3DS");
obone.bone_init_x = 0;
obone.bone_init_y = 1;
obone.bone_init_z = 0;
bonevec.push_back (obone);

obone = bone (3,"rShoulder",1);
bonevec.push_back (obone);

obone = bone (4,"lShoulder",1);
bonevec.push_back (obone);

obone = bone (5,"rElbow",3);
strcpy(obone.file_name_3ds,"rShoulder.3DS");
obone.bone_init_x = fy;
obone.bone_init_y = -1;
obone.bone_init_z = 0;
obone.CID = 7;
bonevec.push_back (obone);

obone = bone (6,"lElbow",4);
strcpy(obone.file_name_3ds,"lShoulder.3DS");
obone.bone_init_x = -fy;
obone.bone_init_y = -1;
obone.bone_init_z = 0;
obone.CID = 8;
bonevec.push_back (obone);

//.............太长只给出部分的代码..........................
}

第四步,学习3ds公共的类CLoad3DS,可以用来载入显示模型

这个类是公用一个类,详细的类CLoad3DS的接口信息可以到一个open source项目里参考。http://scourge.sourceforge.net
http://scourge.sourceforge.net/api/3ds_8h-source.html
实际上在使用这个类时候,我做了一些修改,加了得到最大顶点的方法。这个在第五步会说明。

我们定义一个OpenGL的类来做模型控制类,负责载入模型,

CLoad3DS* m_3ds;

int OpenGL::Load3DS(int ID, char *filename)
{
if(m_3ds!=NULL) m_3ds->Init(filename,ID);
return 0;
}

然后在显示时候调用

int OpenGL::show3ds(int ID)
{
m_3ds->show3ds(ID,0,0,0,2);
return 0;
}

第五步,使用递归方法分层次载入模型

这里是重点的内容了,让我们思考一些问题,实现骨骼会随着输入的方向而改变方向,需要做那些事情呢?

首先针对一块骨骼来考虑:

第一,我们需要让骨骼绕着它的节点旋转到输入的方向上

第二,我们需要知道骨骼目前节点的位置,才能旋转。可是我们知道骨骼会跟着它的父骨骼转动的,例如左小臂会跟着左臂转动,当身体转动时左臂也会跟着身体转动的,这里看起来像是有一个父子连动的关系,所以当前节点的位置会与它的父骨骼有关,父骨骼转动的角度,子骨骼也必须转动,所以这里自然想到了递归模型了,至于如何存储这些转动过程呢,还好openGL提供了glPushMatrix();glPopMatrix();那么所有的子骨骼必须包含在父骨骼的glPushMatrix();glPopMatrix();好了,这个变成

//递归实现3d现实
int skelecton::Render_skeleton_3D(int ID)
{

glPushMatrix(); //开始记录堆栈
joint_point = pgl->get_joint_point(ID); //找到节点位置
glTranslatef(joint_point.x,joint_point.y,joint_point.z); //坐标移到节点位置
pgl->rotate_bone (vt1,vt2,vto); //旋转骨骼到指定的方向
glTranslatef(-joint_point.x,-joint_point.y,-joint_point.z);//坐标移回来
pgl->show3ds(ID); //显示模型

//遍历子节点
for (theIterator = bonevec.begin(); theIterator != bonevec.end(); theIterator++)
{
pbone = theIterator;
if((pbone->PID == ID) )
{
Render_skeleton_3D(pbone->ID); //递归调用
}
}

glPopMatrix(); //退出记录堆栈
}

剩下需要解决的问题就是如何找到节点位置。
寻找节点位置,我们看到上面代码 get_joint_point(ID)就是找到节点了,其实如果不追求高的准确度,我们可以假设每个模型的最高的点即为骨骼的节点,当然这个假设前提是人体模型是正面站立的,手臂自然垂下,这样可以近似认为每个模型的最高的点即为骨骼的节点,这样函数就很简单了,这个方法是修改了Cload3ds类的方法,如下:

Vector3f CLoad3DS::get_joint_point(int j0)
{
CVector3 LastPoint;
Vector3f vect;
LastPoint.y = -1000 ;
if(j0==2) LastPoint.y = 1000 ;//头部节点朝下

// 遍历模型中所有的对象
for(int l = 0; l < g_3DModel[j0].numOfObjects; l++)
{
if(g_3DModel[j0].pObject.size() <= 0) break;// 如果对象的大小小于0,则退出
t3DObject *pObject = &g_3DModel[j0].pObject[l];// 获得当前显示的对象

for(int j = 0; j < pObject->numOfFaces; j++) // 遍历所有的面
{
for(int tex = 0; tex < 3; tex++) // 遍历三角形的所有点
{
int index = pObject->pFaces[j].vertIndex[tex]; // 获得面对每个点的索引

if(j0==2)
{
if(pObject->pVerts[index].y < LastPoint.y )
LastPoint = pObject->pVerts[index];
}
else
{
if(pObject->pVerts[index].y > LastPoint.y )
LastPoint = pObject->pVerts[index];
}
}
}
}
vect.x = LastPoint.x ;
vect.y = LastPoint.y ;
vect.z = LastPoint.z ;
return vect;
}

比较特殊的是头部节点是通过脖子连接的,所以它是取最低的点。

现在解决最后的问题了,如何旋转了,具体来讲就是骨骼从原来自然的状态旋转到目前的方向,例如手臂从自然垂下变成抬起,垂下和抬起两个状态的矢量是不同的方向的,如何旋转呢? 这里就要用到了空间几何里的点积和叉积的概念了,简单来讲就是利用点积来求矢量夹角余弦,利用叉积来求两个矢量的法向量,如果你忘记了这些概念,可以回去参考一下高等数学书,这个连接也提供了一些资料,可以帮助理解http://www.gameres.com/Articles/Program/Visual/Other/shiliang.htm
然后呢,我们知道了两个矢量的夹角与它们的法向量,下面的事情就变得简单了,我们让骨骼原来的矢量以法向量为旋转轴,旋转一定角度,这个角度就是两个矢量的夹角,这样问题就解决了,所以这里的代码如下:

int OpenGL::rotate_bone(Vector3f vVector1, Vector3f vVector2, Vector3f vVectorOrgin)
{
Vector3f vt1 = Vector3f(vVector1.x,vVector1.y,vVector1.z);
Vector3f vt2 = Vector3f(vVector2.x,vVector2.y,vVector2.z);
Vector3f vt4 = vt2-vt1;

double arc12 = AngleBetweenVectors(vVectorOrgin,vt4);
double rarc12 = 180*arc12/pi;
float len= Distance(vt1,vt2);
Vector3f vt3 = Cross(vVectorOrgin,vt4);
glRotatef ((float)rarc12,vt3.x,vt3.y,vt3.z);

return 0;
}

热点内容
汽修汽配源码 发布:2025-05-14 20:08:53 浏览:742
蜜蜂编程官网 发布:2025-05-14 19:59:28 浏览:57
优酷怎么给视频加密 发布:2025-05-14 19:31:34 浏览:635
梦三国2副本脚本 发布:2025-05-14 19:29:58 浏览:860
phpxmlhttp 发布:2025-05-14 19:29:58 浏览:434
Pua脚本 发布:2025-05-14 19:24:56 浏览:449
苹果像素低为什么比安卓好 发布:2025-05-14 19:13:23 浏览:461
安卓机微信怎么设置红包提醒 发布:2025-05-14 19:00:15 浏览:272
androidsystem权限设置 发布:2025-05-14 18:56:02 浏览:971
mq脚本 发布:2025-05-14 18:45:37 浏览:25