- PVSM.RU - https://www.pvsm.ru -

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

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

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

Ссылка на Github [2]

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 модели по яркостям пикселей на фотографии. Я взял вот это фото снизу.

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

Изображение обрабатывается (для лучшего результата) с помощью библиотеки 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 модель.

Как создавать 3d модели с помощью Python - 3
Часть кода, создающая координаты.


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')

Автор: Mars

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/python/278526

Ссылки в тексте:

[1] подробнее в этой статье: https://geektimes.ru/post/299525/

[2] Ссылка на Github: https://github.com/Neptune-1/Github_submarine/

[3] Источник: https://geektimes.ru/post/300211/?utm_campaign=300211