3D сканер из камеры, но без лазера v 0.1

в 17:50, , рубрики: android, DIY, diy или сделай сам, дополненная реальность, сделай сам, смартфоны

3D сканер из камеры, но без лазера v 0.1 - 1
Хотелось получать стереоизображение в очки виртуальной реальности из одной камеры(ведь они делались под смартфон или планшет), чтобы дописать в нее дополненную реальность.


Поиски готового решения расстроили: лидар — дорого и громоздко; кинект — финансово и физически неподъемно; 3д сканер с лазером — время обработки.
Подумав, решил работать с тем что имеется, то есть камерой ноутбука.

Абстрагируемся пока от конкретной реализации и обратимся к алгоритму.
Все действо изначально происходит в трехмерном пространстве, есть плоскость изображения, которую можно вращать в любую сторону, у каждого приходящего пикселя  берется освещенность одного из цветов или их совокупность и этот пиксель выносится перпендикулярно из плоскости изображения на число освещенности (0-255).
image
Получается что мы выносим пиксели исходного изображения перпендикулярно к его плоскости в зависимости от освещенности.

3D сканер из камеры, но без лазера v 0.1 - 3

3D сканер из камеры, но без лазера v 0.1 - 4

Как вы видите получается относительно сносное 3D, годное для получения стереоизображения.

Но это была картинка с выборкой по диапазону освещенности, вот что выйдет если фильтр снять:

3D сканер из камеры, но без лазера v 0.1 - 5

Ну и в качестве бонуса пара изображений.
image
image

Исходный код довольно прост.

Используется язык Processing

Сдвиг выборки управляется sw (включите английскую раскладку).

Код

int colfilter=25;  // диапазон фильтра+-
import processing.video.*;
float rotx = 0;//переменные поворота
float roty = 0;

int countcol=1;//счетчик

float pixelBrightness=0; //освещенность пикселя
float Brightness=0;///освещеность
Capture cam;
int numPixels;//переменная количества пикселей
void setup() {
size(900,700, P3D);

cam = new Capture(this, 320,240);///запускаем камеру
cam.start();
numPixels = cam.width * cam.height;
frameRate(30);//кадры в секунду

}

void draw()
{

background(255);
translate(width/2.0, height/2.0-250, +200);//переместимся на середину
rotateY(roty);//поворот изображения
// rotateX(rotx);

if (cam.available() == true)
{
cam.read();//читаем камеру

cam.loadPixels();//загружаем пиксели

float col[]=new float[numPixels]; //создаем массив под хранение освещенности

loadPixels();

for (int i = 0; i < numPixels; i++) {

pixelBrightness =red(cam.pixels[i]);   ///берем освещенность  по красному цвету каждого пикселя
// pixelBrightness =brightness(cam.pixels[i]);//можете использовать любую освещенность
col[i]=pixelBrightness;//записываем освещенность в массив
// Brightness = red(cam.pixels[i]);
// float Brightness2 = blue(cam.pixels[i]);
// float Brightness3 = green(cam.pixels[i]);

updatePixels();//обновляем пиксели

}

translate(-160,120,0);//по очереди перебираем пиксели и отрисовываем их
for(int i=0;i<240;i++)
{
for(int j=0;j<320;j++)
{

if(countcol<numPixels)
{
if(col[countcol]<colfilter+50&&col[countcol]>colfilter-50)

{
fill(col[countcol]);
point(j*1.3,i*1.3,col[countcol]/2);
}

countcol++;

}}}

countcol=0;
}}
void mouseDragged() {
float rate = 0.01;
rotx += (pmouseY-mouseY) * rate;
roty += (mouseX-pmouseX) * rate;
}

void keyPressed()   /////Управление положение выборки освещенности
{
if(key=='w')
{
colfilter++;
}

if(key=='s')
{
colfilter--;
}
}

Ну и сама софтина (нужны Java,JRE,x64)
Если что не так — пишите, исправлю.

Автор: Dorrin

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js