美文网首页
基于粒子群算法的牙齿正畸路径规划方法python实现

基于粒子群算法的牙齿正畸路径规划方法python实现

作者: Python解决方案 | 来源:发表于2020-04-18 12:44 被阅读0次

这篇是基于粒子群算法的牙齿正畸路径规划研究的python实现,参考的是徐晓强等人的《基于改进粒子群算法的牙齿正畸路径规划方法》,与这篇文章的区别在于:
1.徐等的文章设计了一种改进的粒子群算法,此篇使用的是普通的粒子群算法。
2.徐等的文章是虽然是对三维进行建模,但是对二维的仿真,而此篇是直接做三维仿真。
3.徐等的文章利用matlab实现在基准函数进行了模型测试,此篇用python实现简单的路径规划仿真。

此篇涉及的知识点有:
1.粒子群算法:如何直观形象地理解粒子群算法?
2.obb包围盒实现:Python实现obb包围盒及包围框
3.python如何读取stl格式数据

主函数

import numpy as np
from sympy import *
from matplotlib import cm
import math
import pylab as pl
import scipy as sp
from stl import stl
from numpy.linalg import solve
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d as a3
import matplotlib.colors as colors
from mpl_toolkits.mplot3d import Axes3D
from orthodontic import Tooth_dot,Tooth_obb_box,Tooth_obb_plot,Tooth_obb_plot2,Orthodontic,Particle_generation
from orthodontic import PSO

fig = plt.figure()
ax = Axes3D(fig)
#加载牙齿的stl数据
stl_list=[0,1,2,3,4,5,6,7,8,9,10,11,12,13]
# stl_list=[13]
z=5#30个粒子
m=len(stl_list)#牙齿个数

n=5#七个阶段
iter_max=10

#通过随机平移和旋转生成z个粒子
pt=Particle_generation(z,m,n)
# print(pt)
#得到最好的粒子
best_pt=PSO(pt,z,m,n,iter_max)
# 获取牙齿的stl点坐标,理想位置
for k in range(n):
    for i in range(0,1):
        dot=Tooth_dot(stl_list[i])
        b,x,ans,les,cos=Tooth_obb_box(dot)

        # diag_b=b.diagonal()
        # for i in range(3):
        #   print(x,math.acos(diag_b[i])*180/math.pi)

        color_bar=['purple','y','orange','g','k','gray','purple']
        #矫正位置

        orth_x=best_pt[i,k,0:3]
        orth_ang=best_pt[i,k,3:6]
        orth_b,orth_ans=Orthodontic(b,cos,orth_ang,orth_x,les)
        if k==0:
            Tooth_obb_plot(ax,dot,orth_b,orth_x,orth_ans,'gp')
        Tooth_obb_plot(ax,dot,orth_b,orth_x,orth_ans,color_bar[k])
        if k==n-1:
            Tooth_obb_plot2(ax,dot,b,x,ans,'rp')
    plt.pause(0.000001)
        
plt.show()
#obb碰撞检测参考:http://www.doc88.com/p-5953424737378.html

obb包围盒实现及粒子群算法仿真:

import math
import copy
import numpy as np
from stl import stl
from math import sin,cos,log,pi
from numpy.linalg import solve
import matplotlib.pyplot as plt
from scipy.optimize import fsolve
import mpl_toolkits.mplot3d as a3
import matplotlib.colors as colors
from mpl_toolkits.mplot3d import Axes3D

#获取牙齿的数据
def Tooth_dot(stl_list_i):

    mesh = stl.StlMesh('./牙齿正畸/牙齿切分模型/'+str(stl_list_i)+'.stl')
    dot_orignal=np.zeros((1,3))
    for i in range(len(mesh)):
        s1=mesh.points[i]
        s2=s1.reshape(3,3)
        dot_orignal=np.vstack((dot_orignal,s2))
    return dot_orignal[1:,:]

#求解obb包围盒
def Tooth_obb_box(dot):
    
#画出obb包围盒
def Tooth_obb_plot(ax,dot,b,x,ans,colorr):

    #画出所有点
    # kwargs = {'alpha': 0.0001,'color':'blue'}
    # ax.plot3D(dot[:,0].tolist(),dot[:,1].tolist(),dot[:,2].tolist(),'.',linewidth=0.05,**kwargs)

    #画出三个新的坐标轴
    for i in range(3):
        ax.plot3D([x[0],x[0]+b[0,i]],[x[1],x[1]+b[1,i]],[x[2],x[2]+b[2,i]])
    
    x_ans=[ans[0,0],ans[1,0],ans[3,0],ans[2,0],ans[0,0],ans[4,0],ans[6,0],ans[7,0],ans[5,0],ans[4,0]]
    y_ans=[ans[0,1],ans[1,1],ans[3,1],ans[2,1],ans[0,1],ans[4,1],ans[6,1],ans[7,1],ans[5,1],ans[4,1]]
    z_ans=[ans[0,2],ans[1,2],ans[3,2],ans[2,2],ans[0,2],ans[4,2],ans[6,2],ans[7,2],ans[5,2],ans[4,2]]

    #画出obb盒子
    ax.plot3D(x_ans,y_ans,z_ans,colorr,linewidth=0.8)
    for i in range(3):
        ax.plot3D([ans[i+1,0],ans[i+5,0]],[ans[i+1,1],ans[i+5,1]],[ans[i+1,2],ans[i+5,2]],colorr,linewidth=0.8)
def Tooth_obb_plot2(ax,dot,b,x,ans,colorr):

    #画出所有点
    kwargs = {'alpha': 0.003,'color':'blue'}
    ax.plot3D(dot[:,0].tolist(),dot[:,1].tolist(),dot[:,2].tolist(),'.',linewidth=0.05,**kwargs)

    #画出三个新的坐标轴
    for i in range(3):
        ax.plot3D([x[0],x[0]+b[0,i]],[x[1],x[1]+b[1,i]],[x[2],x[2]+b[2,i]])
    
    x_ans=[ans[0,0],ans[1,0],ans[3,0],ans[2,0],ans[0,0],ans[4,0],ans[6,0],ans[7,0],ans[5,0],ans[4,0]]
    y_ans=[ans[0,1],ans[1,1],ans[3,1],ans[2,1],ans[0,1],ans[4,1],ans[6,1],ans[7,1],ans[5,1],ans[4,1]]
    z_ans=[ans[0,2],ans[1,2],ans[3,2],ans[2,2],ans[0,2],ans[4,2],ans[6,2],ans[7,2],ans[5,2],ans[4,2]]

    #画出obb盒子
    ax.plot3D(x_ans,y_ans,z_ans,colorr,linewidth=0.8)
    for i in range(3):
        ax.plot3D([ans[i+1,0],ans[i+5,0]],[ans[i+1,1],ans[i+5,1]],[ans[i+1,2],ans[i+5,2]],colorr,linewidth=0.8)


#求解变换后的局部坐标系向量
def f(x):
    x1 = float(x[0])
    y1 = float(x[1])
    z1 = float(x[2])
    x2 = float(x[3])
    y2 = float(x[4])
    z2 = float(x[5])
    x3 = float(x[6])
    y3 = float(x[7])
    z3 = float(x[8])
    return [x1*x2+y1*y2+z1*z2,
             x1*x3+y1*y3+z1*z3,
             x2*x3+y2*y3+z2*z3,
             x1*x1+y1*y1+z1*z1-1,
             x2*x2+y2*y2+z2*z2-1,
             x3*x3+y3*y3+z3*z3-1,
             x1-float(x[9]),
             y2-float(x[10]),
             z3-float(x[11]),
             0.,
             0.,
             0.]

#牙齿移动后的相关坐标:局部坐标系,八个顶点的坐标
def Orthodontic(ob,cos,orth_ang,orth_x,les):
    b = ob.T.flatten().tolist()
    orth_ang = np.cos(orth_ang/180*pi)
    orth_ang = orth_ang.tolist()
    x=b+orth_ang
    result = fsolve(f,x)
    orth_b = np.array(result[0:9]).reshape(3,3)
    orth_b=orth_b.T
    orth_ans = np.mat(orth_b.T).I*cos.T
    for i in range(8):
        orth_ans[:,i]=orth_ans[:,i]*les[i]+np.mat(orth_x).T
    return orth_b,orth_ans.T

def Particle_generation(z,m,n):
    pt=np.zeros((z,m,n,6))
    #三颗牙齿的理想位置
    for i in range(z):
        for j in range(m):
            pt[i,0,0,:]=np.array([23.61006943,17.82747056,-20.16727971,69.4602916066788,118.19793758099148,28.944969967151017])
            pt[i,1,0,:]=np.array([22.00154474,22.23109873,-10.56274203,82.20503306251742,102.23797429234898,22.659750787501384])
            pt[i,2,0,:]=np.array([20.21602939,24.55590149,-2.56155887,19.59300214465621,160.00846123132308,9.34366689686702])
            pt[i,3,0,:]=np.array([17.4970468,27.10152147,2.91609252,40.59623501981751,139.67459285911806,6.191516712578595])
            pt[i,4,0,:]=np.array([12.69758738,29.13274355,8.5260505,78.95655178930328,100.28096565608264,33.931521943543544])
            pt[i,5,0,:]=np.array([8.16643294,30.28463427,11.42548952,89.19138292409808,98.71517063028655,41.944118961376994])
            pt[i,6,0,:]=np.array([3.55807655,31.58355968,12.26046366,83.50554859236546,103.41535763991074,53.69547623532445])
            pt[i,7,0,:]=np.array([-2.04687096,32.17083736,12.52742242,85.46722651861216,84.94579068682329,58.91289971101213])
            pt[i,8,0,:]=np.array([-7.12704824,32.10145805,11.43092301,98.08610437351948,104.41711898593356,59.05840552581135])
            pt[i,9,0,:]=np.array([-12.15524467,31.13939936,8.31407426,100.21243845803976,69.79845402078593,37.36596015162017])
            pt[i,10,0,:]=np.array([-17.12435839,30.17595961,2.86044776,150.92175547611808,162.41497137576253,60.810690756858506])
            pt[i,11,0,:]=np.array([-20.04271334,29.57043377,-4.32045092,152.3966623284993,26.461495168995285,9.154096620848087])
            pt[i,12,0,:]=np.array([-22.0431927,26.59292723,-12.05594014,103.35215185282235,79.9218652295453,21.802210187730434])
            pt[i,13,0,:]=np.array([-23.77424033,22.90435583,-21.39226861,73.461423996978,79.07185113689994,113.40844315750385])

            for k in range(1,n):
                pt[i,j,k,0:3]=pt[i,j,k-1,0:3]+((-1 + 2*np.random.random((1,3)))*0.28)
                pt[i,j,k,3:6]=pt[i,j,k-1,3:6]+(-1 + 2*np.random.random((1,3)))
    for i in range(z):
        for j in range(m):
            # print(np.flipud(pt[i,j]))
            pt[i,j]=copy.deepcopy(np.flipud(pt[i,j]))
            # print(pt[i,j])
    return pt

#碰撞检测
def Collision_detection(pt_i):
    return 0

#其他限制条件
def Constraint(p1,p2):
    gc1=sum(np.power(p1[0:3]-p2[0:3],2))
    gc2=sum(abs(p1[3:6]-p2[3:6]))
    if gc1<=0.25 and gc2<=3:
        return 1
    else:
        return 0

#适应度函数
def Fitness(pt_i,m,n):
    f1=0;f2=0;f3=0;g1=0;g2=0;gc1=0;gc2=0;cons=0;Cons=1
    for j in range(m):
        for k in range(1,n):
            #距离评价函数
            f1=f1+np.sqrt(sum(np.power(pt_i[j,k,0:3]-pt_i[j,k-1,0:3],2)))
            #角度评价函数
            f2=f2+np.sum(abs(pt_i[j,k,3:6]-pt_i[j,k-1,3:6]))
            #碰撞检测约束条件
            f3=Collision_detection(pt_i[j,k,:])
            #距离和角度约束条件
            cons=Constraint(pt_i[j,k,:],pt_i[j,k-1,:])
            Cons=Cons*cons
    if Cons==1:
        fitness=f1+f2+f3
    else:
        fitness=(f1+f2+f3)*100
    return fitness
# #PSO算法
def PSO(pt,z,m,n,iter_max):
    #初始化粒子群算法相关参数
    w=0.8;c1=2;c2=2;r1=np.random.random(1);r2=np.random.random(1)
    v=np.zeros((m,6))
    sbf=np.ones(z)*500#单个粒子最小适应度值
    sb=np.zeros((z,m,n,6))#单个粒子最优值
    ap=np.zeros((z,m,n,6))#平均值
    sd=np.zeros((z,m,n,6))#标准差
    wb=np.ones((iter_max,m,n,6))#全局最优值
    
    for iter in range(iter_max):
        for i in range(z):#粒子个数
            sf=Fitness(pt[i],m,n)
            if sf<sbf[i]:
                # print("第",iter,"循环,","第",i,"个粒子的适应度值:",sf)
                sbf[i]=sf
                sb[i]=pt[i]         #更新单个粒子目前为止最优值
        # print("第",iter,"循环后,单个粒子的最小适应度值:",sbf)
        wb[iter]=sb[np.argmin(sbf)] #更新目前为止全局最优值
        # print("第",iter,"循环后,全局最小适应度值对应的粒子:",wb[iter])

        #进行更新
        for i in range(z):
            for j in range(m):
                for k in range(1,n-1):
                    ap[i,j,k,:]=(pt[i,j,k,:]+sb[i,j,k,:]+wb[iter,j,k,:])/3#公式5
                    sd[i,j,k,:]=np.sqrt((np.power((pt[i,j,k,:]-ap[i,j,k,:]),2)#公式6
                        +np.power(sb[i,j,k,:]-ap[i,j,k,:],2)
                        +np.power(wb[iter,j,k,:]-ap[i,j,k,:],2))/3)                 
                    K=np.sqrt(-2*log(np.random.random(1)))*cos(2*pi*np.random.random(1))#公式7
                    # p1=w*pt[i,j,k,:]![Figure_1.png](https://img.haomeiwen.com/i1437023/49eaea517c0273a2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

                    # p2=c1*r1*(w*(sb[i,j,k,:]+wb[iter,j,k,:])/2-pt[i,j,k,:])
                    # p3=c2*r2*((sb[i,j,k,:]-wb[iter,j,k,:])/2-pt[i,j,k,:])
                    # p4=K*sd[i,j,k,:]
                    # pt[i,j,k,:]=p1+p2+p3+p4#公式4

                    v[j,:]=w*v[j,:]+c1*r1*(sb[i,j,k,:]-pt[i,j,k,:])+c2*r2*(wb[iter,j,k,:]-pt[i,j,k,:])
                    pt[i,j,k,:]=pt[i,j,k,:]+v[j,:]#公式4
                    # print(i,j,k,pt[i,j,k,:])

    return wb[-1]

效果图(图有点丑,但这不是重点):


单颗牙齿正畸过程.png

相关文章

网友评论

      本文标题:基于粒子群算法的牙齿正畸路径规划方法python实现

      本文链接:https://www.haomeiwen.com/subject/tvlvvhtx.html