Olu*_*eri 5 c python 3d image image-processing
我正在尝试使用代码将2D图像转换为3D可打印雕塑.首先,我想知道是否可以只使用脚本来完成它?我已经知道Python和C了,如果我可以使用其中一个做我想做的事情,那将是很棒的.
这里有两个链接供您查看我的意思,说"将任何2D图像转换为3D可打印雕塑"(但这些都是使用软件):
https://www.youtube.com/watch?v=ngZwibfaysc
https://www.youtube.com/watch?v=-fe2zxcKSic
更具体地说,我想插入一个图像,然后等待获得3D雕塑的结果.
Spe*_*tre 12
有点奇怪所以我编码了一个照明表面编码的小例子
height = (color_intensity)*scale
这是我测试的输入图像(谷歌搜索中的第一个漂亮的油画):
这是结果(点云3D预览)
在左边是动画gif,所以重新加载/刷新页面,看动画,如果它已经停止或下载gif并打开更多的东西然后棕色的gif预览...在右边是彩色点云预览(静态图像)
这是用于计算的C++代码:
OpenGLtexture zed,nx,ny,nz; // height map,normal maps (just 2D images)
picture pic; // source image
int x,y,a;
// resize textures to source image size
zed.resize(pic.xs,pic.ys);
nx.resize(pic.xs,pic.ys); float *pnx=(float*) nx.txr;
ny.resize(pic.xs,pic.ys); float *pny=(float*) ny.txr;
nz.resize(pic.xs,pic.ys); float *pnz=(float*) nz.txr;
// prepare tmp image for height map extraction
picture pic0;
pic0=pic; // copy
pic0.rgb2i(); // grayscale
// this computes the point cloud (this is the only important stuff from this code)
// as you can see there are just 3 lines of code important from all of this
for (a=0,y=0;y<pic.ys;y++)
for (x=0;x<pic.xs;x++,a++)
zed.txr[a]=pic0.p[y][x].dd>>3; // height = intensity/(2^3)
// compute normals (for OpenGL rendering only)
double n[3],p0[3],px[3],py[3];
int zedx,zedy,picx,picy;
for (a=zed.xs,zedy=-(pic.ys>>1),picy=1;picy<pic.ys;picy++,zedy++)
for (a++, zedx=-(pic.xs>>1),picx=1;picx<pic.xs;picx++,zedx++,a++)
{
vector_ld(p0,zedx-1,zedy ,-zed.txr[a -1]); // 3 neighboring points
vector_ld(py,zedx ,zedy-1,-zed.txr[a+zed.xs ]);
vector_ld(px,zedx ,zedy ,-zed.txr[a ]);
vector_sub(px,p0,px); // 2 vectors (latices of quad/triangle)
vector_sub(py,p0,py);
vector_mul(n,px,py); // cross product
vector_one(n,n); // unit vector normalization
pnx[a]=n[0]; // store vector components to textures
pny[a]=n[1];
pnz[a]=n[2];
}
Run Code Online (Sandbox Code Playgroud)
这里是OpenGL预览代码(C++):
scr.cls(); // clear buffers
scr.set_perspective(); // set camera matrix
glMatrixMode(GL_MODELVIEW); // set object matrix
rep.use_rep();
glLoadMatrixd(rep.rep);
// directional (normal shading)
float lightAmbient [4]={0.20,0.20,0.20,1.00};
float lightDiffuse [4]={1.00,1.00,1.00,1.00};
float lightDirection[4]={0.00,0.00,+1.0,0.00};
glLightfv(GL_LIGHT1,GL_AMBIENT ,lightAmbient );
glLightfv(GL_LIGHT1,GL_DIFFUSE ,lightDiffuse );
glLightfv(GL_LIGHT1,GL_POSITION,lightDirection);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
glDisable(GL_TEXTURE_2D);
glEnable(GL_COLOR_MATERIAL);
// render point cloud
int zedx,zedy,picx,picy,a;
glColor3f(0.7,0.7,0.7);
float *pnx=(float*)nx.txr;
float *pny=(float*)ny.txr;
float *pnz=(float*)nz.txr;
glBegin(GL_POINTS);
for (a=zed.xs,zedy=-(pic.ys>>1),picy=1;picy<pic.ys;picy++,zedy++)
for (a++, zedx=-(pic.xs>>1),picx=1;picx<pic.xs;picx++,zedx++,a++)
{
//glColor4ubv((BYTE*)&pic.p[picy][picx].dd); // this is coloring with original image colors but it hides the 3D effect
glNormal3f(pnx[a],pny[a],pnz[a]); // normal for lighting
glVertex3i(zedx ,zedy ,-zed.txr[a]); // this is the point cloud surface point coordinate
}
glEnd();
scr.exe(); // finalize OpenGL calls and swap buffers ...
scr.rfs();
Run Code Online (Sandbox Code Playgroud)
矩阵设置如下:
// gluProjection parameters
double f=100; //[pixels] focus
scr.views[0].znear= f; //[pixels]
scr.views[0].zfar =1000.0+f; //[pixels]
scr.views[0].zang = 60.0; //[deg] view projection angle
scr.init(this); // this compute the Projection matrix and init OpenGL
// place the painting surface in the middle of frustrum
rep.reset();
rep.gpos_set(vector_ld(0.0,0.0,-0.5*(scr.views[0].zfar+scr.views[0].znear)));
rep.lrotx(180.0*deg); // rotate it to match original image
Run Code Online (Sandbox Code Playgroud)
[笔记]
我正在使用自己的图片类,所以这里有一些成员:
xs,ys
图像大小,以像素为单位p[y][x].dd
是(x,y)位置的像素为32位整数类型p[y][x].db[4]
通过色带(r,g,b,a)进行像素访问我也在使用自定义OpenGl scr
和Texture Clases:
xs,ys
缓冲区大小,以像素为单位Texture::txr
是32位像素指针(图像被分配为线性1D阵列)剩下要做的唯一事情是:
还有其他方法可以将照明编码到表面:
你可以做一些像菲涅耳透镜表面的东西
这需要更少的体积/材料
动画的前半部分是正常高度编码,然后切换到菲涅耳曲面编码/打包进行比较
编码照明不是高度图,但如粗糙度地图代替
这也可以从角度看到,并且可以相对较薄,因此需要非常少的材料(远远少于之前的子弹)
真实高度图(真实3D网格表示)
你需要对颜色,阴影和光照效果进行标准化非常棘手,因此只留下正常的阴影(因为表面来自单一材质,颜色,光泽,粗糙度......),然后才提取高度图.为此你需要很多东西,比如分割,自适应阈值处理,过滤等等......最后添加空的内部并添加支撑墙,使网格在打印时/后保持在一起.
归档时间: |
|
查看次数: |
3100 次 |
最近记录: |