自动摘要: >修订历史 |时间 |版本号 |修订人 |主要修订内容 | ||||| |20220616|1.0 ……..
修订历史
时间
版本号
修订人
主要修订内容
2022-06-16
1.0.0
杨新
模板设定
2022-06-16
1.0.1
罗依蒙
整体文档结构安排
2022-06-17
1.0.2
罗依蒙
文档结构安排调整
2022-6-18
1.0.3
罗依蒙
文档结构敲定与分牙数据函数开始整合
2022-6-22
1.0.4
罗依蒙
全冠代码整理
2022-6-23
1.0.5
罗依蒙
全冠代码整理
2022-6-25
1.1.6
罗依蒙
全冠代码完善
2022-6-29
1.1.7
罗依蒙
全冠代码完善与部署类部分代码整理
2022-7-1
1.1.8
罗依蒙
部署类部分代码整理
2022-7-4
1.1.9
罗依蒙
部署类部分代码整理
2022-7-5
1.1.10
罗依蒙
部署类部分代码整理
2022-7-6
1.1.11
罗依蒙
部署类代码存在的疑问的修正
2022-7-7
1.2.12
罗依蒙
部署类代码整理完善
2022-7-8
1.2.13
罗依蒙
现有的分牙代码整理
2022-7-15
1.2.14
罗依蒙
添加“一键式”目录与FullCrown的run函数
2022-7-27
1.2.15
罗依蒙
嵌体部分代码整理
2022-8-1
1.2.16
罗依蒙
嵌体部分代码修改
2022-8-2
1.2.17
罗依蒙
完善函数注释
算法库链接
http://192.168.1.55/up3d/AI
APIImage measurement
蓝色字体是相对于原始代码更改的说明 棕色字体是对代码内容的疑问 橘色是对代码数据或输入输出注意点的说明
数据处理类-DataProcess
用于数据处理的一些函数,根据数据格式等的不同划分为3D数据处理、2D数据处理、文本数据处理以及图像数据处理。根据业务不同分为全冠数据处理、分牙数据处理
全冠数据处理-FullCrown 对原始数据进行隐式曲面处理,生成torch需要的数据
AI.Repair.FullCrown.init (self, user_path=None, torch_path=None, pt_path=None, generate_path=None,batch_size=167800) 1 2 3 4 5 6 7 8 9 10 def __init__ (self, user_path=None , torch_path=None user_path, torch_path, pt_path=None , generate_path=None ,batch_size=167800 ): """ 定义FullCrown :param user_path: (str)用户数据目录,其目录下的Object与Preparation内的文件名一一对应,默认None :param torch_path: (str)torch数据输出目录/训练数据目录,默认None :param pt_path: (str)历史/前一周期训练结果文件,默认None :param generate_path: (str)推理数据目录,默认None :param batch_size: (int)批量大小,默认 167800 """
AI.Repair.FullCrown.mesh_split(self,mesh:trimesh.Trimesh)->list 1 2 3 4 5 6 7 def mesh_split (self, mesh:trimesh.Trimesh )->list : """ 根据连通体,进行分割牙位,注意:只针对南航数据特性 :param mesh: (trimesh.Trimesh)含3个连通体的网格数据 :return: ((3,)trimesh.Trimesh)返回从左到右的三个连通体的list """
AI.Repair.FullCrown.normalize_meshes(self,mesh) 1 2 3 4 5 6 7 def normalize_meshes (self, mesh ): """ 归一化到[-0.45,0.45] :param mesh: (trimesh.base.Trimesh)需要归一化的原始牙模型 :return: (trimesh.base.Trimesh)归一化后的牙模型 """
AI.Repair.FullCrown.get_mid(self,sources_path=None, target_path=None) 1 2 3 4 5 6 7 8 def get_mid (self, sources_path=None , target_path=None ): """ 获取目标模型的中间牙 :param sources_path: (str)源路径 :param target_path: (str)目标路径 :return: (trimesh.base.Trimesh)中间牙模型 """
AI.Repair.FullCrown.data_process(self,ply_path: str, get_two_teeth: bool = True, resolution:int = 32, pcd_samples_num:int=100000, sigma:float = 0.1, sources_path=None) -> np.array 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def data_process (self,ply_path: str , get_two_teeth: bool = True , resolution:int = 32 , pcd_samples_num:int =100000 , sigma:float = 0.1 , sources_path=None ) -> np.array: """ 处理ply数据 对两颗牙(含中间的基台)的源模型:获取两颗牙(不含中间基台)的数据 对三颗牙的目标模型:目标牙的样本点在其模型上的占用率 :param ply_path: (str)ply数据路径 :param get_two_teeth: (bool)是否要通过连通体进行裁剪成两个牙冠 :param resolution: (int)针对两个牙冠(源)体素进行采样的采样率 [32,64,128,256] 默认32 :param pcd_samples_num: (int)生成部位(目标)采样率 [100k,200k,300k,400K] 默认100k :param sigma: (float)生成部位(目标)边界采样噪声方差 [ [0.1, 0.01]] 默认0.1 :param sources_path: (str)源模型的数据路径,默认None when get_two_teeth==Ture :return: data: ((n,n,n)bool)处理后的原始牙的体素栅格 when get_two_teeth==False :return: data: ((n,)bool)目标牙的样本点在模型上的占用率 :return: pcd_n: (trimesh.caching.TrackedArray)样本点 """
AI.Repair.FullCrown.process(self,user_path=None,torch_path=None) -> None: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 def process (self,user_path=None ,torch_path=None ) -> None : """ 对原始数据进行隐式曲面处理,生成torch需要的数据 步骤: 1.遍历X目录,载入待修复的牙冠 2.对x1,,Xn 进行均值归一化,并将中间的基台去除(对需求无帮助,即噪声) 3.对y1,,Yn 进行均值归一化 4.对处理的数据打包成pt格,放入指定路径下,方便直接于DataLoader加载数据 :param user_path: (str)用户数据目录,其目录下的Object与Preparation内的文件名一一对应,默认None(使用FullCrown对象的user_path) :param torch_path: (str)torch数据输出目录/训练数据目录,默认None :return: None """
AI.Repair.FullCrown.create_bounds(self,min=-0.45, max=0.45, res=256) 1 2 3 4 5 6 7 8 9 def create_bounds (self,min =-0.45 , max =0.45 , res=256 ): """ 生成边界 :param min: (float)最小值,默认-0.45 :param max: (float)最大值,默认0.45 :param res: (int)在min到max范围内划分的个数 :return:points_list ((n, 3)float64)有效范围内各个点的坐标集合 """
分牙数据处理-MeshSeg AI.MeshSeg.MeshSeg.init (self, dataset_path,batch_size=12, save_path=”MeshSeg.pt”, num_workers=12): 1 2 3 4 5 6 7 8 9 10 def __init__ (self, dataset_path,batch_size=12 , save_path="MeshSeg.pt" , num_workers=12 ): """ 定义MeshSeg :param dataset_path: (str)分牙数据目录 :param batch_size: (int)批量大小,默认12 :param save_path: (str)分牙结果存储,默认"MeshSeg.pt" :param num_workers: (int)线程数,默认12 :return:None """
AI.MeshSeg.MeshSeg.dataProcessing(self): 1 2 3 4 5 6 def dataProcessing (self ): """ 数据处理 pass """
模型搭建类-Building 按模型形式分为点云/网格/体素模型、图像模型以及文本模型
点云模型-PointCloud 网格模型-Mesh 体素模型-Voxel 图像模型-Image 文本模型-Text 模型训练类-Training 按训练流程分为数据分割、优化器选择、损失函数选择以及模型保存按业务分为全冠训练、
AI.Repair.FullCrown.train(self, torch_path=None, pt_path=None,batch_size=1,num_workers=1,start_epoch=0,end_epoch=15000,shuffle=True): 1 2 3 4 5 6 7 8 9 10 11 12 13 def train (self, torch_path=None , pt_path=None ,batch_size=1 ,num_workers=1 ,start_epoch=0 ,end_epoch=15000 ,shuffle=True ): """ 进行训练 :param torch_path: (str)torch数据输出目录/训练数据目录,默认None(使用FullCrown对象的torch_path) :param pt_path: (str)历史/前一周期训练结果文件,默认None(使用FullCrown对象的pt_path) :param batch_size: (int)批量大小,默认1 :param num_workers: (int)线程数,默认1 :param start_epoch: (int)训练起始周期,默认0 :param end_epoch: (int)训练结束周期,默认15000 :param shuffle: (bool)是否打乱顺序,默认Ture :return:None """
AI.Segmentation.MeshSeg.train(self,num_epochs=2000): 1 2 3 4 5 6 7 def train (self,num_epochs=2000 ): """ 模型训练 :param num_epochs: (int)训练周期,默认2000 :return: None """
AI.DentalInlay.DentalInlay.train(dataroot=None,,checkpoints_dir=”C:\“,batch_size=8, name=”dental_pix2pix”, model_type=”pix2pix”): 1 2 3 4 5 6 7 8 9 10 11 def train (dataroot=None ,checkpoints_dir="C:\\" ,batch_size=8 , name="dental_pix2pix" , model_type="pix2pix" ): """ 实现嵌体生成训练 :param dataroot:(str)参与训练的图片目录,默认None :param checkpoints_dir:(str)生成的pth文件存储的目录,默认"C:\\" :param batch_size:(int)批量大小,默认8 :param name:(str)训练的模型与样本所存储的文件夹的名称,默认"dental_pix2pix" :param model_type:(str)模型类型,默认pix2pix :return:None """
原始代码中是每五周期保存一份当前周期的训练结果文件并更新latest_net_D.pth与latest_net_G.pth,由于这样会导致整个文件夹内容过大现仅实现更新训练生成的pth文件存储在:checkpoints_dir/name训练过程中的图片存储目录:checkpoints_dir / name + ‘/web/images’推理生成的html存储目录:checkpoints_dir / name + ‘/web’
数据分割-DataPartition 优化器选择-Optimizer 损失函数选择-LossFunction 推理类-Inference 按目的分为分割推理、分类推理、生成推理以及检测推理
分割推理-Segmentation 分类推理-Classification 生成推理-Generation AI.Repair.FullCrown.generate_pcd(self,mesh_path,out_path) 1 2 3 4 5 6 7 8 def generate_pcd (self,mesh_path,out_path ): """ 实现单份点云模型的生成推理 :param mesh_path(str): 未修复模型的路径 :param out_path(str): 生成模型的输出路径 :return:None """
AI.Repair.FullCrown.generate_vol(self,mesh_path,out_path) 1 2 3 4 5 6 7 8 9 def generate_vol (self,mesh_path,out_path,batch_size=167800 ): """ 实现单份体素模型的生成推理 :param mesh_path: (str)未修复模型的路径 :param out_path: (str)生成模型的输出路径 :param batch_size: (int)批量大小,默认167800 :return: None """
AI.Repair.FullCrown.generate_all_vol(self,generate_path=None,pt_path=None): 1 2 3 4 5 6 7 8 def generate_all_vol (self,generate_path=None ,pt_path=None ): """ 实现整个目录下模型的生成推理,调用的是generate_vol :param generate_path: (str)推理数据目录,默认None(使用FullCrown对象的generate_path) :param pt_path: (str)历史/前一周期训练结果文件,默认None(使用FullCrown对象的pt_path) :return:None """
AI.DentalInlay.DentalInlay.inference(dataroot=None, checkpoints_dir=”C:/“,name=”experiment_name”,direction=”BtoA”): 1 2 3 4 5 6 7 8 9 10 def inference (dataroot=None , checkpoints_dir="C:/" ,name="dental_pix2pix" ,direction="BtoA" ): """ 实现嵌体生成推理,onnx模型生成 :param dataroot:(str)参与推理的图片目录 :param checkpoints_dir:(str)训练生成的pth文件存储的目录,默认"C:\\" :param name:(str)推理的模型所存储的文件夹的名称,默认"dental_pix2pix" :param direction:(str)推理方向,默认BtoA :return:None """
生成的onnx文件存储目录:checkpoints_dir / name推理生成的图片输出目录:’./results_dir/‘ + name + ‘/test_last/images’推理生成的html输出目录:’./results_dir/‘ + name + ‘/test_last’在计算平均SSIM时,原本sum += i,现改为sum += 1
AI.DentalInlay.DentalInlay.Inference_model(onnx_path,dataroot=None,name=”dental_pix2pix”,direction=” BtoA”) 1 2 3 4 5 6 7 8 9 10 def Inference_model (checkpoints_dir="C:/" ,dataroot=None ,name="dental_pix2pix" ,direction=" BtoA" ): """ 利用.onnx模型实现嵌体生成推理 :param checkpoints_dir:(str)onnx模型存储的目录,默认"C:\\" :param dataroot:(str)参与推理的图片目录 :param name:推理的模型所存储的文件夹的名称,默认"dental_pix2pix" :param direction:(str)推理方向,默认BtoA :return:None """
调用的onnx文件的存储目录:checkpoints_dir / name推理生成的图片输出目录: 当前文件所在的目录下
检测推理-Measurement 显示类-Show AI.Repair.FullCrown.show(self,sources_path,target_path) 1 2 3 4 5 6 7 8 def show (self,sources_path,target_path ): """ 实现单份数据的原始数据与推理结果显示 :param sources_path: (str)原始地址 :param target_path: (str)修复后模型的地址 :return: None """
AI.Repair.FullCrown.show_all(self,generate_path=None): 1 2 3 4 5 6 7 def show_all (self,generate_path=None ): """ 实现整个地址路径下的所有原始数据与推理结果显示 :param generate_path: (str)推理数据目录,默认None(使用FullCrown对象的generate_path) :return: None """
一键式-Run 全冠生成 AI.Repair.FullCrown.run(self,process:bool = True,train:bool = True,generate:bool = True,show:bool = True): 1 2 3 4 5 6 7 8 9 10 def run (self,process:bool = True ,train:bool = True ,generate:bool = True ,show:bool = True ): """ 包括训练在内的整个流程实现:数据处理->训练->推理->显示 :param process: (bool)是否进行数据处理,默认True :param train: (bool)是否进行训练,默认True :param generate: (bool)是否进行模型推理,默认True :param show: (bool)是否进行显示,默认True :return: None """
部署类-Deploy 1 2 3 4 5 6 7 def default (self, obj ): """ 自定义json编码器 :param obj:编译对象 :return:目标格式的对象 """
1 2 3 4 5 6 7 8 def DictToJson (data,out_path="out.json" ): """ 将字典保存为json格式保存 :param data:需要保存的数据 :param out_path: (str)保存地址,默认out.json :return: None """
1 2 3 4 5 6 7 8 def json_to_ply (json_path:str ,out_dir ): """ 将分牙json字典,转发成ply输出 :param json_path: (str)json字典路径 :param out_dir: (str)ply输出输出路径 :return: None """
1 2 3 4 5 6 7 def show_json (json_path ): """ 将json结果进行渲染显示 :param json_path: (str)json字典路径 :return: None """
正畸部署-OrthodonticDeploy class ToothSeg: 调用AI模型进行分牙实现: 数据处理;推理;结果优化;
AI.Deploy.OrthodonticDeploy.ToothSeg.init (self, mesh_path, model_path,devices=’CPUExecutionProvider’, num_classes=15): 1 2 3 4 5 6 7 8 9 10 def __init__ (self, mesh_path, model_path, devices='CPUExecutionProvider' , num_classes=15 ): """ 定义ToothSeg :param mesh_path:(str)需要分牙的网格的路径 :param model_path:(str)分牙模型的路径 :param devices:(str)模型推理设备,默认'CPUExecutionProvider' :param num_classes:(int)当前模型支持分割类数,默认15 """
AI.Deploy.OrthodonticDeploy.ToothSeg._remove_overlapping_triangles(self,m: trimesh.Trimesh): 1 2 3 4 5 6 7 def _remove_overlapping_triangles (self,m: trimesh.Trimesh ) -> trimesh.Trimesh: """ 删除重叠的三角面片 :param m : (trimesh.Trimesh)需要处理的网格模型 :return cleaned_mesh :(trimesh.Trimesh)清除重叠面片后的网格模型 """
原注释为“删除重叠的三角面片”,实际是对共面的相邻面进行处理,面片数会增加,则其原本的目的是什么?@sindre(sindre)
AI.Deploy.OrthodonticDeploy.ToothSeg.prepare(self): 1 2 3 4 5 6 def ToothSeg .prepare(self ): """ 实现模型预处理,包括删除离群点与重复面片, :return:None """
正则化特征[-1,1]的for循环内是正态分布向标准正态分布的转换过程,则原始面片与法线是怎样遵循正态分布的
A_S&A_L设置的目的
AI.Deploy.OrthodonticDeploy.ToothSeg.infer(self, model_path): 1 2 3 4 5 6 7 def infer (self, model_path ): """ 推理 :param model_path: (str) 实现推理的模型地址 :return data: ([(1,n,15)float32])完成推理后的结果,其内容包括面片的三个点坐标、重心坐标以及法向量 """
AI.Deploy.OrthodonticDeploy.ToothSeg.optimized(self, tensor_prob_output): 1 2 3 4 5 6 7 def optimized (self, tensor_prob_output ): """ 推理结果数据优化 :param tensor_prob_output: ([(1,n,15)float32])推理结果 :return data: ([(1,n,15)float32])精炼优化后的结果 """
@sindre(sindre)
beta的意义,常数(向量内积)取模的意义
edges的第三个值(权重)的计算方式/公式
is_upper的意义
267为什么会有零散的面片(nei==0),内含四个是“删除重叠面片”里添的,1-3是正常状态,此处处理的是预处理后的模型。
AI.Deploy.OrthodonticDeploy.ToothSeg.run(self, json_out_path): 1 2 3 4 5 6 7 def run (self, json_out_path ): """ 实现分牙的整个流程 :param json_out_path:(str)分牙结果的json输出地址 :return:None """
AI.Deploy.OrthodonticDeploy.ToothSeg.KNN(self, json_path, target_mesh_path, json_out_path): 1 2 3 4 5 6 7 8 9 def KNN (self, json_path, target_mesh_path, json_out_path ): """ 对结果进行knn映射 :param json_path: (str)当前分牙json文件 :param target_mesh_path: (str)目标mesh路径 :param json_out_path: (str)结果输出路径 :return: None """
class ToothArrange: 调用AI模型进行排牙实现:数据处理;推理;结果优化;
AI.Deploy.OrthodonticDeploy.ToothArrange.init (self, data_list, out_dir, model_path=”14牙弓.npy”): 1 2 3 4 5 6 7 8 9 def __init__ (self, data_list, out_dir, model_path="14牙弓.npy" ): """ 定义ToothArrange :param data_list (list): 需要排牙的牙齿teeth_list,文件命名需符合 _tooth_牙位号.ply :param model_path (str): 目标排牙模型的路径 :param out_dir (str): 排牙后输出目录,默认"14牙弓.npy" """
AI.Deploy.OrthodonticDeploy.ToothArrange.prepare(self): 1 2 3 4 5 6 7 def prepare (self ): """ 读入原始牙齿模型 :return: None """
AI.Deploy.OrthodonticDeploy.ToothArrange.infer(self): 1 2 3 4 5 6 7 def infer (self ): """ 实现排牙 :return: None """
AI.Deploy.OrthodonticDeploy.ToothArrange.optimized(self): 1 2 3 4 5 6 7 def optimized (self ): """ 结果优化 pass """
AI.Deploy.OrthodonticDeploy.ToothArrange.run(self): 1 2 3 4 5 6 7 def run (self ): """ 实现排牙的整个流程 :return: None """
class GumGen: 通过模板牙龈进行牙列拟合,从而实现”牙龈生成”
AI.Deploy.OrthodonticDeploy.GumGen.init (self, teeth_list, gum_path, seg_list): 1 2 3 4 5 6 7 8 def __init__ (self, teeth_list, gum_path, seg_list ): """ 定义GumGen :param teeth_list: list(str)牙齿数据列表,需要 牙位号.ply 结尾 :param gum_path: (str)模板牙龈stl文件的路径 :param seg_list: (str)分割后牙列路径 """
AI.Deploy.OrthodonticDeploy.GumGen.get_teeth_edge_points(self): 1 2 3 4 5 6 def get_teeth_edge_points (self ): """ 获取牙列网格与牙列数据 :return: None """
AI.Deploy.OrthodonticDeploy.GumGen.get_gum_edge_points(self): 1 2 3 4 5 6 def get_gum_edge_points (self ): """ 获取牙龈数据 :return: None """
AI.Deploy.OrthodonticDeploy.GumGen.fitting(self): 1 2 3 4 5 6 def fitting (self ): """ 原始的牙龈向目标牙进行匹配形变,生成形变后的牙龈网格 :return: None """
AI.Deploy.OrthodonticDeploy.GumGen.export(self, out_path): 1 2 3 4 5 6 7 def export (self, out_path ): """ 实现牙龈生成的整个流程并导出牙齿和牙龈 :param out_path: (str)文件输出路径 :return:None """
AI.Deploy.OrthodonticDeploy.GumGen.show(self): 1 2 3 4 5 6 def show (self ): """ 显示牙齿和牙龈 :return: None """
class Orthodontic: 正畸整个流程实现:数据修复–>分牙–>排牙–>生成牙龈
AI.Deploy.OrthodonticDeploy.Orthodontic.init (self, mesh_path, model_path,arrange_model): 1 2 3 4 5 6 7 8 def __init__ (self, mesh_path, model_path,arrange_model ): """ 定义Orthodontic :param mesh_path: (str)原始网格模型路径 :param model_path: (str)分牙模型路径 :param arrange_model: (str)标准牙弓线路径 """
AI.Deploy.OrthodonticDeploy.Orthodontic.DataRepair(self): 1 2 3 4 5 6 def DataRepair (self ): """ 数据修复方法 pass """
AI.Deploy.OrthodonticDeploy.Orthodontic.ToothSeg(self, out_dir): 1 2 3 4 5 6 7 def ToothSeg (self, out_dir ): """ 牙齿分割 :param out_dir: (str)分牙后单颗牙的输出目录 :return:None """
AI.Deploy.OrthodonticDeploy.Orthodontic.ToothArrange(self, out_dir): 1 2 3 4 5 6 7 def ToothArrange (self, arrange_out_dir ): """ 牙齿排列 :param arrange_out_dir:(str)排牙后输出目录 :return:None """
AI.Deploy.OrthodonticDeploy.Orthodontic.GumsGen(self, gum_out_dir): 1 2 3 4 5 6 7 def GumsGen (self, gum_out_dir ): """ 牙龈生成 :param gum_out_dir: (str)牙龈生成后输出目录 :return:None """
AI.Deploy.OrthodonticDeploy.Orthodontic.run(self, gum_out_dir, arrange_out_dir, seg_out_dir): 1 2 3 4 5 6 7 8 9 def run (self, seg_out_dir, arrange_out_dir, gum_out_dir ): """ 实现正畸整个流程 :param seg_out_dir: (str)分牙后单颗牙的输出目录 :param arrange_out_dir: (str)排牙后输出目录 :param gum_out_dir: (str)牙龈生成后输出目录 :return:None """
AI.Deploy.OrthodonticDeploy.Orthodontic.ShowSeg(self): 1 2 3 4 5 6 7 def ShowSeg (self ): """ 显示分牙结果 pass """
AI.Deploy.OrthodonticDeploy.Orthodontic.ShowArrange(self): 1 2 3 4 5 6 7 def ShowArrange (self ): """ 显示排牙结果 pass """