Поверните любое 2D-изображение в 3D-печатную скульптуру с кодом

Я пытаюсь преобразовать 2D-изображение в 3D-печатную скульптуру, используя только код. Сначала я хотел бы узнать, можно ли это сделать только с помощью скрипта? Я уже знаю Python и C, и было бы здорово, если бы я мог использовать один из них, чтобы делать то, что хочу.

Вот две ссылки для вас, чтобы понять, что я имею в виду, говоря «Поверните любой 2D-образ в 3D-печатную скульптуру» (но они используют программное обеспечение):

Чтобы быть более конкретным, я хочу вставить изображение и просто подождать, чтобы получить результат, который будет представлять собой 3D-скульптуру.

One Solution collect form web for “Поверните любое 2D-изображение в 3D-печатную скульптуру с кодом”

было немного любопытно, поэтому я закодировал небольшой пример кодирования поверхности освещения

  • для каждого пикселя height = (color_intensity)*scale входного изображения height = (color_intensity)*scale

Это входное изображение, которое я тестировал (сначала красивую масляную живопись в поиске Google) :

вход

Это результат (предварительный просмотр 3D-облака точек)

выводвывод

Слева – анимированная gif, чтобы перезагрузить / обновить страницу, чтобы увидеть анимацию, если она уже остановлена ​​или загрузится gif и откроется в чем-то более подходящем, чем brownser для предварительного просмотра 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]; } 

Здесь код предварительного просмотра 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(); 

Матрицы задаются следующим образом:

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

[заметки]

Я использую собственный класс изображения, поэтому здесь некоторые участники:

  • xs,ys Размер изображения в пикселях
  • p[y][x].dd – пиксель в позиции (x, y) как 32-битный целочисленный тип
  • p[y][x].db[4] – доступ к пикселям по цветным полосам (r, g, b, a)

Также я использую пользовательские скрипты OpenGl и Texture Clases:

  • xs,ys размер буфера в пикселях
  • Texture::txr – 32-разрядный указатель на пиксель (изображение выделяется как линейный 1D-массив)
  • height map используется для хранения значений int
  • нормальные карты используются для хранения нормальных векторных компонентов float

Осталось только:

  1. фильтровать pointcloud по своему вкусу
  2. triangulate / export to mesh, поддерживаемый вашим принтером

Существуют и другие способы кодирования освещения на поверхность:

  1. вы можете сделать что-то вроде поверхности линзы Френеля

    • поэтому разделите сетку на сегменты
    • и смещают каждый так, чтобы он начинался с одной и той же базовой плоскости (z offset)

    Это требует гораздо меньшего объема / материала

    нормальная высота против кодирования френеля

    Первая половина анимации – нормальная кодировка высоты, затем она переключается на кодирование / упаковку поверхности Френеля для сравнения

  2. закодировать подсветку не как карту высоты, а как карту неровностей вместо

    • каждый пиксель будет отображаться в малую карту высот
    • Плоская поверхность – высокая освещенность / интенсивность цвета
    • шероховатая поверхность черная
    • а между ними – оттенки серого

    Это будет видно также из-за углов и может быть относительно тонким, поэтому для этого требуется очень мало материала (намного меньше предыдущей пули)

  3. Реальная карта высоты (реальное представление сетки 3D)

    Очень сложно, что вам нужно нормализовать цвета, тени и артефакты освещения, чтобы оставалось только обычное затенение (поскольку поверхность из одного материала, цвета, блеска, шероховатости …) и только затем извлекает карту высоты. Для этого вам нужно много вещей, таких как сегментация, адаптивное подделки, фильтрация и многое другое … Наконец, добавьте пустое внутри и добавьте опорные стенки, чтобы сетка держалась вместе во время / после печати.

  • Доступ к базовой структуре PyObject
  • Cython Memoryviews - из массива структур?
  • Boost.Python - отображение класса
  • Печать переменной во встроенном интерпретаторе Python
  • Как работает сборщик мусора и область работы C #?
  • Перевод словаря на Python на C ++
  • C Арифметика указателя в Python
  • Как эффективно найти линию горизонта на высотной фотографии?
  • Python - лучший язык программирования в мире.