Convierte cualquier imagen 2D en escultura imprimible en 3D con código

Estoy tratando de convertir una imagen 2D en una escultura imprimible en 3D usando solo el código. Primero me gustaría saber si se puede hacer con solo un script. Ya conozco Python y C y sería genial, por supuesto, si pudiera usar uno de estos para hacer lo que quiero.

Aquí hay dos enlaces para que veas lo que quiero decir al decir “Convertir cualquier imagen 2D en una escultura imprimible en 3D” (pero estos están usando software):

https://www.youtube.com/watch?v=ngZwibfaysc

Para ser más específico, quiero insertar una imagen y solo esperar a obtener el resultado, que será una escultura en 3D.

Fue un poco curioso, así que codifiqué un pequeño ejemplo de encoding de superficie de iluminación

  • para cada píxel de la height = (color_intensity)*scale imagen de entrada height = (color_intensity)*scale

Esta es la imagen de entrada que probé (primera pintura al óleo agradable en la búsqueda de Google) :

entrada

Este es el resultado (vista previa en 3D de la nube de puntos)

salidasalida

A la izquierda está el gif animado, así que recargue / actualice la página para ver la animación si ya está detenida o descargue el gif y ábrala con un poco más de tendencia, luego baje el color marrón para la vista previa del gif … A la derecha está la vista previa de la nube de puntos de colores (imagen estática)

Este es el código C ++ para calcular esto:

 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>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>1),picx=1;picx 

Aquí el código de vista previa de 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>1),picx=1;picx 

Las matrices se establecen de esta manera:

 // 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 

[notas]

Estoy usando mi propia clase de imágenes, así que aquí algunos miembros:

  • xs,ys tamaño de imagen en pixeles
  • p[y][x].dd es el píxel en la posición (x, y) como tipo entero de 32 bits
  • p[y][x].db[4] es el acceso a píxeles mediante bandas de color (r, g, b, a)

También estoy usando OpenGl scr y textura Clases personalizados:

  • xs,ys tamaño del buffer en pixeles
  • Texture::txr es un puntero de píxel de 32 bits (la imagen se asigna como una matriz lineal 1D)
  • mapa de altura se utiliza para almacenar valores int
  • Los mapas normales se utilizan para almacenar componentes vectoriales flotantes normales.

Lo único que queda por hacer es:

  1. Filtra la nube de puntos a tu gusto.
  2. triangular / exportar a una malla soportada por su impresora

Hay otras formas de codificar la iluminación en superficie:

  1. Usted puede hacer algo como la superficie de la lente de Fresnel

    • así que divide la malla en segmentos
    • y desplace cada uno de ellos para que comience desde el mismo plano de referencia (desplazamiento z)

    Eso necesita mucho menos volumen / material.

    altura normal vs. codificación de Fresnel

    La primera mitad de la animación es la encoding de altura normal, luego se cambia a la encoding / empaque de la superficie de Fresnel para comparación

  2. codifique la iluminación no como mapa de altura sino como mapa de rugosidad en su lugar

    • Cada píxel será mapeado en un pequeño mapa de subtelarios
    • La superficie plana es alta iluminación / intensidad de color.
    • la superficie rugosa es negra
    • y en el medio son los tonos de gris

    Esto será visible también desde angularjs y puede ser relativamente delgado, por lo que se necesita muy poco material para esto (mucho menos que la bala anterior)

  3. Mapa de altura real (representación de malla 3D real)

    Es muy complicado que necesite normalizar los colores, las sombras y los artefactos de iluminación, por lo que solo queda el sombreado normal (ya que la superficie es de un solo material, color, brillo, rugosidad ...) y solo entonces extraiga el mapa de altura. Para eso, necesita muchas cosas como segmentación, restricción adaptativa, filtrado y mucho más ... Por último, agregue el interior vacío y agregue paredes de soporte para que la malla se mantenga unida mientras / después de la impresión.