Миллиард точек: 3 доллара против 8 миллионов рублей

Вот как в реале выглядит всевидящее око

e9b601b9b3a44229a761cc009a42f737.jpg
Кстати, сканер дороже автомобиля. Tesla S. С авиадоставкой до подъезда в Москве

В этом посте будет описание самого дорогого (наверное) в мире и самого дешевого в мире 3d-сканера.

Благодаря компании 3d.ru мне удалось потестировать и разобраться, как работает крутейший в мире 3d-сканер. Они мне рассказали, что обычно такие точные круговые 3d-сканеры их клиенты используют в авиастроении, аэрокосмической промышленности, при сканировании музеев и галерей, реконструкции старых помещений, геодезии и т.д.
(И да, я спросил сколько стоит доменное имя из двух букв, ребята хитро промолчали.)

dcefa1322c4f47a18f589e0931e8e130.jpg
Разобрать (распилить) устройство по цене тесламобиля мне не дали, поэтому я заглянул в инструкцию. Пара фоток внутренностей оттуда.
На вопрос, а может ли 3d-сканер сделать селфи (если перед ним поставить зеркало), мне ответили, что у этих приборов нелады с отражающими поверхностями. Поэтому я взял череп с соседней полки и попробовал его отсканировать.

Вот такие красивые штуки создаются при помощи сканера

3D сканер Surphaser 25HSX


3D сканер Surphaser 25HSX является трехмерным лазерным сканером со сферической системой отклонения луча, предназначенным для формирования 3-х мерных моделей реальных объектов для последующего использования в различных областях:

— изготовление чертежей проектируемых деталей по прототипам;
— создание резервных копий музейных экспонатов и интерьеров;
— разработка компьютерных игр и рекламной мультипликации;

Работа сканера основана на использовании «Сканирующей головки» (hardware сканера) и управляющего компьютера, на котором установлено «Программное обеспечение» (software сканера), с помощью которого компьютер запускает процесс сканирования, принимает поток данных измерений из сканирующей головки, а после окончания сканирования обрабатывает эти данные, переводя их в форму облака точек объекта.

ТТХ
Сканирующая головка является входным устройством 3d сканера, которое является, по сути, электронным прибором для измерения геометрических величин.

При этом головка позволяет обеспечивать 3d сканеру Surphaser 25HSX следующие параметры:

  • Дальность до измеряемого объекта — 1.5 — 60 м;
  • Зона обзора сканирующей головки со сферической системой отклонения — большая часть поверхности сферы с угловыми размерами 240×180 град;
  • Дискретность измерений — 200 000 -1 000 000 точек в секунду;
  • Плотность распределения точек отсчета дальности -17–100 точек на градус
  • Время сканирования всей зоны обзора ~ 2 минуты (при плотности 17 точек на градус и дискретности 200 000 точек в секунду);
  • Точность измерения продольная — 1 мм и менее; поперечная 20–60 угловых секунд.
  • Сканирующая головка питается от источника постоянного тока 18–22 В, обеспечивающим ток до 3,3 А.

Одновременно сканирующая головка является устройством ввода-вывода. При этом головка обеспечивает передачу данных в цифровом виде со скоростью до 200 Мбайт/с.

Интерфейс связи с управляющим компьютером: USB-2.

809db09192384f6eb99c2cef69be2b7e.jpg
Составные части Сканирующей головки для 3D сканера сферического типа

расшифровка
1- Модуль оптической развертки (выделен штриховой линией)
1.1- Дальномерная головка (выделена штриховой линией)
1.1.1- Лазерный модуль
1.1.2- Фотоприѐмный модуль
1.1.3- Объектив.
1.1.4- Радиотехнический модуль
1.1.5- Плата контроля луча
1.1.6- Коммутационная плата
1.2. — Система отклонения
1.2.1- Узел быстрого вращения
1.2.1.1- Вращающееся зеркало
1.2.2- Узел медленного вращения
1.3- Шасси
2.- Устройство выделения «полезного» сигнала
2.1- Плата АЦП
2.2- Цифровая плата
3- Плата питания
4- Кожух Сканирующей головки

Работа сканирующей головки состоит в том, что луч дальномерной системы (аналоговой частью которой является Дальномерная головка) с постоянной угловой скоростью поворачивается в пространстве. Развертка луча вокруг вертикальной оси путем поворота шасси производится медленно (0,05–0,2 об/мин), а развертка луча вокруг горизонтальной оси с помощью вращающегося зеркала — быстро (4–40 об/сек). При этом непрерывно с частотой около 200 кГц (при необходимости до 1 МГц) производится отсчет времени распространения света до текущей точки объекта (точнее фазовых сдвигов у отраженного луча на частотах модуляции интенсивности света). Данные фазовых измерений, а также данные о текущих значениях углов поворота передаются во внешнее устройство — управляющий компьютер для накопления этих данных и
последующего расчета по ним геометрии отражающей поверхности объекта.

fee85ee0b04d40ba8193e5976506f129.jpg
Модуль оптической развёртки для сферического 3d сканера с системой отклонения с вращением только вокруг горизонтальной оси, подготовленный для транспортировки.

c2cc413b39494fa5b119a5254e2c61cf.jpg
Оптическая схема Модуля оптической развертки

описание по элементам
892ef9ebed8b41b0a136ca859208a8f9.jpg

Обозначения на схеме:
Оптические элементы из стекла
3 –линза 47464
4 — оптический фильтр 690.0 IF 40 U
7 — фокусирующая линза 46377
8 — защитное окно 18.105
11 — зеркало 18.106
14 — линза 18.101.
15 — линза 18.102.
16 — линза 47911 или 48692
17 — оптический фильтр 38 02 27 032
Прочие элементы
1 — корпус фотоприемного модуля
2 — приемный фотодиод
5 — корпус лазерного модуля
6 — лазерный диод
9 — деталь крепления защитного окна
10 — вращающееся зеркало
12 — фотодиод на плате контроля луча
13 — корпус объектива

d26fdd6cae854b16a4aab3f03622667e.jpg
Плата Лазерного модуля BL предназначена для управления полупроводниковым лазерным диодом HL6750MG. В рабочем режиме Плата обеспечивает формирование непрерывного оптического излучения с постоянной средней оптической мощностью и амплитудной модуляцией

ce53b414873c4c02ad2bfe483b121322.jpg
Плата BP фотоприемного модуля предназначена для приема модулированного по интенсивности лазерного излучения с помощью лавинного фотодиода. В рабочем режиме Плата обеспечивает выделение модулирующего свет сигнала и его усиление.

38d3b7f326b342e39ddf2af11c18f755.jpg
Плата BR Радиотехнического модуля, являющегося частью модуля оптической развертки 3D сканера, предназначена для формирования комбинированного сигнала, модулирующего по интенсивности световой луч, преобразование (перевод на низкую частоту 1 МГц и усиление) принятого отраженного ВЧ сигнала и опорного ВЧ сигнала, выделение и усиление отраженного НЧ сигнала

1201feb01d8646628735f43bd1a0745b.jpg
Плата BS, являющаяся частью модуля оптической развертки 3D сканера, предназначена для формирования сигнала о наличии луча на выходе лазерного модуля. Для формирования сигнала используется только рассеянное излучение. В рабочем режиме выходное напряжение превышает 0,1 В при мощности луча более 3 мВт.

Сканирование


71cc05de76cf4c669dffd2ef0344008d.jpg
Вот так видит комнату 3д-сканер в предварительном режиме (можно выбрать нужную область, которую сканер будет зондировать)

bb562f38484d4bb0ab40d4efc6c00919.jpg
Мир глазами 3д-сканера. Кто может разглядеть человека?

97b0cf8256204fa2bfdaabc9ef3d65a1.jpg
Та же комната в 3д-редакторе

f63353f1830e43a3a3adea7a1d4a0871.jpg
Вот так видит череп обычный человек

f4fa9143ad1f44c6a7cca1be99b7307b.jpg
Вся комната на этот раз не нужна, поэтому мы выбираем только тот участок с черепом в режиме предсканирования. Затем минут 5–10 сканер крутит своим оком, ищет хоббитов. Главное не попадаться на его пути, а то сожжет будет дефект. Сканер захватывает не только сам череп, но и участки которые далеко за ним. Это легко правится в редакторе.

0b5444dc567a424c920720b1a88381ad.jpg
Мимо человек проходил, попал в зону лазерного луча. Видите полосу? Не вставайте на пути когерентного света. С человеком все в порядке, а вот на скане это отразилось как «битый пиксель»

Немного про использование Surphaser`a в реальной жизни


1c76f98072b84eb39b73a848622a291c.jpg

еще фото

3d-сканер за 3 доллара

b223fc2221134ff1b78f3445edf6d7bc.jpg

  • Arduino с Arduino IDE
  • Processing IDE
  • немного LEGO
  • шаговый двигатель (например из принтера)
  • драйвер шагового двигателя и питание
  • лазер
  • веб-камера
  • работающая Meshlab
по компонентам
image
из старого OKI принтера. Делает полный оборот за 48 шагов (7,5 градусов за шаг),
3,7V, 200–250mA

image
Питание, драйвер и редуктор

4090ec08af99463f8a3bc3c36e693bdf.jpg

image

b7c75751b6e742e780a3634bab2bbbc3.jpg

image
CD, резиночки, клей, LEGO зеленая бумага

image
Камера — Creative Webcam Vista. она устаревшая и с плохим сенсором (640×480), и плохой оптикой (plastic lenses). Но есть одно преимущество. Автор ее имел в наличии.

image
Низкокачественный и дешевый лазер (~1$)приделан к цилиндрической линзе, сделанной из стеклянного стержня. (стержень из химической лаборатории). Угол между лазером и камерой 30 градусов

image

code
#include
Stepper oki (48,8,9); //see stepper tutorial in arduino.cc for info about that
const int ledPin = 13; // the pin that the LED is attached to
int incomingByte; // a variable to read incoming serial data into

void setup () {
// initialize serial communication:
Serial.begin (9600);
// initialize the LED pin as an output:
pinMode (ledPin, OUTPUT);
oki.setSpeed (60);
}

void loop () {
// see if there’s incoming serial data:
if (Serial.available () > 0) {
// read the oldest byte in the serial buffer:
incomingByte = Serial.read ();
// if it’s a capital H (ASCII 72), turn on the LED:
if (incomingByte == 'S') {
digitalWrite (ledPin, HIGH);
oki.step (4);
}
// if it’s an L (ASCII 76) turn off the LED:
if (incomingByte == 'K') {
digitalWrite (ledPin, LOW);
}
}
}

image

Processing
code:
import codeanticode.gsvideo.*;
import processing.serial.*;

//objects
PFont f;
GSCapture cam;
Serial myPort;
PrintWriter output;

//colors
color black=color (0);
color white=color (255);

//variables
int itr; //iteration
float pixBright;
float maxBright=0;
int maxBrightPos=0;
int prevMaxBrightPos;
int cntr=1;
int row;
int col;

//scanner parameters
float odl = 210; //distance between webcam and turning axle, [milimeter], not used yet
float etap = 120; //number of phases profiling per revolution
float katLaser = 25*PI/180; //angle between laser and camera [radian]
float katOperacji=2*PI/etap; //angle between 2 profiles [radian]

//coordinates
float x, y, z; //cartesian cords., [milimeter]
float ro; //first of polar coordinate, [milimeter]
float fi; //second of polar coordinate, [radian]
float b; //distance between brightest pixel and middle of photo [pixel]
float pxmmpoz = 5; //pixels per milimeter horizontally 1 px=0.2mm
float pxmmpion = 5; //pixels per milimeter vertically 1 px=0.2mm

//================= CONFIG ===================

void setup () {
size (800, 600);
strokeWeight (1);
smooth ();
background (0);

//fonts
f=createFont («Arial»,16, true);

//camera conf.
String[] avcams=GSCapture.list ();
if (avcams.length==0){
println («There are no cameras available for capture.»);
textFont (f,12);
fill (255,0,0);
text («Camera not ready»,680,32);
}
else{
println («Available cameras:»);
for (int i = 0; i < avcams.length; i++) {
println (avcams[i]);
}
textFont (f,12);
fill (0,255,0);
text («Camera ready»,680,32);
cam=new GSCapture (this, 640, 480, avcams[0]);
cam.start ();
}

//Serial (COM) conf.
println (Serial.list ());
myPort=new Serial (this, Serial.list ()[0], 9600);

//output file
output=createWriter («skan.asc»); //plik wynikowy *.asc

}

//============== MAIN PROGRAM =================

void draw () {

PImage zdjecie=createImage (cam.width, cam.height, RGB);
cam.read ();
delay (2000);
for (itr=0; itrcam.read ();
zdjecie.loadPixels ();
cam.loadPixels ();
for (int n=0; nzdjecie.pixels[n]=cam.pixels[n];
}
zdjecie.updatePixels ();
set (20,20, cam);
String nazwaPliku=«zdjecie-»+nf (itr+1, 3)+».png»;
zdjecie.save (nazwaPliku);
obroc ();
delay (500);
}
obroc ();
licz ();
noLoop ();

}

void licz (){
for (itr=0; itr

String nazwaPliku=«zdjecie-»+nf (itr+1, 3)+».png»;
PImage skan=loadImage (nazwaPliku);
String nazwaPliku2=«odzw-»+nf (itr+1, 3)+».png»;
PImage odwz=createImage (skan.width, skan.height, RGB);
skan.loadPixels ();
odwz.loadPixels ();
int currentPos;
fi=itr*katOperacji;
println (fi);

for (row=0; rowmaxBrightPos=0;
maxBright=0;
for (col=0; colcurrentPos = row * skan.width + col;
pixBright=brightness (skan.pixels[currentPos]);
if (pixBright>maxBright){
maxBright=pixBright;
maxBrightPos=currentPos;
}
odwz.pixels[currentPos]=black; //setting all pixels black
}

odwz.pixels[maxBrightPos]=white; //setting brightest pixel white

b=((maxBrightPos+1-row*skan.width)-skan.width/2)/pxmmpoz;
ro=b/sin (katLaser);
//output.println (b + »,» + prevMaxBrightPos + »,» + maxBrightPos); //I used this for debugging

x=ro * cos (fi); //changing polar coords to kartesian
y=ro * sin (fi);
z=row/pxmmpion;

if ((ro>=-30) && (ro<=60) ){ //printing coordinates
output.println (x + »,» + y + »,» + z);
}

}//end of row analysis

odwz.updatePixels ();
odwz.save (nazwaPliku2);

}
output.flush ();
output.close ();
}

void obroc () { //sending command to turn
myPort.write ('S');
delay (50);
myPort.write ('K');
}

image
сканирование

image
облако точек

image
исходный объект

image
некое подобие облако точек и совы заметно невооруженным глазом

image
после обработки в MeshLab

еще один проект
image

image
hackaday.io/project/2021–3dollar-scanner

И все же у меня вопрос к знатокам: что составляет большую часть стоимости устройства за 8 миллионов рублей?

P.S.
Идея.
Есть задумка сделать обучающий проект (для школьников и студентов) с выходом на краудсорсинг. Можно вытащить 3d-сканер на ВДНХ и отсканировать «Рабочего и колхозницу», а потом напечатать много брелков и статуэток тем, кто сделал взнос. А еще фильм-обучалку снять и на youtube выложить.
Студентам — знания, компаниям — пиар, 3d-сообществу — полезная движуха.
Если есть ли у кого знакомые из администрации ВДНХ или может у кого есть подъемная платформа, пишите.

P.P. S.

Применение 3d-сканеров в играх




© Geektimes