Как создавать 3d модели с помощью Python

Привет, Хабр! Однажды мне потребовалось создать 3d модель дна, подробнее в этой статье. Сегодня я хочу рассказать о том, как можно создавать 3D модели Python 3. Способов для этого достаточно много: blender python api, Vpython… Но я хочу рассказать, как делать модели используя только Python.

Как создавать 3d модели с помощью Python

Ссылка на Github

STL

Для этого нужно понять, как работает формат stl (популярный формат 3D файлов).
Вся модель в этом формате состоит из множества треугольников, поэтому файл состоит из 3-х мерных координат их вершин.

STL-файл

solid
facet normal 0 0 0
outer loop
vertex 0 0 0
vertex 1 0 0
vertex 1 1 0
endloop
endfacet
facet normal 0 0 0
outer loop
vertex 1 1 0
vertex 0 0 0
vertex 0 1 0
endloop
endfacet
endsolid

Пример

Я хотел бы показать, как реализовать создание 3D модели по яркостям пикселей на фотографии. Я взял вот это фото снизу.

Изображение обрабатывается (для лучшего результата) с помощью библиотеки opencv.

import cv2 import numpy as np  cd_1=['0', '0', '0']# создание массива для хранения координат 1 вершины cd_2=['0', '0', '0']# создание массива для хранения координат 2 вершины cd_3=['0', '0', '0']# создание массива для хранения координат 3 вершины  file_stl='new.stl' file_im=r'C:UsersallexPictures2.jpg'# путь к изображению op_stl=open(file_stl, 'w') op_im=cv2.imread(file_im)  gray = cv2.cvtColor(op_im, cv2.COLOR_BGR2GRAY)#преобразование в чб изображение blur = cv2.GaussianBlur(gray,(0,0),1)# небольшое размытие для сглажеввания шумов res=cv2.resize(blur,(320,240))# преобразование изображения к размеру 320*240 

Снизу функция, принимающая 3 массива с координатами вершин треугольника и записывающая в файл 1 треугольную грань.

 def face_file_stl(cd_1, cd_2, cd_3): 	op_stl.write("facet normal 0 0 0") 	op_stl.write("outer loop") 	op_stl.write("vertex " + "  ".join(cd_1))#запись в файл координаты 1 вершины 	op_stl.write("vertex " + " ".join(cd_2))#запись в файл координаты 2 вершины 	op_stl.write("vertex " + " ".join(cd_3))#запись в файл координаты 3 вершины 	op_stl.write("endloop ntendfacet") 

Теперь самое главное — создание правильных координат вершин треугольников из которых состоит 3D модель.


Часть кода, создающая координаты.

 for i in range(size.shape[1]):#перебор пикселей по ширине           for k in range(size.shape[0]-1):#перебор пикселей по высоте               if i!=size.shape[1]-1:                      try: #making the first triangls  for relief                         cd_1=[str(i),     str(k),   str(blur[k, i])   ]                         cd_2=[str(i + 1), str(k),   str(blur[k, i+1]) ]                         cd_3=[str(i+1),   str(k+1), str(blur[k+1,i+1])]                                            except:                         print('er')                      face_file_stl(cd_1, cd_2, cd_3)                      try: #making the second triangls  for relief                         cd_1=[str(i),     str(k),   str(blur[k, i])    ]                         cd_2=[str(i+1),   str(k+1), str(blur[k+1, i+1])]                         cd_3=[str(i),     str(k+1), str(blur[k+1,i])   ]                        except:                         print('er')                      face_file_stl(cd_1, cd_2, cd_3) 

Собственно, это все, что я хотел написать до следующей статьи.

Весь код

import cv2 import numpy as np cd_1=['0', '0', '0']# создание массива для хранения координат 1 вершины cd_2=['0', '0', '0']# создание массива для хранения координат 2 вершины cd_3=['0', '0', '0']# создание массива для хранения координат 3 вершины file_stl='new.stl' file_im=r'C:UsersallexPictures22.jpg'# путь к изображению op_stl=open(file_stl, 'w') op_im=cv2.imread(file_im)  gray = cv2.cvtColor(op_im, cv2.COLOR_BGR2GRAY)#преобразование в чб изображение blur = cv2.GaussianBlur(gray,(0,0),1)# небольшое размытие для сглажеввания шумов blur=cv2.resize(blur,(320,240)) print(blur.shape[1]) #cv2.imshow("jj",gray) #cv2.waitKey(1000) x=0 y=0 file='STL_project-1.stl' o_1="nt" o_2="ntt" o_3="nttt" op_stl.write("solid") def face_file_stl(cd_1, cd_2, cd_3): 	op_stl.write(o_1+"facet normal 0 0 0") 	op_stl.write(o_2 + "outer loop") 	op_stl.write(o_3 + "vertex " + " ".join(cd_1))#запись в файл координаты 1 вершины 	op_stl.write(o_3 + "vertex " + " ".join(cd_2))#запись в файл координаты 2 вершины 	op_stl.write(o_3 + "vertex " + " ".join(cd_3))#запись в файл координаты 3 вершины 	op_stl.write(o_2 + "endloop ntendfacet")  #making the first triangls  for base for i in range(blur.shape[1]-1):       cd_1=[str(i),"0","0"]       cd_3=[str(i+1),str(blur.shape[0]-1),"0"]       cd_2=[str(i),str(blur.shape[0]-1),"0"]       face_file_stl(cd_1, cd_2, cd_3) #making the second triangls  for base       for i in range(blur.shape[1]-1):       cd_1=[str(i+1),str(blur.shape[0]-1),"0"]       cd_3=[str(i),"0","0"]       cd_2=[str(i+1),"0","0"]       face_file_stl(cd_1, cd_2, cd_3) #base has done  for i in range(blur.shape[1]):         if i%30==0:             print(i)         for k in range(blur.shape[0]-1):#making the first triangls  for relief             if i!=blur.shape[1]-1:                     try:                                                  cd_1=[str(i),     str(k),   str(blur[k, i])   ]                         cd_2=[str(i + 1), str(k),   str(blur[k, i+1]) ]                         cd_3=[str(i+1),   str(k+1), str(blur[k+1,i+1])]                                            except:                         print('er')                     face_file_stl(cd_1, cd_2, cd_3) 			        #for j in range(blur.shape[1]-1):#making the second triangls  for relief                     try:                         cd_1=[str(i),  str(k),   str(blur[k, i])    ]                         cd_2=[str(i+1),str(k+1), str(blur[k+1, i+1])]                         cd_3=[str(i),  str(k+1), str(blur[k+1,i])   ]                        except:                         print('er')                     face_file_stl(cd_1, cd_2, cd_3) #relief has done  #making the first triangls  for right side         for i in range(blur.shape[1]):      if i!=blur.shape[1]-1:       try:             cd_1=[str(i),str(blur.shape[0]-1),"0"]             cd_3=[str(i+1),str(blur.shape[0]-1),str(blur[blur.shape[0]-1, i+1])]             cd_2=[str(i),str(blur.shape[0]-1),str(blur[blur.shape[0]-1, i])]                    except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)        #making the second triangls  for right side            try:             cd_1=[str(i),str(blur.shape[0]-1),"0"]             cd_3=[str(i+1),str(blur.shape[0]-1),"0"]             cd_2=[str(i+1),str(blur.shape[0]-1),str(blur[blur.shape[0]-1, i+1])]       except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)       if i!=blur.shape[1]-1:       try:             cd_1=[str(i),'0',"0"]             cd_2=[str(i+1),'0',str(blur[0, i+1])]             cd_3=[str(i),'0',str(blur[0, i])]                    except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)        #making the second triangls  for right side            try:             cd_1=[str(i),'0',"0"]             cd_2=[str(i+1),'0',"0"]             cd_3=[str(i+1),'0',str(blur[0, i+1])]       except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)  for i in range(blur.shape[0]):    if i!=blur.shape[0]-1:       try:             cd_1=['0',str(i),"0"]             cd_3=['0',str(i+1),str(blur[ i+1,0])]             cd_2=['0',str(i),str(blur[i,0])]                    except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)        #making the second triangls  for right side            try:             cd_1=['0',str(i),"0"]             cd_3=['0',str(i+1),"0"]             cd_2=['0',str(i+1),str(blur[i+1,0])]       except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)           try:             cd_2=[str(blur.shape[1]-1),str(i),"0"]             cd_3=[str(blur.shape[1]-1),str(i+1),str(blur[ i+1,blur.shape[1]-1])]             cd_1=[str(blur.shape[1]-1),str(i),str(blur[i,blur.shape[1]-1])]                   except:             print("er")       face_file_stl(cd_1, cd_2, cd_3)        #making the second triangls  for right side            try:             cd_2=[str(blur.shape[1]-1),str(i),"0"]             cd_3=[str(blur.shape[1]-1),str(i+1),"0"]             cd_1=[str(blur.shape[1]-1),str(i+1),str(blur[i+1,blur.shape[1]-1])]       except:             print("er")        face_file_stl(cd_1, cd_2, cd_3)  op_stl.write("nendsolid" ) op_stl.close()      print('end') 

 
Источник

Читайте также