[/b/] [/d/] [/tu/] [/a/] [/ph/] [/wa/] [/cg/] [/t/] [/p/]

[Burichan] [Foliant] [Futaba] [Greenhell] [Gurochan] [Photon] - [Home] [Manage] [Archive]

[Return]
Posting mode: Reply
Leave these fields empty (spam trap):
Name
Link
Subject
Comment
File
Verification
Password (for post and file deletion)
  • Supported file types are: GIF, JPG, PDF, PNG
  • Maximum file size allowed is 20480 KB.
  • Images greater than 200x200 pixels will be thumbnailed.

File: 1359370923064.jpg -(340408 B, 966x1216) Thumbnail displayed, click image for full size.
340408 No.88310  

В этом треде я расскажу о том, как я пилил лазерный объемный сканер и что из этого вышло. По ходу дела я столкнулся с одной технической трудностью и мне известно, что на новере сидят анонимы, умеющие в CV. Быть может они пояснят, что я делаю не так.
Обо всем об этом ниже по треду.

>> No.88311  

Идея моего сканера состоит в восстановлении геометрии объекта по падающей на него линии света. Для сканирования я использую стенд, представленный на пике. Камера находится на некотором удалении и смотрит на стенд сверху вниз. На пике также видна лазерная указка с блоком питания, но об этом позже.
Процесс сканирования состоит в последовательном снятии рельефа при помощи падающего на объект лазерного луча. Назовем этот срез слайсом, например.

>> No.88312  
File: 1359371316822.png -(481363 B, 640x480) Thumbnail displayed, click image for full size.
481363

Пик забыл.

>> No.88313  
File: 1359371711301.png -(3457 B, 640x480) Thumbnail displayed, click image for full size.
3457

После снятия рельефа я получаю картину, представленную на пике (это один из слайсов сканирования чашки).
По этомому изображению я нахожу *x*, *y* и *z* координату следующим образом:

  1. Устанавливаю регион интереса на левую сторону изображения.
  2. Алгоритмом Хафа нахожу самый длинный отрезок. Этот отрезок - отражение лазерной линии от стенок стенда, представленного выше.
  3. Повторяю то же самое для правой части изображения.
  4. Нахожу точку пересечения этих отрезков. Это будет *y* координатой слайса.
  5. Провожу перпендикуляр от каждой точки на левый и правый отрезок, вычисляю длину от *y* координаты до точки пересечения перпендикуляра с отрезком. Таким образом получаю *x* и *z* координату. Все точки, лежащие на отрезке удаляются - теперь они не нужны, меня интересуют только рельеф объекта сканирования, а не стенда.
>> No.88314  
File: 1359371980223.png -(17270 B, 382x370) Thumbnail displayed, click image for full size.
17270

Далее я записываю полученные точки в текстовый файл и открываю его программой CloudCompare. Это софт для работы с облаками точек. И тут-то и начинается загвоздка: облако точек очень искажено и причина этого мне не ясна. Посмотрите на пик.
(продолжение в следующем посте - я прикреплю картинку с пояснением).

>> No.88315  
File: 1359372344456.png -(23624 B, 509x413) Thumbnail displayed, click image for full size.
23624

Слайс искажен и довольно сильно. Красной линией на пике показано как должны были располагаться точки. С неравномерностью расположения слайсов все понятно - я вручную двигаю лазер и с непостоянной скоростью. А вот причины искажений мне до конца неясны. Если бы дело было в изменении угла падения линии, я бы получил конусообразное облако точек. Тремор рук тоже не подходит - на изображениях он не заметен. Что же могло вызвать подобные искажения.
В следующем посте я выложу файл с облаком точек, на случай, если вам будет интересно.

>> No.88316  

Вот ссылка на файл с облаком точек: http://rghost.ru/43369933
Это обычный текстовый файл, его можно открыть любой программой для работы с облаками точек, например CloudCompare.

>> No.88317  
File: 1359373280083.jpg -(212006 B, 626x800) Thumbnail displayed, click image for full size.
212006

>>88315

> я вручную двигаю лазер

Но ведь когда ты вручную двигаешь лазер, ты не можешь каждый раз двигать его строго параллельно оси y, следовательно тебе нужно вычислять все три координаты для каждой, а не считать y для всего слайса.

>> No.88318  

>>88317
Этап вычисления *y* координаты производится для каждого слайса.

>нужно вычислять все три координаты для каждой, а не считать y для всего слайса

Не понимаю, поясни.

>> No.88320  
File: 1359374334612.jpg -(1518735 B, 1200x898) Thumbnail displayed, click image for full size.
1518735

>>88318
Для каждой точки. Прости, опечатка.

>> No.88321  
File: 1359374685035.png -(2274 B, 205x238) Thumbnail displayed, click image for full size.
2274

>>88320
У каждой точки слайса координата *y* должна быть одинакова.
Проблема в погрешности определения *x* и *z*, причины которой я понять не могу.

>> No.88322  
File: 1359375437877.png -(3622 B, 290x203) Thumbnail displayed, click image for full size.
3622

И таки да, искажения наверняка вызваны перемещением лазера вручную.
Еще одна тонкость: David Laser Scanner (http://www.david-laserscanner.com/) перемещает луч как показано на пике. Я тоже так хочу, иначе механика слишком дорого обойдется.
К сожалению, потрогать давидовский софт не могу, т.к. нищепекарня не может в SSE.

>> No.88323  
File: 1359376994773.jpg -(46215 B, 481x651) Thumbnail displayed, click image for full size.
46215

>>88321

> У каждой точки слайса координата *y* должна быть одинакова.

Но она не может быть одинакова, если ты не перемещаешь лазер специальным механизмом.
>>88322

> К сожалению, потрогать давидовский софт не могу, т.к. нищепекарня не может в SSE.

Если оно не реалтаймовое то можно попробовать qemu в режиме софтовой эмуляции.

>> No.88328  

Нашел ошибку. Линза лазора у меня самодельная, поэтому свет здорово рассеивается. Из-за этого рассеивания, линию, что падает на стенд, так пидорасит, что она не всегда правильно детектируется. А это здорово шатает *y* координату. Попробую как-то это исправить.

>> No.88333  

Линза. Сейчас я использую самодельную линзу из кусочка лампочки: стеклянная трубочка, которая держит металлические ножки, которые поддерживают спиральку лампочки, залитая водой и загерметизированная с обоих концов. Дает не самый худший результат, хоть и недостаточно четкий луч. Сейчас вода в ней высохла, видимо, герметизация цианокриалатным клеем - плохая идея.
Новерь, чем бы заменить эту линзу? Параметры: её очень легко изготовить и она дает более-менее четкую и равномерную лазерную линию, при проходе через нее лазерного луча. Ножки бокалов не подходят.

>> No.88334  

>>88333
Донышко от бутылки?

>> No.88335  
File: 1359398932303.jpg -(1145460 B, 1280x933) Thumbnail displayed, click image for full size.
1145460

>>88333
Взять готовую линзу откуда-нибудь не вариант?

>> No.88336  
File: 1359399184936.png -(29304 B, 640x960) Thumbnail displayed, click image for full size.
29304

Хреновое качество облака - конская погрешность при распознавании отражения от стенда. Пикрилейтед. По крайней мере, я пока думаю, что это так. Пикрилейтед.
>>88335
Я использую кусочек лампочки именно потому, что готовые линзы мне недоступны. От оптических приводов тоже не подходят.
>>88334
Недостаточно чистое.

>> No.88337  
File: 1359399499409.jpg -(331232 B, 780x1040) Thumbnail displayed, click image for full size.
331232

>>88336

> Я использую кусочек лампочки именно потому, что готовые линзы мне недоступны. От оптических приводов тоже не подходят.

Магазины или мастерские очков есть практически в каждом городе, достать там одиночную линзу возможно выйдет даже дешевле чем разбирать очки для этого. Или в твоем случае размер имеет значение?

>> No.88339  
>разбирать очки для этого

Обычная очковая линза не разлагает луч в линию. Нужна асферическая линза. И да, размер важен.

>> No.88340  
File: 1359401905864.png -(19831 B, 318x448) Thumbnail displayed, click image for full size.
19831

У меня уже баттхерт от таких искажений.

>> No.88343  

Померил угол между прямыми стенда для всех слайсов. Удивительно, но погрешность его определения оказалась ~0.01, а не 100500.

>> No.88345  

Посчитал облако старым алгоритмом, вычислил среднее изменение y координаты центра и линий стенда. Захардкодил. Потерял пропорцию, но искажения очень сильно уменьшились. Все еще не понимаю, как заставить эту штуку работать.

>> No.88346  

>>88339
По-моему, хороший мастер из оптики может сделать и асферическую линзу. Поспрашивай.

>> No.88348  
File: 1359415285835.png -(30315 B, 611x353) Thumbnail displayed, click image for full size.
30315

Raspeedoraseeelo.

>> No.88510  

А тебе не подойдет лазер, что можно сделать из какого-нибудь лазерного уровня? Они не очень дорогие, в то же время уже готовые и достаточно устойчивые. Единственная проблема с обратной связью.

>> No.88602  

Более того: в оптиках обычно етсь готовые асферические линзы.

>> No.88619  

Всем по нобелевской премии в этом итт треде.

>> No.88794  

>>88510
Звучит чертовски годно, я имел трогать лазерный уровень и мне понравилась его лазерная линия.
Но я нищеброд ебанный, поэтому ограничен тем, что могу достать либо очень дешево, либо бесплатно.
Все еще думаю о подавлении искажений. Попробую использовать шаговый моторчик из CD-привода (он там двигает каретку) в качестве привода лазора.

>> No.88807  

http://www.youtube.com/watch?feature=player_embedded&v=CZiSK7OMANw#

>> No.89516  

Насасываю с шаговиком из-за своей криворукости.
А бампануть очень хочется.

>> No.89627  
File: 1364218126534.png -(11870 B, 514x515) Thumbnail displayed, click image for full size.
11870

С моторчиком дела налаживаются, уже собираю примитивную платку для управления.
Черновой вариант лазороперемещателя.

>> No.89631  
File: 1364218577445.jpg -(445982 B, 1039x1477) Thumbnail displayed, click image for full size.
445982

>>89627
Платка на контроллере? Или ты прямо с компа даешь управляющие сигналы на мотор?

>> No.89661  

>>89631
Напрямую, через ключи. Это черновая версия же. Схему сейчас не доставлю, потому что она на другой пекашечке, а где я её взял не помню.

>> No.89736  

>>89661
А какие ключи ты используешь?

>> No.89862  

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

В чём вопрос: вот у тебя есть компьютер, в котором ты царь и Бог. Вот у тебя есть какие-то моторчики, шестерёнки, реле, которые ты научил захватывать мир: выключать свет в ванной, управлять лазером, ходить по комнате, радиосигналы подавать. Но пока они по отдельности, никакого волшебства не происходит. Итак, как же они объединяются? Я не понимаю даже, куда это ты втыкаешь: в современных ноутах кроме USB-то ничего и не осталось, а USB ведь довольно сложный протокол, оверкилл, да и не напасёшься на всё портами USB. А если ты хочешь приделать к домашнему серверу целую армию различных устройств?

Я понимаю, что вопрос очень глупый, но я правда не знаю, как это всё работает. Пару раз пытался нагуглить что-то "общее" по теме, но все мануалы начинаются с предположения, что я знаю что-то, чего я на самом деле не знаю.

>> No.89869  
File: 1364255463414.png -(139467 B, 880x450) Thumbnail displayed, click image for full size.
139467

>>89862
Материнки с COM и LPT портами еще далеют. Есть платы расширения с указанными выше портами или GPIO. Кроме того есть всякие переходники на них с USB. И даже есть монстры вроде http://www.xdimax.com/sub20/sub20.html

>> No.89870  
File: 1364256478093.jpg -(868852 B, 1200x900) Thumbnail displayed, click image for full size.
868852

>>89869
Но всё равно их же будет несколько штук, да и потом, ну ок, а если нет у тебя такой материнки, что теперь? Фактически через любой порт ПК можно принимать/передавать дикие объёмы данных, вычислительной мощности самого скромного домашнего сервера за глаза хватает, чтоб управлять всем домом, при этом закачивая торренты, проигрывая радио, обучая нейронную сеть и раздавая странички твоей персональной имиджборды, — список неполный. Но как сделать фантазии твоего ПК реальностью? Т.е., наверняка же есть какие-то стандартные решения, да и вообще, просто, как вы всё это делаете? Я даже не знаю, с какой стороны к этому подойти.

>> No.89871  
File: 1364257374438.jpg -(3972450 B, 2888x4080) Thumbnail displayed, click image for full size.
3972450

>>89870
Если тебе нужно дикое количество GPIO то проще вывести из компьютера шину данных (параллельную, I2C, CAN, LIN или что-нибудь еще) и на нее навесить пачку микроконтроллеров со своими GPIO.

>> No.90863  
File: 1364753439088.gif -(15941 B, 336x343) Thumbnail displayed, click image for full size.
15941

>>89736
Пикрилейтед.
>>89862
Я сам мало что понимаю в электронике. Несложное устройство по схеме собрать сумею, но настроить и, тем более, разработать самостоятельно, для меня представляет огромную трудность.

>> No.91365  

http://dx.com/ru/p/red-laser-module-focused-line-3-5v-4-5v-16mm-5mw-5928

Теперь я знаю, на что собирать деньги со школьных завтраков.

>> No.91366  

>>89862
недавно тоже задавался этим вопросом. пока дошел до такого варианта:
http://www.raspberrypi.org/
есть gpio. а к компу можно подключить через вайфай или блютуз.

>> No.91368  
File: 1365628765472.png -(695034 B, 850x1202) Thumbnail displayed, click image for full size.
695034

>>91366
Вы серьёзно? Даже ардуина для таких целей оверкилл.
Можно что-нибудь на PIC спаять. Проще всего купить переходник USB-RS232 и вообще ничего не паять

>> No.91375  

>>91368
но ардуину нужно же программировать.
USB-RS232 - а это стоит не многим дешевле малины (хотя я думал над этим). зато встроенная операционная система и независимость от компа - хорошие вещи.

>> No.91378  

>>91375
Где ты видел малину за 3 бакса? http://dx.com/ru/p/usb-to-rs232-serial-port-adapter-transparent-green-24512

>> No.91384  

>>91378
опачки. значит, я не умею гуглить. просто я интересуюсь этой темой всего пару дней. ничего не зная, пришел к самому простому выводу - малина. благодарю за наводку.

>> No.91576  

Заказал лазер с линзой. Продолжаю собирать моторчик и головку.
Баттхерт от того, что все можно было сделать гораздо быстрее.

>> No.91578  

>>91576
Наковырял бы из двд-ромов

>> No.91584  
File: 1366136688509.jpg -(44495 B, 250x250) Thumbnail displayed, click image for full size.
44495

>>91578

>Я использую кусочек лампочки именно потому, что готовые линзы мне недоступны. От оптических приводов тоже не подходят.
>> No.91589  

>>91584
Лазер от оптического привода + линзы из китайской указки, классический набор

>> No.91677  
File: 1366547673650.png -(2296742 B, 1600x1200) Thumbnail displayed, click image for full size.
2296742

Собрал драйвер по схеме выше. Работает.
Пожалуй, следует отойти от концепции "умный ящик для сканирования" и использовать отдельно каретку, отдельно поворотный стол. Электронику тоже надеюсь разместить в каретке.
Пожалуй, помимо датчиков крайнего положения будет не лишней примитивная система самодиагностики, перегруза двигателей, например.
Сворую "Компас 3D" и буду играть в моделиста-конструктора в попытках запилить каретку.

>> No.91678  
File: 1366548909501.jpg -(1327284 B, 2468x3246) Thumbnail displayed, click image for full size.
1327284

>>91677
Зачем и то и другое? Крайнее положение можно определить резким возрастанием нагрузки на двигатель, когда он натыкается на упор, если есть обратная связь. Если есть датчик крайнего положения то перегрузку можно определить прогнав каретку от одного края до другого. Впрочем можно даже обойтись и без того и без другого, сделав проскальзывающее от перегрузке сцепление (пасик например) и просто отогнав каретку в одну сторону на полное расстояние при инициализации устройства.

>> No.91679  

>>91678
Новерь, ты меня разочаровываешь.

Датчики крайнего положения нужны, чтобы не насиловать почем зря моторчик о стенку каретки. С этим справится обычная кнопочка.
А определение перегруза поможет определить, что образовалась механическая неисправность, провод зажевало, мусор попал etc. Не думаю, что это реально понадобится, но все же попробую впилить.
Как оказалось, готовый драйвер обойдется мне в столько же, во сколько и эта хуйня на пике выше. Может, там и перегруз есть.

>> No.91680  
File: 1366550866393.jpg -(942079 B, 800x800) Thumbnail displayed, click image for full size.
942079

>>91679

> чтобы не насиловать почем зря моторчик о стенку каретки

Ему от этого ни холодно, ни особо жарко, если ты конечно не гоняешь его на запредельных мощностях.

>> No.91836  
File: 1367175263696.jpg -(407486 B, 1600x1200) Thumbnail displayed, click image for full size.
407486

Стыдно, но на запилку этой хуйни у меня ушел почти весь день. Ось и лазор еще не закреплены.
Это черновая версия каретки, работает через пень-колоду, не имеет датчиков крайнего положения и все такое. Отошел от первоначальной схемы, эта более компактна и не нужно разбирать на части двигатель.
На днях допилю софт и попробую сканировать с её помощью.

>> No.91840  
File: 1367188512934.png -(649638 B, 850x600) Thumbnail displayed, click image for full size.
649638

Нахуй лазеры. Погружаешь в жидкость контрастного к объекту цвета, по мере погружения снимаешь с 4 сторон границу. Никаких проблем с линзами и рассеиванием, под сканирование подходит куда большее количество материалов. Можно перемазаться в жидкости, всем весело

>> No.91843  
File: 1367189496786.jpg -(216191 B, 763x785) Thumbnail displayed, click image for full size.
216191

>>91840
Есть какой-то простой алгоритм, позволяющий отличить контактную границу жидкости и объекта от неконтактной?

>> No.91845  

>>91843

>контрастного к объекту цвета
>> No.91847  
File: 1367195309184.png -(614178 B, 975x741) Thumbnail displayed, click image for full size.
614178

>>91845
Как ты собираешься различать границы 1 и 2?

>> No.91848  

>>91847
Несколько камер же, с пересекающимися областями видимости. При совмещении проекций будет очевидно, где граница раздела

>> No.91849  
File: 1367196378853.jpg -(805679 B, 1280x1024) Thumbnail displayed, click image for full size.
805679

>>91848

> При совмещении проекций будет очевидно, где граница раздела

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

>> No.91850  

>>91849
Ага. Проецируешь, находишь точку пересечения контуров, отбрасываешь всё, что выше точки. Второй вариант, просто отсечь всё, что выше замкнутого пространства снизу, алгоритм заливки тривиален

>> No.91853  
File: 1367227873222.png -(317347 B, 900x600) Thumbnail displayed, click image for full size.
317347

>>91850
Хм, если знать заранее взаимное расположнение камер, должно сработать. Только стенд будет куда дороже картонной коробки и моторчика с лазером.

>> No.91872  

>>91840
Инженерия уровня /b/.

http://www.melog.ch/3dscan/
Но я чего-то неосиляю.

>> No.91880  

>>91872
Главное, чтобы было весело. Практической пользы от этого всё равно никакой.

>> No.91894  

>>91880
Таки да. И это печально ._.

>> No.92007  

И что вы таки думаете? Соснул хуйца. У шестеренок оказался слишком большой люфт, таким образом движение лазера неравномерно. К тому же, они неподходящего размера - через полметра шаг линии становится 1 см при обычном шаге двигателя и 0.5 при микрошаге. Попробую еще понякаться с шестеренками, если сосну опять, вернусь к первоначальной схеме с роликами.
Новерь, ты имел опыт изготовления/дублирования шестеренок (не диванный!)? Попробую отлить копию шестерни из полистирола (пенопласт + ацетон).
Все еще реквестирую умеющих в машиностроение и CV.

>> No.92008  

>>92007
Ты молодец, что занимаешься этим, анон. К сожалению, в opencv и машиностроении я не разбираюсь.

>> No.92012  

>>92007
Попробуй ременную передачу в качестве редуктора

>> No.92019  

>>92007

>пенопласт + ацетон

Хм, интересный способ. А это проще, чем плавить полиетилен? И какая прочность будет у такого материала?

>> No.92021  

>>92019
Прочность хорошая, годная. А полиэтилен, я думаю, будет мягок. Но попробую и его. Точно скажу на выходных, когда это сделаю.

>> No.92108  

С полистиролом фейл полный. Эта херня превратилась в некоторое подобие жевательной резинки, густое и чудовищно медленно сохнет. Придется таки идти за эпоксидкой. Пока попробую еще и из пластмассы, но прозреваю фейл.
Зато пришел из Китая лазор с разлагающей в линию луч линзой, который я заказывал три недели назад.
Думаю, мне придется разобрать старый принтор.

>> No.92114  
File: 1368307630477.jpg -(460244 B, 630x630) Thumbnail displayed, click image for full size.
460244

>>92108
Из расплавленных PET-бутылок отлить не вариант? Или на кухне с вентиляцией все плохо?

>> No.92118  

>>92114

  1. Гипс плохо держит форму шестеренки.
  2. PET очень нежный становится хрупким при обычной переплавке.

Сейчас жду, пока высохнет шестеренка из цианокриалата с содой. Прозреваю фейл.

>> No.92119  

Цианокриалат с содой провалился. Не буду выебываться и просто возьму шестеренку с другого CD-привода.

>> No.92123  

Попробовал еще раз суперклей и соду. При должной доли терпения у меня получилось. Сейчас выковыриваю отливку из воска. Надуюсь, будет прочной. Теперь самое сложное - просверлить отверстие точно по центру.

Бложик сегодня здеся.

>> No.92124  

>>92123
Нам интересно следить за твоими успехами

>> No.92193  
File: 1368549064229.jpg -(370168 B, 1600x1200) Thumbnail displayed, click image for full size.
370168

Чувствую себя советским инженером: ему дали задание спроектировать лампу, а вышел бронированный вертолет.
Итак, эта хуерга дает шаг в 1 см на полметра при обычном шаге и 0.5 см при микрошаге. Для тестов хватит, ведь это сорт пруф оф концепт.
На пике: каретка лазора, лазор, плата стабилизатора и плата драйвера. Пачка сигарет для масштаба.
И что вы думаете? А нихуя! На изображении с камеры этот лазер выглядит даже хуже, чем мой самодельный! Скана не получил, очень вероятно, что проблема в софте.
Открытые вопросы:

  1. Как рассчитать ролики так, чтобы через полметра шаг лазера был ~1мм.
  2. Зачем эти пидорасы выпускают камеры с автоматической неотключаемой подсветкой.
  3. Где новереанонимы, умеющие в CщьзгеукVшышщт.

Думаю, может купить камеру получше, ведь даже Давид использует 800 х 600, а не 640 х 480!

>> No.92197  
File: 1368550502540.jpg -(685308 B, 1000x1000) Thumbnail displayed, click image for full size.
685308

>>92193

> На изображении с камеры этот лазер выглядит даже хуже, чем мой самодельный!

А визуально? Может действительно лазер проблемный попался?

> Как рассчитать ролики так, чтобы через полметра шаг лазера был ~1мм.

Проще померить шаг и забить его в софт. Если шаг сильно большой - добавь шестерню. Олсо не забывай, что шаг вначале и в конце будет несколько отличаться, если тебе конечно нужна точность.

> Зачем эти пидорасы выпускают камеры с автоматической неотключаемой подсветкой.

Паяльником отключается все.

> Думаю, может купить камеру получше, ведь даже Давид использует 800 х 600, а не 640 х 480!

Бери уже сразу HD, они нынче копеечные.

>> No.92213  
File: 1368600982749.png -(75219 B, 1000x1000) Thumbnail displayed, click image for full size.
75219

До сих пор не удосужился спросить - а ты не пробовал лазор сажать на модельную сервомашинку? Или у неё точности мало?

>> No.92234  
File: 1368646444846.png -(46812 B, 730x561) Thumbnail displayed, click image for full size.
46812

>>92213
Чертовски хорошая идея. Обязательно попробую, благо у меня есть серва. К тому же, ролики на ютубе используют именно её, на что я не обращал внимания.

>> No.92273  
File: 1368821495427.jpg -(8757 B, 259x194) Thumbnail displayed, click image for full size.
8757

До меня наконец-то дошло, почему пидорасит сканы. Тепловые флуктации в матрице камеры делают изображение дрожать и именно это влияет на проеб точности!
Так просто, а непроссывал.
А все почему? Потому что пришло лето и они стали заметны так, что не обращать на них внимания было бы максимум слепо.

>> No.92278  

>>92273
Значит, тебе освещённости не хватает. Поэтому соотношение сигнал/шум такое.

>> No.92339  

Затея близка к провалу - выдуманный мною метод слишком ненадежен. А эту http://www.rob.cs.tu-bs.de/content/03-research/03-publications/download/swi_2006_09_konferenz_dagm.pdf бумагу я плохо понимаю.

>> No.92385  

>>92339
Попробуй делать несколько проходов и потом брать среднее значение.

>> No.93850  
File: 1372595514133.jpg -(131384 B, 650x471) Thumbnail displayed, click image for full size.
131384

Я не забросил, просто нет времени. Поэтому бамп, тред мне еще понадобится.

>> No.93984  

Опу уже советовали http://www.thingiverse.com/thing:3946 ?
И по тегу makerscanner там же.

Результат на пике.

>> No.93985  
File: 1372806620037.jpg -(136834 B, 690x518) Thumbnail displayed, click image for full size.
136834

>>93984
Пик отклеился.

>> No.94022  

Вот тебе забавная ссылка
http://hackaday.com/2013/06/21/3d-scanning-by-calculating-the-focus-of-each-pixel/

>> No.95499  
File: 1376221266462.png -(492030 B, 640x480) Thumbnail displayed, click image for full size.
492030

Серва все равно дает большой шаг и конскую погрешность. Либо серва изношена, либо я что-то делаю не так. Попытаюсь таки осилить мануалы от Давида теперь.

>> No.95500  
File: 1376222340546.jpg -(979644 B, 1600x1200) Thumbnail displayed, click image for full size.
979644

>>95499
Поменяй редуктор или прицепи дополнительный.

>> No.95516  

>>95499
Серва вообще не нужна. Нужно просто сделать как можно больше линий, закрыть ими всю поверхность поочереди, а потом интерполировать результаты.

>> No.97691  
File: 1381078101848.jpg -(122469 B, 850x815) Thumbnail displayed, click image for full size.
122469

Бамп.

>> No.99270  
File: 1384099261208.png -(351200 B, 657x519) Thumbnail displayed, click image for full size.
351200

С новой камерой изображение значительно четче и меньшим шумом. Может, на этот раз получится лучше.

>> No.99273  

>>99270

> меньшим шумом

В темноте тоже? А то у меня складывается впечатление что современные вебки совсем не умеют в съемку при плохом освещении.

>> No.99276  
File: 1384101336425.png -(222976 B, 657x519) Thumbnail displayed, click image for full size.
222976

>>99273
Пикрилейтед.

>> No.99648  
File: 1385296756797.png -(542881 B, 655x515) Thumbnail displayed, click image for full size.
542881

Я у мамы дополненная реальность.

>> No.99650  

>>99648
Неплохо. ARToolkit?

>> No.99696  
File: 1385472510104.png -(450482 B, 657x519) Thumbnail displayed, click image for full size.
450482

>>99650

OpenCV.

>> No.99698  

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

>> No.99866  
File: 1386103172826.jpg -(611089 B, 850x1119) Thumbnail displayed, click image for full size.
611089

>>99698
Я пока с этим еще совсем не разобраолся.
http://xenia.media.mit.edu/~cwren/interpolator/ Как получаются эти формулы? Почему именно такие? Хуй проссышь.

Давайте покукарекаем с дивана: как можно найти освещенность объектов сцены по полученному с камеры изображению? Вычитание из изображения сцены без освещения отпадает - свет из окна, например, не закрыть.

>> No.99869  

>>99866
Это произведения матриц. У нас в курсе аналитической геометрии были основы.

>как можно найти освещенность объектов сцены по полученному с камеры изображению?

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

Хотя это слишком сильно. Лампочку может что-то загородить. Например, сам же наблюдатель.

>> No.99874  
File: 1386163520743.jpg -(202301 B, 600x800) Thumbnail displayed, click image for full size.
202301

>>99869
Это я понимаю. Но почему именно так нет. Надо освежать аналитическую геометрию и матричные вычисления, короч.

>> No.99875  

>>99874
Что мешает пойти от обратного и использовать за показатель освещенности конкретного пикселя в рамке отношение текущего цвета, полученного с камеры к какому-то идеальному шаблону (цвет бумаги в яркий солнечный день, например). Все равно все возможные источники света во всех возможных помещениях не смоделировать, а такой способ позволит получить некоторые представления о текущем свете.
Возможно я не понял, что является целью, да.

>> No.100885  
File: 1388763748905.png -(464973 B, 1302x531) Thumbnail displayed, click image for full size.
464973

Что-то OpenCVшные матрицы совсем не такие как OpenGLевские. Что-то пошло не так.

>> No.100886  

>>100885
Транспонируй

>> No.100892  

[code]void process()
{

frame = cvQueryFrame(capture);
cvFlip(frame, frame, 1);
IplImage * gray = cvCreateImage(cvGetSize(frame), frame->depth, 1);
cvCvtColor(frame, gray, CV_BGR2GRAY);
int cornerCount = 0;
int found = cvFindChessboardCorners(frame, patternSize, patternCorners, &cornerCount,
CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
cvFindCornerSubPix(gray, patternCorners, PATTERN_SQUARES_COUNT, patternSize,cvSize(-1,-1),
cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));
if( cornerCount == PATTERN_SQUARES_COUNT)
{
printf("Pattern found!\n");
for( int i = 1; i < cornerCount; ++i)
cvLine(frame,
cvPoint((int)patternCorners[i - 1].x, (int)patternCorners[i - 1].y),
cvPoint((int)patternCorners[i].x, (int)patternCorners[i].y),
CV_RGB(0, 255, 0));
CvPoint2D32f patternPlane[4];
CvPoint2D32f imagePlane[4];
imagePlane[0].x = 0;
imagePlane[0].y = 0;
imagePlane[1].x = 640;
imagePlane[1].y = 0;
imagePlane[2].x = 640.0f;
imagePlane[2].y = 480.0f;
imagePlane[3].x = 0;
imagePlane[3].y = 480.0f;
	patternPlane[0].x = patternCorners[0].x;
patternPlane[0].y = patternCorners[0].y;
patternPlane[1].x = patternCorners[4].x;
patternPlane[1].y = patternCorners[4].y;
patternPlane[2].x = patternCorners[19].x;
patternPlane[2].y = patternCorners[19].y;
patternPlane[3].x = patternCorners[15].x;
patternPlane[3].y = patternCorners[15].y;
	cvGetPerspectiveTransform(imagePlane, patternPlane, warpMatrix);
	cv::Mat rvec(3,1,cv::DataType<double>::type);
cv::Mat tvec(3,1,cv::DataType<double>::type);
std::vector<cv::Point3d> objectPoints(4);
std::vector<cv::Point2d> imagePoints(4);
for( int i = 0; i < 4; ++i)
{
objectPoints[i].x = patternPlane[i].x;
objectPoints[i].y = patternPlane[i].y;
objectPoints[i].z = 0.5;
imagePoints[i].x = imagePlane[i].x;
imagePoints[i].y = imagePlane[i].y;
}
cv::Mat distCoeffs = cv::Mat(4, 1, cv::DataType<double>::type);
distCoeffs.at<double>(0) = 0;
distCoeffs.at<double>(1) = 0;
distCoeffs.at<double>(2) = 0;
distCoeffs.at<double>(3) = 0;
	cv::Mat camMat = cv::Mat(3, 3, cv::DataType<double>::type);
cv::setIdentity(camMat);
	camMat.at<double>(0, 2) = 320;
camMat.at<double>(1, 2) = 240;
	cv::solvePnP(objectPoints, imagePoints, camMat, distCoeffs, rvec, tvec);
DebugPrint("Rotation: %f %f %f\n", (float)rvec.at<double>(0),
(float)rvec.at<double>(1),
(float)rvec.at<double>(2));
DebugPrint("Translation: %f %f %f\n", tvec.at<double>(0), tvec.at<double>(1), tvec.at<double>(2));
	cv::Mat R;
cv::Rodrigues(rvec, R);
cv::Mat T(4, 4, R.type());
T( cv::Range(0,3), cv::Range(0,3) ) = R * 1;
T( cv::Range(0,3), cv::Range(3,4) ) = tvec * 1;
double *p = T.ptr<double>(3);
p[0] = p[1] = p[2] = 0; p[3] = 1;
	glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
float mat44[16] = {(float)T.at<double>(0, 0), (float)T.at<double>(0, 1), (float)T.at<double>(0, 2), 0,
(float)T.at<double>(1, 0), (float)T.at<double>(1, 1), (float)T.at<double>(1, 2), 0,
(float)T.at<double>(2, 0), (float)T.at<double>(2, 1), (float)T.at<double>(2, 2), 0,
0,0, 0, 1};
glLoadMatrixf(mat44);
	/*glRotatef((float)rvec.at<double>(0), 1, 0, 0);
glRotatef((float)rvec.at<double>(1), 0, 1, 0);
glRotatef((float)rvec.at<double>(2), 0, 0, 1);*/
}
cvReleaseImage(&gray);
gray = NULL;
cvShowImage(WINDOW_CAPTURE_NAME, frame);
glutPostRedisplay();

}[/code]

Более-менее правильно вращается только по z. Углы по x и y получаются крайне малыми. Где-то в этом коде проется ошибка.

>> No.100893  
File: 1388780558185.png -(539321 B, 1315x519) Thumbnail displayed, click image for full size.
539321
>> No.100897  
File: 1388790938284.png -(607662 B, 838x1183) Thumbnail displayed, click image for full size.
607662

Так, похоже Intristic Parameters гораздо более важны, чем я предполагал. Похоже, в них-то все и дело.

Плохо быть тупым, новерь. Трудно и плохо.

>> No.100898  
File: 1388794251271.png -(524447 B, 1317x518) Thumbnail displayed, click image for full size.
524447

Ерунда какая-то.

>> No.100899  
File: 1388796113105.jpg -(52305 B, 720x480) Thumbnail displayed, click image for full size.
52305

>>100897

>Трудно

А можно просто использовать ARToolkit

>> No.100900  

>>100899
Действительно. Зачем разбираться как все работает, лучше еще раз скачаю библиотеку.

>> No.100902  
File: 1388830187201.jpg -(99967 B, 261x512) Thumbnail displayed, click image for full size.
99967

>>100900
Тогда нахуй OpenCV. И, чего уж там, OpenGL и stdlib тоже нахуй. Вместо того, чтобы сделать что-то полезное, ты говнокодишь очередной велосипед

>> No.101055  
File: 1389143251873.png -(541143 B, 636x480) Thumbnail displayed, click image for full size.
541143

Такие дела.

>> No.101076  

>>101055
Такое ощущение, будто чайник под углом к поверхности.

>> No.101077  

>>101055
Поздравляю, это круто

>> No.101084  

>>101076
Ага, оно ось неправильно распознало.

>> No.101086  
File: 1389201217262.jpg -(540013 B, 984x1000) Thumbnail displayed, click image for full size.
540013

>>101076
Так он и под углом же - маркер-то повернут.
>>101084
Хочется думать, что это все же иллюзия из-за освещения.

>> No.101779  
File: 1390171622177.png -(594977 B, 655x518) Thumbnail displayed, click image for full size.
594977

Чай из пустой чашки, хихик.

Углы и правда пидорасило, надо было матрицу транспонировать.
Последнее, что осталось пофиксить - корректная трансляция. Сейчас она не.

>> No.101785  
File: 1390203323253.jpg -(766921 B, 1000x1250) Thumbnail displayed, click image for full size.
766921

>>101779

>надо было матрицу транспонировать.

>>100886

>> No.101794  

>>101785
Тогда это не работало из-за других ошибок.

>> No.102284  
File: 1391360616795.jpg -(584524 B, 1280x960) Thumbnail displayed, click image for full size.
584524

Потрогать мое говно можно здесь: https://github.com/lolka359/SimpleAR

>> No.102356  

>>102284
Нужна вебка?

>> No.102608  

>>102284
А как этот код собрать и запустить?

>> No.102619  

>>102608
gcc *.cpp сработает, наверное, у меня сейчас нет опенцв, чтобы проверить. Он это в виндовсе каком-то делает, судя по всему, потому что инклудит gl/glew.h, нужно регистр папки поменять в этой строке.

>> No.103221  

ОП, выходи на связь. Хочу обсудить с тобой >>102284

>> No.103244  

>>103221
Просто напиши прямо здесь.

>> No.103664  
File: 1397257938049.png -(798035 B, 656x518) Thumbnail displayed, click image for full size.
798035

Все равно насасываю, не удается создать иллюзию объекта на маркере. Попробую назначать матрицу трансформации не объекту, а камере.

>> No.103665  

Забыл, перевести BGR в RGB, но черт возьми, мне нравится эта синяя гамма.

>> No.103666  

>>103664
Освещение не согласовано.

>> No.103677  

>>103664
Принцесса живая :3

>> No.103679  
File: 1397307263846.jpg -(568330 B, 2480x3507) Thumbnail displayed, click image for full size.
568330

>>103664

>Попробую назначать матрицу трансформации не объекту, а камере.

Разницы нет, матрицы всё равно потом перемножаются. Разве только ты не справа умножаешь. Скорее всего, ты выбрал неправильную проекционную матрицу для камеры, попробуй поменять fov

>> No.103766  
File: 1397666992599.png -(718315 B, 656x518) Thumbnail displayed, click image for full size.
718315
>> No.103767  
File: 1397667575730.png -(604856 B, 656x518) Thumbnail displayed, click image for full size.
604856
>> No.103812  

Лол, все оказалось очень просто:

  1. Центр объектов был в (0; 0; 0).
  2. Координаты модели надо было задавать так, чтобы центр модели был в (0; 0; 0).
>> No.103813  

Т.е маркер как бы разделял объект пополам, но его изображение это просто видео в ортогональной проекции, так что "невидимая" часть объекта оставалась видимой. Отсюда и эффект "гуляния".

>> No.104649  
File: 1402249036256.jpg -(55187 B, 436x600) Thumbnail displayed, click image for full size.
55187

Когда-нибудь я к этому вернусь. Но определенно не в ближайшее время.
А пока - немного исходников уровня /b:
Первое - нарезчик слайсов. Это первое звено в цепи.
[code]#include "stdafx.h"
#include <windows.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
#include <fstream>
#include <stdio.h>

#define WINDOW_NAME "0"

int main(int argc, char** argv)
{

char buf[MAX_PATH];
CvCapture * capture = cvCaptureFromCAM(0);
cvNamedWindow(WINDOW_NAME, 1);
CvFont font;
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5);
IplImage * image;
int c;
bool captureEnabled = false;
int framesCaptured = 0;
while( true)
{
image = cvQueryFrame(capture);
c = cvWaitKey(1);
if( c == VK_ESCAPE)
break;

if( c == 116) // t
captureEnabled = !captureEnabled;
	if( captureEnabled)
{
sprintf(buf, "%sframe%d.jpg", argv[1], framesCaptured);
cvSaveImage(buf, image);
printf("%s\n", buf);
sprintf(buf, "%d frames captured. Press 't' to stop.", framesCaptured);
cvPutText(image, buf, cvPoint(0, 15), &font, CV_RGB(0, 255, 0));
++framesCaptured;
}
else
{
framesCaptured = 0;
cvPutText(image, "Press 't' to start capturing", cvPoint(0, 15), &font, CV_RGB(0, 255, 0));
}

cvLine(image, cvPoint(cvGetSize(image).width / 2, 0),
cvPoint(cvGetSize(image).width / 2, cvGetSize(image).height),
CV_RGB(0, 255, 0), 1, CV_AA);
cvShowImage(WINDOW_NAME, image);
/*if( image )
cvReleaseImage(&image);*/
}
cvReleaseCapture(&capture);
return 0;

}

[/code]

>> No.104650  
File: 1402249126496.jpg -(149509 B, 500x493) Thumbnail displayed, click image for full size.
149509

Второй этап - первичная обработка.
[code]
#include <windows.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <iostream>
#include <fstream>
#include <stdio.h>

int main(int argc, char** argv)
{

// usage: <path to directory with raw slices> <start slice> <end slice> <path to directory with prepared slices>
char buf[MAX_PATH];
IplImage * image;
IplImage * final;
int start = atoi(argv[2]);
int end = atoi(argv[3]);
for( int i = start; i < end; i++)
{
sprintf(buf, "%sframe%d.jpg", argv[1], i);
image = cvLoadImage(buf, CV_LOAD_IMAGE_GRAYSCALE);
final = cvCreateImage(cvGetSize(image), 8, 1);
cvSet(final, CV_RGB(0, 0, 0));
	//cvLaplace(image, image, 5);
//cvSmooth(image, image, CV_GAUSSIAN, 3, 0, 3, 7);
cvThreshold(image, image, 48/*64*/, 255, CV_THRESH_BINARY);
//cvCanny(image, image, 250, 50, 5);
	CvSize size = cvGetSize(image);
for( int x = 0; x < image->width - 1; ++x)
for( int y = 0; y < image->height - 1; ++y)
if(((uchar*)(image->imageData + image->widthStep * y))[x] == 0xFF)
{
int yy = y;
for(; y < image->height - 1; ++y)
if(((uchar*)(image->imageData + image->widthStep * y))[x] != 0xFF)
{
if( y == image->height - 1)
yy += ((y - 1) - yy) / 2;
else
yy += (y - yy) / 2;
cvLine(final, cvPoint(x, yy), cvPoint(x,yy), CV_RGB(255, 255, 255), 1, 8);
break;
}
}
sprintf(buf, "%s%d.jpg", argv[4], i);
cvSaveImage(buf, final);
printf("%d of %d image(s) done\n", i, end);
}
return 0;

}[/code]

>> No.104651  
File: 1402249283276.jpg -(49509 B, 600x600) Thumbnail displayed, click image for full size.
49509

И последний этап, ебем картинки, получаем точки.
[code]#include "opencv/cv.h"
#include "opencv/highgui.h"
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <math.h>
#include <iostream>
#include <fstream>
#include <stdio.h>

using namespace cv;

#define EPSILON 0.1

void GetLongestLine(CvArr * image, CvPoint * pt1, CvPoint * pt2);
CvPoint2D32f IntersectionPoint(CvPoint pt1, CvPoint pt2, CvPoint pt3, CvPoint pt4);
CvPoint2D32f Perpendicular(CvPoint2D32f p1, CvPoint2D32f p2, CvPoint2D32f p);
float AngleBetweenLines(CvPoint2D32f pt1, CvPoint2D32f pt2, CvPoint2D32f pt3, CvPoint2D32f pt4);

int main(int argc, char ** argv)
{

if( argc < 5)
{
printf("Not enough arguments. Must be 4.\n");
return 0;
}

int start = atoi(argv[2]); // Начальный индекс слайса.
int end = atoi(argv[3]); // Конечный индекс слайса.
std::fstream file; // Выходной файл с облаком точек.
char filename[MAX_PATH]; // Путь к файлу слайса.
IplImage * slice;
file.open(argv[4], std::ios::out);

char buf[MAX_PATH];
char buf2[5];
int sliceIndex = 0;

CvPoint2D32f center;
CvPoint2D32f ptLd;
CvPoint2D32f ptRd;
CvPoint2D32f leftLowerLine;
CvPoint2D32f rightLowerLine;
bool b = true;
for( sliceIndex = start; sliceIndex < end; sliceIndex++)
{
sprintf(filename, "%s%d.jpg", argv[1], sliceIndex);
printf("Processing of %s\n", filename);
slice = cvLoadImage(filename, CV_LOAD_IMAGE_GRAYSCALE);
CvPoint pt1, pt2, pt3, pt4; // pt1, pt2 - левый отрезок, pt3, pt4 - правый отрезок
CvPoint pt;
int width = cvGetSize(slice).width;
int height = cvGetSize(slice).height;
// Устанавливаем область интереса на левую сторону изображения.
cvSetImageROI(slice, cvRect(0, 0, width / 2, height));
// Находим самый длинный отрезок в левой стороне изображения.
GetLongestLine(slice, &pt1, &pt2);

// На правую частб экрана.
cvSetImageROI(slice, cvRect(width / 2, 0, width / 2, height));
// Самый длинный отрезок на правой стороне изобрежения.
GetLongestLine(slice, &pt3, &pt4);

pt3.x += width / 2; // снятие последствий применения ROI
pt4.x += width / 2; // снятие последствий применения ROI
	cvResetImageROI(slice);
	if( pt2.y < pt1.y)
{
CvPoint temp = pt1;
pt1 = pt2;
pt2 = temp;
}
if( pt3.y > pt4.y)
{
CvPoint temp2 = pt3;
pt3 = pt4;
pt4 = temp2;
}
	ptLd = IntersectionPoint(pt1, pt2, cvPoint(320, 0), cvPoint(320, height));
ptRd = IntersectionPoint(pt3, pt4, cvPoint(320, 0), cvPoint(320, height));
	// Точка пересечения прямых.
center = cvPoint2D32f((ptLd.x + ptRd.x) / 2.0, (ptLd.y + ptRd.y) / 2.0);
	//center = IntersectionPoint(pt1, pt2, pt3, pt4);


// Нижняя точка левой линии.
leftLowerLine = cvPoint2D32f(pt1.x, pt1.y);
// Нижняя точка правой линии.
rightLowerLine = cvPoint2D32f(pt3.x, pt3.y);


// Достраиваем точку до пересечения с осью абсцисс.
// С левой абсциссой.
CvPoint2D32f ip = IntersectionPoint(cvPoint(center.x, center.y),
cvPoint(pt2.x, pt2.y/*leftLowerLine.x, leftLowerLine.y*/),
cvPoint(0, 0), cvPoint(0, height));
leftLowerLine.x = 0;
leftLowerLine.y += fabs(ip.y - leftLowerLine.y);
// С "правой" абсциссой.
ip = IntersectionPoint(cvPoint(center.x, center.y), cvPoint(pt4.x, pt4.y/*rightLowerLine.x, rightLowerLine.y*/),
cvPoint(width, 0), cvPoint(width, height));
rightLowerLine.x = width;
rightLowerLine.y += fabs(ip.y - rightLowerLine.y);
	for( int x = 0; x < width; x++)
for( int y = 0; y < height; y++)
if( ((uchar*)(slice->imageData + slice->widthStep * y))[x] == 0xFF)
{
CvPoint2D32f point = cvPoint2D32f(x, y);
CvPoint2D32f pPerp = Perpendicular(center, leftLowerLine, point);
CvPoint2D32f p = cvPoint2D32f( abs(pPerp.x - center.x), abs(pPerp.y - center.y));
double mX = sqrt(pow(center.x - p.x, 2.0f) + pow(center.y - p.y, 2.0f));

pPerp = Perpendicular(center, rightLowerLine, point);
p = cvPoint2D32f( abs(pPerp.x - center.x), abs(pPerp.y - center.y));
double mY = sqrt(pow(center.x - p.x, 2.0f) + pow(center.y - p.y, 2.0f));

if( fabs((point.y - leftLowerLine.y) / (center.y - leftLowerLine.y) -
(point.x - leftLowerLine.x) / (center.x - leftLowerLine.x)) <= EPSILON )
continue;
if( fabs((point.y - rightLowerLine.y) / (center.y - rightLowerLine.y) -
(point.x - rightLowerLine.x) / (center.x - rightLowerLine.x)) <= EPSILON)
continue;
file << mX << " " << mY << " " << center.y << std::endl;
}
	cvReleaseImage(&slice);
}
file.close();
return 0;

}

/* ************************************************************* */
/* Находит самую длинный отрезок на изображении. */
/* image - изображение. pt1, pt2 - координаты отрезка. */
/* ************************************************************* */
void GetLongestLine(CvArr * image, CvPoint * pt1, CvPoint * pt2)
{

CvMemStorage * storage = cvCreateMemStorage(0);
/* 1 - изображение.
2 - место, куда сохраняются найденные точки.
3 - тип метода
4 - разрешение в пикселах еденицы изображения
5 - угловое разрешение в радианах
6 - пороговое значение аккумулятора
7 - минимальная длина линии
8 - максимальный разрыв между отрезками для восприятия их как единой линии
*/
CvSeq * res = cvHoughLines2(image, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180.0, 60, 70, 5);
if( res->total > 0)
{
CvPoint * line = (CvPoint *)cvGetSeqElem(res, 0);
double maxL = sqrt(pow(abs(line[0].x - line[1].x), 2.0) + pow(abs(line[0].y - line[1].y),2.0));
double d;
int index = 0; // Индекс самого длинного отрезка.
// Находим самый длинный отрезок.
for( int i = 1; i < res->total; i++)
{
d = sqrt(pow(abs(line[i].x - line[i-1].x), 2.0) + pow(abs(line[i].y - line[i-1].y),2.0));
if( maxL < d )
{
maxL = d;
index = i;
}
}
CvPoint *maxLine = (CvPoint*)cvGetSeqElem(res, index);
*pt1 = maxLine[0];
*pt2 = maxLine[1];

}
else
{
*pt1 = cvPoint(0, 0);
*pt2 = cvPoint(0, 0);
}
cvReleaseMemStorage(&storage);

}

/* ************************************************************************ */
/* Находит точку пересечения двух прямых. */
/* pt1, pt2 - перый отрезок. pt3, pt4 - второй отрезок. */
/* Возвращает точку пересечения прямых. */
/* ************************************************************************ */
CvPoint2D32f IntersectionPoint(CvPoint pt1, CvPoint pt2, CvPoint pt3, CvPoint pt4)
{

CvPoint2D32f result;
double A1, B1, C1, A2, B2, C2;
// Находим коэффициенты уравнения первой прямой по двум точкам.
// Ax + By + C = 0
A1 = pt1.y - pt2.y;
B1 = pt2.x - pt1.x;
C1 = pt1.x * pt2.y - pt2.x * pt1.y;
// Второй прямой.
A2 = pt3.y - pt4.y;
B2 = pt4.x - pt3.x;
C2 = pt3.x * pt4.y - pt4.x * pt3.y;
// По формуле Крамера находим точку пересечения прямых.
// Если знаменатель дробей равен нулю, прямые не пересекаются.
double ZX = A1 * B2 - A2 * B1;
if( ZX == 0 )
{
result = cvPoint2D32f(0, 0);
return result;
}
result.x = -((C1 * B2 - C2 * B1) / ZX);
result.y = -((A1 * C2 - A2 * C1 ) / ZX);
return result;

}

/* ********************************************************************** */
/* Находит перпендикуляр точки к отрезку. */
/* pt1, pt2 - координаты отрезка, p - координаты точки. */
/* ********************************************************************** */
CvPoint2D32f Perpendicular(CvPoint2D32f p1, CvPoint2D32f p2, CvPoint2D32f p)
{

CvPoint2D32f c = cvPoint2D32f( p.x - p1.x, p.y - p1.y);
CvPoint2D32f b = cvPoint2D32f( p2.x - p1.x, p2.y - p1.y);
// Нормализация.
double length = sqrt( pow(b.x, 2.0f) + pow(b.y, 2.0f) );
CvPoint2D32f d = cvPoint2D32f( b.x / length, b.y / length);
double vdot = d.x * c.x + d.y * c.y;
CvPoint2D32f j = cvPoint2D32f( d.x * vdot, d.y * vdot);
return cvPoint2D32f( j.x - c.x, j.y - c.y);

}

float AngleBetweenLines(CvPoint2D32f pt1, CvPoint2D32f pt2, CvPoint2D32f pt3, CvPoint2D32f pt4)
{

double A1, B1, C1, A2, B2, C2;
// Находим коэффициенты уравнения первой прямой по двум точкам.
// Ax + By + C = 0
A1 = pt1.y - pt2.y;
B1 = pt2.x - pt1.x;
C1 = pt1.x * pt2.y - pt2.x * pt1.y;
// Второй прямой.
A2 = pt3.y - pt4.y;
B2 = pt4.x - pt3.x;
C2 = pt3.x * pt4.y - pt4.x * pt3.y;
float res = acos(
(B1 * B2 + A1 * A2) / (sqrt(pow(B1, 2.0) + pow(A2, 2.0)) * sqrt(pow(B2, 2.0) + pow(A2, 2.0)))
);
return (180.0f / CV_PI) * res;

}[/code]

>> No.104660  

>>104649
Положи их на гитхаб какой-нибудь.

>> No.110310  

bump



Delete Post []
Password

[/b/] [/d/] [/tu/] [/a/] [/ph/] [/wa/] [/cg/] [/t/] [/p/]