Intro
I extracted my mate’s (approximately 60×60 pixel) face from a Facebook picture, and overlaid it onto a depth-map for a similarly shaped face, then used a custom python script to create a 3d wavefront model of his face, and an accompanying .mtl file for the texture.
I will create a post soon properly dissecting the script, and commenting-in some better explanations.
Source Images:
Video:
Code:
Depthmap to mesh converter and material generator.
from PIL import Image,ImageDraw
Faces=[]
def load_heightmap(heightmap="Heightmap.png",texture="boon.png",Scale=1.25): ##Scale is inversed so scale=2 means half the resolution of the source image
#vertices=[] ##uncomment for 2d array of vertices
verticesflat=[]
faces=[]
Height_Im=Image.open(heightmap)
Tex_Im=Image.open(texture)
Width=width=Height_Im.size[0]
trueWidth=int(Width/Scale)-2
Height=height=Height_Im.size[1]
trueHeight=int(Height/Scale)-2
tex_coord=[]
colsflat=[]
for yn in range(0,trueHeight,1): ###iterate through each row
y=yn*Scale
#vertices.append([])##uncomment for 2d array of vertices
for xn in range(0,trueWidth,1):##iterate through each pixel in the row
x=xn*Scale
depth=25-(Height_Im.getpixel((x,y))[0]+Height_Im.getpixel((x+1,y))[0]+Height_Im.getpixel((x+2,y))[0]+Height_Im.getpixel((x+3,y))[0])/(4*Scale)
Col=Tex_Im.getpixel((x,y))
verticesflat.append((xn,yn,depth))##uncomment for flat array of vertices
tex_coord.append((xn/trueWidth,yn/trueHeight))
colsflat.append(Col)
#vertices[yn].append((x,y,depth))##uncomment for 2d array of vertices
topleft=yn*trueWidth+xn
topright=yn*trueWidth+xn+1
bottomright=(yn+1)*trueWidth+xn+1
bottomleft=(yn+1)*trueWidth+xn
faces.append((topleft,topright,bottomright))
faces.append((topleft,bottomright,bottomleft))
xn=trueWidth-1
x=xn*Scale
depth=25-(Height_Im.getpixel((x,y))[0]+Height_Im.getpixel((x+1,y))[0]+Height_Im.getpixel((x+2,y))[0]+Height_Im.getpixel((x+3,y))[0])/(4*Scale)
verticesflat.append((xn,yn,depth))##uncomment for flat array of vertices
tex_coord.append((xn/trueWidth,yn/trueHeight))
Col=Tex_Im.getpixel((x,y))
colsflat.append((x,y,depth))##uncomment for flat array of vertices
yn=trueHeight-1
y=yn*Scale
for xn in range(0,int(Width/Scale)-2,1):
x=xn*Scale
depth=25-(Height_Im.getpixel((x,y))[0]+Height_Im.getpixel((x+1,y))[0]+Height_Im.getpixel((x+2,y))[0]+Height_Im.getpixel((x+3,y))[0])/(4*Scale)
Col=Tex_Im.getpixel((x,y))
verticesflat.append((xn,yn,depth))##uncomment for flat array of vertices
tex_coord.append((xn/trueWidth,yn/trueHeight))
colsflat.append(Col)
#vertices[yn].append((x,y,depth))##uncomment for 2d array of vertices
xn=trueWidth-1
x=xn*Scale
depth=25-(Height_Im.getpixel((x,y))[0]+Height_Im.getpixel((x+1,y))[0]+Height_Im.getpixel((x+2,y))[0]+Height_Im.getpixel((x+3,y))[0])/(4*Scale)
verticesflat.append((xn,yn,depth))##uncomment for flat array of vertices
tex_coord.append((xn/trueWidth,yn/trueHeight))
Col=Tex_Im.getpixel((x,y))
colsflat.append((x,y,depth))##uncomment for flat array of vertices
return verticesflat,colsflat,faces,tex_coord
def create_material(materialname,mapfile,maptype="Kd",ambientlighting=(1,1,1),diffusivelighting=(1,1,1),specularlighting=(1,1,1),specularexponent=1,refractiveindex=1,illuminationmodel=1):
return """newmtl %s
Ka %f %f %f
Kd %f %f %f
Ks %f %f %f
Ns %f
Ni %f
d 1.000000
illum %s
map_%s %s"""%(materialname,ambientlighting[0],ambientlighting[1],ambientlighting[2],diffusivelighting[0],diffusivelighting[1],diffusivelighting[2],
specularlighting[0],specularlighting[1],specularlighting[2],specularexponent,refractiveindex,illuminationmodel,maptype,mapfile)
#heightmap="Heightmap.png"
#texture="boon.png"
def heightmap_texture_to_3d(heightmapfilename,texturefilename,filename="testout.obj",materialname="test",materialfilename="testmaterial.mtl",Scale=4):
mesh=load_heightmap(heightmapfilename,texturefilename,Scale=Scale)
fileout=open(filename,"w")
fileout.write("mtllib %s\n"%materialfilename)
for pos in range(len(mesh[0])):
i=mesh[0][pos]
col=mesh[1][pos]
fileout.write("v %s %s %s\n"%(i[0],i[1],i[2]))
for tex in mesh[3]:
fileout.write("vt %s %s\n"%(str(tex[0])[:6],str(tex[1])[0:6]))
fileout.flush()
fileout.write("usemtl %s\n"%materialname)
for face in mesh[2]:
fileout.write("f %s/%s %s/%s %s/%s\n"%(face[0]+1,face[0]+1,face[1]+1,face[1]+1,face[2]+1,face[2]+1))
fileout.flush()
fileout.close()
materialout=open(materialfilename,"w")
materialout.write(create_material(materialname,texturefilename))
materialout.flush()
materialout.close()
heightmap_texture_to_3d("Heightmap.png","boon.png",Scale=1.25,filename="EnormousSmoothBoon.obj",materialname="boon",materialfilename="boon.mtl")
Related post:
.Obj in R5RS Scheme (Lisp)
R5RS Scheme 3d Extruder (Lisp)
0