-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNotas.tex
2603 lines (1994 loc) · 291 KB
/
Notas.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Work done so far}
\label{chap:trabalho_semanal}
In this chapter I will explain all the research I have done until now.
\section{Trabalho Semanal - (Apenas para registo/nota)}
\label{chap5:sec:TD}
\subsection{1º Semana - 16 de Setembro a 22 de Setembro}
\label{chap5:sec:TD:Semana1}
Leitura do relatório de Ricardo Domingos com o título, "Artificial Vision for Blind People", para puder obter mais informação sobre os típicos problemas e dificuldades na construção de sistemas para invisuais.
Foram encontradas diversas dificuldades...
Testar o código desenvolvido pelo Ricardo Domingos no sistema Raspberry PI 3 + Camâra 3D RealSense + Bateria share
Portátil. Para isso foi necessário construir este sistema portátil.
- clone do repositório clone https://github.com/Inte\^C, este repositório serve para instalar a camâra 3D realSense no sistema operativo ( Intel® RealSense™ SDK ).
- seguir as instruções da intel para se instalar o realsense sdk.
-Make Ubuntu Up-to-date:
-Download/Clone librealsense github repository:
-Prepare Linux Backend and the Dev. Environment:
-Building librealsense2 SDK\
-[Tutorial] - Activate OpenGL driver for ubuntu mate 16.04
\bigskip
Configuração da câmara RealSense tanto no computador do laboratório como no Raspberry PI 3.
\bigskip
O Raspberry PI 3 teve de ser formatado visto que só era detetada metade da memória RAM, (512 Mb).
Estou a ter problemas a instalar no computador... 53\% dá erro. Vou tentar instalar no master branch. também deu o mesmo erro.
instalei agora por aqui : "https://github.com/IntelRealSense/librealsense/ blob/development/doc/distribution\_linux.md", e já deu para utilizar o viewer realsense.
\bigskip
Tentou-se instalar o viewer no raspberry PI B+, mas devido à sua capacidade de memória RAM (1Gb) não se consegiu instalar. Tentou-se aumentar a swap area para (2Gb) e voltou-se a tentar instalar.
\bigskip
% Dia seguinte.
Testar os exemplos do site no computador do lab. hello-world e save-to-disk.
Alguns exemplos não estavam a dar, estou a tentar resolver neste site, https://dev.intelrealsense.com/docs/compiling-librealsense-for-linux-ubuntu-guide.
Os exemplos que a intelrealsense disponibiliza em cpp estão a dar alguns problemas no computador de diretorias. Testar exemplos em python que é uma linguagem que estou muito mais à vontade.
Os programas em python usados como exemplos para realsense correm sem qualquer problema.
Foi desenvolvido um programa para guardar a imagem RGB + Depth ( 1 frame) para ser utilizado mais tarde no Raspberry PI. Este programa foi desenvolvido e funciona no computador do lab.
Foi instalado o cython no raspberry PI para se puder instalar o pyrealsense2.
seguiu-se um tutorial para instalar o pyrealsense2 no raspberry, mas está um pouco obsolento e há packages que já não estão a funcionar, teve-se de procurar alternativas para instalar as várias dependencias que o pyrealsense necessita. Protobf instalado com sucesso. OpenCv deu bastante trabalho.+-
sites utilizados até agora:
Instalação completa para o raspberry, o problema é que para instalar o pyrealsense é necessário instalar outros pacotes.
-https://github.com/IntelRealSense/librealsense/blob/master/doc/RaspberryPi3.md
Tutorial mais expecifico para instalar tudo o que é necessário para se puder instalar depois o pyrealsense.
-https://github.com/IntelRealSense/librealsense/blob/master/doc/installation\_raspbian.md
Site para instalar o protocol-buffer que era referido no site anterior mas pelos comandos e instruções não estava a conseguir instalar, no fundo é uma alternativa.
-https://osdevlab.blogspot.com/2016/03/how-to-install-google-protocol-buffers.html
Site para instalar o OpenCV no raspberry PI, com vários passos.
-https://www.pyimagesearch.com/2017/09/04/raspbian-stretch-install-opencv-3-python-on-your-raspberry-pi/
https://www.learnopencv.com/install-opencv-4-on-raspberry-pi/
instalei a PCL
replicar trabalho do Ricardo + instalar no raspberry PI
\bigskip
Quinta-feira - 19/07/2019
: - Fui procurar a rede e o repositório que o Ricardo utilizou no seu trabalho. Instalei o pytorch e tive algumas problemas para instalar o repositório.
sudo python3 setup.py install (tive de usar sudo e python3 que é o que funciona) No python 2 não funciona.
Continuo a tentar instalar o realsense no raspberry... 89\%
raspberry já têm o software realsense-viewer instalado com sucesso.
No computador do laboratório estou a alterar o código desenvolvido pelo Ricardo para guardar imagens RGB mas também imagens Depth e só guardar quando é pressionado uma tecla específica e não estar continuamente a guardar imagens. A maneira de como as imagens são guardadas foi alterada para guardar a imagem com a data em que a mesma foi guardada.
As imagens continuam com a tal "ondulação". (Instalando a pcl e utilizando o script pcd2pcl, e depois utilizando o viewer\_pcl observei estes resultados)
\bigskip
Sexta-feita - 20/07/2019
Faltava instalar algumas coisas da realsense para se detetar o modulo pyrealsense2 no python e o mesmo com o opencv... Instalou-se ainda o modulo keyboard no python que também era necessário para o programa desenvolvido.
Instalação da biblioteca pyrealsense2 concluída com sucesso.
Testei o programa e correu tudo bem, ou seja, já é possível com o sistema raspberry PI 3+ tirar fotografias com a câmara realsense D345 e guardar a imagem RGB + imagem Depth. Com um dos programas/exemplo da pcl, é possível utilizando ambas as imagens RGB e Depth converter para um ficheiro do tipo pcd (point cloud data) para podermos visualizar a nuvem de pontos.
https://we.tl/t-yHFy0Nro0y
Fiz o tutorial todo https://github.com/IntelRealSense/librealsense/blob/master/doc/installation\_raspbian.md para instalar a biblioteca realsense no raspberry pi. É importante dizer que alguns passos deste tutorial não funcionavam e então foram encontradas outras maneiras para instalar bibliotecas que eram necessárias para a instalação do realsense. As bibliotecas que tiveram de ser instalas de maneira diferente do tutorial foram o opencv e o protobuff. É necessário colocar o programa executável dentro de uma diretoria onde está localizado o ficheiro realsense.so para o python conseguir detetar a biblioteca quando o programa é compilado. Isto só é necessário no sistema raspberry, no computador fixo não é preciso colocar o ficheiro python numa localização específica.
(Outro aparte) Não foi necessário instalar o OpenGL, apesar de o mesmo estar no tutorial acima como uma dependência necessária para a biblioteca realsense.
O raspberry não será o equipamento final a ser utilizado neste trabalho mas está preparado para correr o código desenvolvido para guardar imagens com profundidade e RGB. Um dos problemas é que com todas as bibliotecas e dependências necessárias, o dispositivo ficou com apenas 2.5Gb de espaço, sendo que este espaço será utilizado para armazenar temporariamente as imagens capturadas pela câmara realsense.
\bigskip
Segunda-feira - 23/07/2019
Estou a fazer este tutorial : https://github.com/huanghoujing/PyTorch-Encoding/blob/master/Install\_Prerequisite\_for\_Pytorch\_Encoding.md - serve para instalar o repositório utilizado pelo Ricardo para fazer a segmentação semântica assim como as dependências do mesmo.
NOTAS:
WORKING\_DIR = /home/socialab/Documents/Torch/
CUDA = /usr/local/cuda ou /usr/local/cuda-10.0
Estavam a dar erros e então para facilitar a instalação criei uma ambiente virtual onde as bibliotecas de python instaladas no computador não estão presentes neste ambiente virtual. Recorri ao site, https://docs.python.org/3/tutorial/venv.html, comandos: python3 -m venv tutorial-env, source tutorial-env/bin/activate e para sair basta utilizar o comando exit.
O tutorial foi novamente repetido mas desta vez no ambiente virtual.
git clone https://github.com/zhanghang1989/PyTorch-Encoding
pip install torchvision
pip install torch==1.0.0
pip install torch-enconding
a versão tem de ser 1.0.0 do torch. pip install torch==1.0.0
https://hangzhang.org/PyTorch-Encoding/notes/compile.html
Ainda deu uns erros quando se tentou correr o setup para se testar um modelo pré-treinado no "Enconding".
Foi necessário ainda instalar a biblioteca cython.
pip install cython
https://hangzhang.org/PyTorch-Encoding/experiments/segmentation.html
Segui o tutorial do repositório utilizado pelo Ricardo, corri o script para preparar o dataset ADE20K que foi o mesmo dataset utilizado pelo Ricardo.
python scripts/prepare\_ade20k.py
Isto está tudo a correr no ambiente virtual tutorial-env.
O que vou fazer:
Testar com modelo pré-treinado e imagens ADE20K.
-Deu erro utilizando o comando "python train.py --dataset ADE20K --model EncNet --aux --se-loss" Tive de alterar o ficheiro,
"/home/socialab/tutorial-env/lib/python3.7/site-packages/encoding/models/\_\_init\_\_.py" e comentei 'atten': get\_atten e 'encnetv2': get\_encnetv2,
treinar com toda a base de dados ADE20K não funciona como era de esperar. (CUDA out of memory)
Deu um erro no test, foi necessário instalar a biblioteca matplotlib, com o comando:
python -m pip install -U matplotlib
Download do modelo ResNet101\_ADE20K, o mesmo utilizado pelo Ricardo.
/home/socialab/.encoding/models/ - localização de todos os modelos.
Avaliar as imagens demora muito tempo, por defeito o código avalia 2000 imagens.
Este script é para avaliar 2000 imagens do ADE20K
python test.py --dataset PContext --model-zoo Encnet\_ResNet50\_ADE20 --eval
% Posso tirar umas 20 imagens aqui da porta do laboratório só para testar o modelo pré treinado no ADE20K e depois puder tirar as conclusões. O Ricardo conseguiu fazer bem a segmentação da porta.
Correr o "demo.py" com essas imagens,
Ver se não é preciso reduzir as imagens ou não. (Não é necessário reduzir o tamanho das imagens)
Ver se a segmentação está a ser bem feita ou não. (Está mais ou menos)...
Utilizei o modelo encnet\_resnet101\_ade e obtive resultados muitos melhores comparativamente com o modelo pre-definido fcn\_resnet50\_ade.
\bigskip
Terça-feira - 24/09/2019
Modifiquei o programa que será utilizado no raspberry PI, visto que estava a dar alguns problemas com a função wait() do pacote keyboard, onde a mesma foi substituída pela função raw\_input. Utilizou-se um "apontador de slides" para funcionar como teclado, para o sistema raspberry ser mais portátil.
Este apontador de slides possuí algumas teclas e tirando proveito do mesmo o programa para o raspberry PI foi modificado mais uma vez. Quando o utilizador carrega numa tecla "w" é guardada a imagem da câmara como "porta fechada" e quando carrega na tecla "b" a imagem da câmara é guardada com o nome "porta aberta". Deste modo é possível já classificar as imagens no momento de captura das mesmas, tornando o processo muito mais eficiente. As imagens também já sao guardadas em diferentes pastas consoante a sua classe.
Alteração do programa "demo" do repositório https://hangzhang.org/PyTorch-Encoding, nomeadamente na palete de cores ADE20K, de modo a representar apenas as classes que queremos para o nosso problema. Neste caso essas classes são "door", "floor" e "wall".
Modificação no ficheiro - pallete.py, linha 48, adepallete.
Para esta modificação foi necessário saber quais os índices segundo o conjunto de dados ADE20K que correspondiam às classes "door", "floor" e "wall". O valor da pallete RGB para os restantes índices das outras classes foi alterado para "0,0,0 (r,g,b)", visto que as mesmas não interessavam para o problema.
\bigskip
Quarta-feira - 25/09/2019
A próxima tarefa a replicar no trabalho do Ricardo Domingos era calcular a maior área para cada uma das 3 classes na imagem 'png' já segmentada. Para depois se recordar e fazer-se uma 'bounding-box' à volta de cada uma das classes, áreas maiores.
Estou a implementar o que o Ricardo fez mas a alterar um pouco o seu código e a tentar perceber passo a passo, no FINAL, colocar aqui todos os passos e o que cada instrução mais ou menos faz. Explicar tudo direito com imagens.
Calculei a área maior de todos os "clusters", objetos para cada uma das classes.
Criação da bounding box à volta da representação maior da área da porta, do chão e da parede.
Cada imagem gera 3 imagens recortadas segundo esta bounding-box.
Código para rodar a imagem 270 graus.
\bigskip
Quinta-feira - 26/09/2019
Depois de conseguir replicar parte do que o Ricardo desenvolveu, nomeadamente no cálculo da maior área de cada classe e recortar a imagem original RGB e Depth tentei criar a nuvem de pontos recortada para cada classe (door, wall and floor). Deu erro, "Component number of depth input file should be 1". Consegue-se criar a nuvem de pontos da imagem original a partir da informação RGB e Depth sem qualquer problema, mas para as imagens recortadas por algum motivo não é possível.
import pcl, não estava a funcionar no ambiente virtual, para tal basta fazer:
https://python-pcl-fork.readthedocs.io/en/rc\_patches4/install.html\#install-python-pcl
instalação python pcl
sudo apt install libpcl-dev -y
pip install python-pcl
\bigskip
Sexta-feira - 27/09/2019
Tentar instalar o pythorch outra vez no ambiente virtual para este projeto...
O pip não funciona no ambiente virtual, vou criar um novo ambiente virtual e começar tudo de novo, para ter a certeza que não existem inconsistências de bibliotecas e outros erros que aconteciam no ambiente virtual antigo.
Criação de novo ambiente virtual:
https://docs.python.org/3/tutorial/venv.html
ambiente virtual: human-vision
Instalação da pcl:
https://python-pcl-fork.readthedocs.io/en/rc\_patches4/install.html\#install-python-pcl
sudo apt install libpcl-dev -y
pip install -U cython
pip install numpy
pip install -U setuptools
git clone https://github.com/strawlab/python-pcl.git na pasta human-vision
python setup.py install - NÃO ESTÁ A DAR...
pip install torchvision
pip install torch==1.0.0
python -m pip install -U matplotlib
Dependências do encoding:
pip3 install requests
pip3 install tqdm
pip3 install scipy
import torch e import encoding já deve estar a funcionar
pip3 install opencv-python (import cv2 já deve funcionar)
pip3 install python-pcl - X Não dá
http://www.pcl-users.org/pcl-1-8-build-problems-td4043322.html
VTK para resolver a pcl:
To download the source code
\# git clone git://vtk.org/VTK.git
\# cd VTK
To update the code
\# git fetch origin
\# git rebase origin/master
cd \$HOME
wget http://www.cmake.org/files/v2.8/cmake-2.8.12.2-Linux-i386.tar.gz
mkdir software
cd software
tar xvfz ../cmake-2.8.12.2-Linux-i386.tar.gz
python -m pip install vtk -> não funcionou...
sudo apt-get install build-essential libxmu-dev libxi-dev libgl-dev libosmesa-dev
HOMEBREW\_MAKE\_JOBS=1 brew install vtk -v
sudo apt-get install libgl1-mesa-dev
brew install --only-dependencies llvm@4
brwe upgrade
sudo rm /usr/lib/x86\_64-linux-gnu/libGL.so
sudo ln -s /usr/lib/libGL.so.1 /usr/lib/x86\_64-linux-gnu/libGL.so
Estou a seguir este site:
https://gist.github.com/IgniparousTempest/ce5fadbe742526d10d6bdbf15c3a3fe7
sudo add-apt-repository ppa:sweptlaser/python3-pcl
sudo apt update
sudo apt install python3-pcl
\bigskip
Domingo - 29/09/2019
Estou a seguir este tutorial...
https://sites.google.com/view/brown-vr-sw-review-2018/course-homepage/data-types-and-examples/python-pcl-tutorial
sudo apt-get install python3-sphinx
não funcionou
Tirei várias fotos a portas abertas e fechadas.
\bigskip
Segunda-feira - 30/09/2019
Instalar biblioteca open3d - "http://www.open3d.org/docs/release/getting\_started.html"
Esquecer por agora o corte das imagens originais nas 3 classes que inicialmente eram utilizadas para se detetar se a porta estava aberta ou fechada. Isto porque, existem casos em que o maior plano da porta vai ser perpendicular à porta mas a mesma não está aberta mas sim fechada. Ou seja, o método utilizado anteriormente falha para um caso geral da vida real, onde as portas não estão em paredes paralelas à mesma sempre.
Não consegui instalar a pcl e por isso instalei a biblioteca open3d para converter as imagens RGB + Depth em nuvens de pontos, mas o problema que residia na pcl, é que quando as imagens são recortadas o seu ângulo (vertical + horizontal) altera e por isso a sua visualização não é possível sem se alterar nos parâmetros estes ângulos de abertura. Neste caso eram alterados na função pcl-png2pcd, mas visto já não se usar esta abordagem não se utilizou.
A próxima abordagem é utilizar uma rede neuronal que tenha como input imagens com 4 canais, RGB + Depth e que devolva como output se a porta está aberta ou fechada. Para tal é preciso estudar-se o que já existe e como funcionam essas redes. É também necessário completar a base de dados e usar técnicas de "data augmentation" para aumentar a nossa base de dados e fazer com que os dados sejam mais gerais para a rede generalizar mais.
Leitura do artigo PointNet++ : https://arxiv.org/pdf/1711.08488v2.pdf
Notas:
Utilizam RGB + Depth para detetar objetos em espaços indoor e outdoor. Utiliza 2D deteção na imagem RGB e depois usam 3D deep learning para saber a localização desse mesmo objeto no espaço 3D. Constroem uma bounding box 3D na nuvem de pontos. Evaluated on KITTI and SUN RGB-D 3D detection benchmarks.
Eles defendem que não se deve converter as nuvens de pontos 3D para imagens através da projecção mas sim processar as nuvens de pontos diretamente sem as converter para outro formato. Isto porque, ao projetar-mos as nuvens de pontos esta-se a criar invariações nos dados e a
PointNet ->
Leitura do artigo PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation: (https://arxiv.org/pdf/1612.00593v2.pdf)
Notas:
Redes convolucionais que têm como input uma nuvem de pontos diretamente - PointNet. Estas redes são usadas em classificação de objetos, segmentação semântica, segmentação de partes de objetos, etc... A vantagem destas redes é que consomem nuvens de pontos sem qualquer tipo de renderização ou "voxelization", o que por um lado há um aumento de desempenho, visto que o computador não perde tempo a renderizar os dados de entrada e por outro lado nenhuma informação é perdida. Se fosse feito uma renderização ou "voxelization", para além do tempo que estas demorariam, algumas invariâncias naturais dos dados 3D eram obscurecidas e perdidas.
Outra vantagem é que, assim, os dados não são tão volumosos como seriam caso fossem renderizados ou transformados em grelhas de voxel 3D.
No estado inicial cada ponto é processado identicamente e individualmente, sendo representado apenas por 3 coordenadas (x,y e z). Usam o max polling porque é uma função simétrica. A rede aprende um conjunto de funções de otimização para escolher pontos interessantes ou informativos e apresenta as razões porque os escolheu. A ultima camada fully connected agrega estes valores num descritor global. A rede consegue sumarizar um nuvem de pontos de input através dos pontos chave(esqueleto dos objetos) da mesma.
Já existem várias redes para Deep Learning em dados 3D. As pioneiras são as Volumetric CNN's, mas o grande problema das mesmas é que o custo computacional das convoluções 3D e a escassez dos dados. A escassez dos dados, visto que temos mais uma características nos nossos dados de entrada (Depth), logo temos de ter muitos mais exemplos na nossa base de dados.
Depois vieram as FPNN e as Vote3D que já lidam melhor com o problema da escassez dos dados, mas ainda não conseguem processar nuvens de pontos muito grandes.
Multiview CNN renderiza as nuvens de pontos 3D em imagens 2D e depois aplica redes convolucionais 2D para as classificar. São boas em classificação de forma e tarefas triviais mas não são boas para conhecimento da cena e point classification.
Feature-based DNN's, convertem os dados 3D para um vetor e depois usam uma rede fully connected para classificar a forma. O problema é que estão restringidas ao poder da representação das características extraídas.
Uma nuvem de pontos no fundo é um conjunto de vectores não ordenados. Cada nuvem de pontos é representada por um conjunto de pontos 3D onde cada ponto contém no mínimo 3 valores, podendo estes aumentar para mais (cor, normal, etc).
Deep network outputs k scores for all the k candidate classes
global descriptors or global features levam em conta toda a cena (grid).
local descriptors or local features só levam em conta o objeto e o problema é que o objeto nem sempre tem o mesmo tamanho e então entram dados de diferentes tamanhos para a rede.
O modelo tem em conta pontos vizinhos. A representação aprendida pela rede do conjunto de pontos deve ser invariante a determinadas transformações como rotação, translação. Estas transformações não devem alterar a categoria global da nuvem de pontos ou a segmentação dos mesmos.
Foi usada uma função simétrica para no fundo conseguir-se a invariância de permutações dos dados de entrada. Esta função vai agregar a informação de cada ponto. Aplicar uma multi camada de percepção aos pontos ordenados é um pouco melhor que processar diretamente os dados de entrada não ordenados.
Primeiro determinam as características globais e depois com as mesmas determinam as características locais, concatenando as duas. Depois são extraídas as características de cada ponto, já tendo em conta a informação local e global.
PointNet itself allows individual inputs to vary in the number of points as a symmetric max function would erase the difference in dimension.
O código show\_cls não estava a funcionar, é necessário corre-lo na pasta home do repositório. É necessário acrescentar o caminho do modelo que queremos usar.
\bigskip
Terça-feira - 01/10/2019
Estou a tentar implementar a pointnet, do artigo https://arxiv.org/pdf/1612.00593v2.pdf, no repositório https://github.com/fxia22/pointnet.pytorch.
Selected Projects that Use PointNet
PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space by Qi et al. (NIPS 2017) A hierarchical feature learning framework on point clouds. The PointNet++ architecture applies PointNet recursively on a nested partitioning of the input point set. It also proposes novel layers for point clouds with non-uniform densities.
Exploring Spatial Context for 3D Semantic Segmentation of Point Clouds by Engelmann et al. (ICCV 2017 workshop). This work extends PointNet for large-scale scene segmentation.
PCPNET: Learning Local Shape Properties from Raw Point Clouds by Guerrero et al. (arXiv). The work adapts PointNet for local geometric properties (e.g. normal and curvature) estimation in noisy point clouds.
VoxelNet: End-to-End Learning for Point Cloud Based 3D Object Detection by Zhou et al. from Apple (arXiv) This work studies 3D object detection using LiDAR point clouds. It splits space into voxels, use PointNet to learn local voxel features and then use 3D CNN for region proposal, object classification and 3D bounding box estimation.
Frustum PointNets for 3D Object Detection from RGB-D Data by Qi et al. (arXiv) A novel framework for 3D object detection with RGB-D data. The method proposed has achieved first place on KITTI 3D object detection benchmark on all categories (last checked on 11/30/2017).
Para o repositório da implementação da pointnet em PyTorch, para utilizar a minha base de dados tenho de colocar pastas de diferentes classes, neste caso, 2 pastas apenas, porta aperta e porta fechada. Só devo precisar dos pontos, ficheiros .pts, para entrar para a rede. Afinal é preciso os ficheiros .seg.
Os ficheiros .seg são as etiquetas dos pontos.
Cada ponto de um objeto pode pertencer a uma parte desse mesmo objeto, é estranho é que isso precise de ser utilizado no scrip de treino para classificação.
O QUE POSSO FAZER:
Envio para a rede PointNet uma nuvem de pontos com porta aberta (entreaberta) e envio uma nuvem de pontos com porta fechada. O problema é a rede não perceber o padrão certo que deve aprender, (porta estar aberta ou fechada) e aprenda outro padrão e assim não faça uma boa generalização para outros dados de entrada.
zipar a pasta tezus, linux\_brew e home. Enviar através do FileZilla.
ip config
meter ssh na aplicação.
mudar hostname no raspberry pi.
password raspberry -> "blind"
\bigskip
Quarta-feira - 02/08/2019
Neste momento estou a formatar o computador devido a o mesmo já ter bastante bibliotecas instaladas e de certeza que já existe alguma inconsistência entre várias versões de bibliotecas instaladas no ubuntu e nos interpretadores do python.
(Not important but) Estou a fazer um backup dos ficheiros, e depois vou passa-los através de ssh mas com um programa com interface gráfico, o FileZilla. Neste programa já é possível fazer-se "grap" dos ficheiros para a diretoria pretendida.
Vou agora ligar o raspberrypi e transferir os ficheiros para o computador onde também irá ser guardado o backup dos dados do computador que me foi destinado para o projeto.
Alterei os nomes dos ficheiros mais uma vez com o "script" criado para tal, database.py. Rodei todas as imagens 90 graus no sentido dos ponteiros do relógio.
Neste momento tenho mais ou menos 450 fotografias de portas, se contar com as de profundidade tenho 900 e pouco.
É preciso estudar que tipo de fotos se quer guardar na base de dados ou não. Existem fotos muito tremidas e não sei se as mesmas vão induzir a rede em erros. Para já vou manter todas as fotos na base de dados e se for necessário filtrar depois filtro.
O próximo objetivo é conseguir testar a base de dados que tenho até agora no repositório que faz a implementação da PointNet. Para isso é primeiro necessário transformar as imagens de profundidade png e as imagens de cor png para uma nuvem de pontos. Nesta altura o computador ainda não foi formatado e então não é possível utilizar a pcl no interpretador do python, mas as ferramentas da mesma já estão instaladas.
A base de dados foi dividida por tipo de objeto, até ao momento, porta aberta, porta fechada, escadas a subir e escadas a descer. Dentro de cada uma destas classes temos 3 pastas. Uma pasta com as imagens RGB, outra com as imagens correspondentes de profundidade e uma última pasta com a junção dos dois tipos de imagens anteriores numa nuvem de pontos .pcd.
Neste momento tenho, 230 imagens de portas abertas e 229 imagens de portas fechadas. 230 + 229 RGB, 230 + 229 Depth e 230 + 229 Pointcloud.
Agora é preciso converter as nuvens de pontos num ficheiro .pts tal e qual a estrutura do repositório da implementação da pointnet. Estava a dar um problema, free(): invalid pointer, Aborted (core dumped). Era devido a ambas as bibliotecas open3d e torch serem importadas... ninguém sabe o porque.
\bigskip
Quinta-feira - 03/10/2019
Formatação do computador.
Estudo AutoML da Goole Cloud AI.
In April, we announced AutoML Vision Edge to help businesses train, build and deploy ML models at the edge, beginning initially with image classification.
O AutoML vision edge é bom porque suporta uma grande variedade de hardware e que em principio tem compatibilidade com o raspberryPI e com nvidia Jetson. Permite treinar modelos de ML para classificar imagens de acordo com as etiquetas.
Para treinar um modelo são necessárias 10 imagens para cada classe.
Paga-se 20 dollars por hora de utilização de treino... não é muito praticavel...
Um dos problemas que tinha era obter a nuvem de pontos recortada. Ao inicio recortei ambas as imagens RGB e depth e a partir das mesmas criava a nuvem de pontos. Por algum motivo não consegui criar a nuvem de pontos utilizando função por defeito da pcl. Decidi então utilizar a biblioteca open3D. Com esta biblioteca já consegui criar a nuvem de pontos mas a nuvem era diferente do resultado previsto, apesar de possuir as dimensões corretas do corte, a informação de profundidade está diferente da original. O problema estava no corte da imagem de profundidade que por algum motivo modificava a profundidade da imagem quando a única coisa que devia ter sido modificada era a dimensão da mesma. Restam duas alternativas, ou recorta-se a imagem de profundidade doutra maneira, visto que a atual não está correta ou então obtêm-se a nuvem de pontos inteira, da imagem original e depois recorta-se a mesma.
O problema estava na função do opencv de guardar a imagem depth, onde a imagem perdia muita informação... [COLOCAR DEPOIS NO RELATÓRIO IMAGEM DAS DUAS DIFERENÇAS PARA SE VER A PERCA DE INFORMAÇÃO DE PROFUNDIDADE QUE ESTAVA A ACONTECER - scrip "criapcd.py"]. Basta guardar com a biblioteca open3d e já guarda a imagem de profundidade com a informação original e recortada.
Não dá para guardar logo como imagem open3d recortada, temos de converter para numpy, recortar e depois converter de novo para open3d.
\bigskip
Sexta-feira - 04/10/2019
formatação do computador.
\bigskip
Segunda-feira - 07/10/2019
Criação do ambiente virtual python3.
instalar torch, encoding, pcl, cython, numpy... entre outras bibliotecas que já foram referidas anteriormente.
Quando se vai preparar o conjunto de dados no Encoding fazer,
"wget https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip
sudo unzip ninja-linux.zip -d /usr/local/bin/
sudo update-alternatives --install /usr/bin/ninja ninja /usr/local/bin/ninja 1 --force"
Está a aparecer-me um erro de cudaHOME não estar definida. É necessário instalar o cuda mas não as suas drivers.
instalar dependências da cuda:
sudo apt-get install freeglut3 freeglut3-dev libxi-dev libxmu-dev
instalação do visual studio code
instalação da cuda (continuação):
cuda-downloads toolkit 10.0
instalação ssh
instalação cuda 10.0 sem as drivers, visto que estas já estão instaladas.
O programa já funciona como funcionava antes da formatação, foi apenas necessário alterar alguns "path's".
falta passar para a pasta dataset, utilizando a etiquetagem
\bigskip
Terça-feira - 08/10/2019
Desenvolvi o script "build-dataset.py" que automaticamente recebe a diretoria com as imagens tiradas do raspberryPI, faz a rotação de -90º graus e coloca-as com os respetivos nomes e ordena-as.
Depois essas imagens são colocadas no conjunto de dados, utilizando o visualizador do opencv, vão aparecendo cada um das imagens e o utilizador faz a etiquetagem simplesmente pressionando a tecla correspondente à classe que a imagem têm. Tanto a imagem RGB como a imagem de profundidade são colocadas no conjunto de dados de acordo com a classe que lhes foi atribuída.
Desenvolvi outro script para gerar as nuvens de pontos no formato ".pcd" para cada par de imagens RGB + depth. É primeiro feita a segmentação semântica utilizando a biblioteca encoding do Pythorch. Esta segmentação é guardada na forma de uma imagem png numa subdiretoria "/semanticSeg", onde as únicas classes desta segmentação que são consideradas são porta, parede e chão. Este script ainda não foi desenhado para as classes das imagens com "escadas". São guardadas os crops das portas nas várias imagens tanto em RGB como em profundidade. Com estes cortes são construídas as nuvens de pontos utilizando a biblioteca open3d.
Existem vários problemas... um dos principais é a segmentação semântica nem sempre é feita corretamente. Claro que para imagens onde a porta está bem centrada e pouco desfocada a segmentação funciona muito bem, mas para casos em que só se vê parte da porta, ou por exemplo não se vê nem o chão nem o tecto, o algoritmo de segmentação semântica têm dificuldade em segmentar a porta. Quando na segmentação não é encontrada qualquer porta, não se consegue construir a nuvem de pontos, visto que os cortes RGB e de profundidade não são criados.
Foi feito o git clone do repositório da implementação da PointNet mais uma vez, https://github.com/fxia22/pointnet.pytorch. Agora com a base de dados mais ou menos 900 imagens já podem ser feitos alguns testes nestas implementações.
Quinta-feira - 10/10/2019
Apresentação rápida do meu projeto.
Um dos problemas é que nem todas a imagens RGB + depth que capturo são analisadas corretamente com o algoritmo da segmentação semântica e então não são usadas, pelo menos na PointNet.
Criar os ficheiros .json,
Primeiro vou definir os conjuntos treino, teste e validação. (80,10,10), para cada classe no meu conjunto de dados. Para já vou apenas utilizar as classes "open" com neste momento 685 imagens e "closed" com 127 imagens.
Ordenar os dados com a função "def rename\_points\_and\_pcd\_points(diretoria)"
Vou utilizar o repositório "split-folders", para separar em pastas test, treino e validação o meu conjunto de dados. Utilizei o método "fixed" para fixar exatamente o número de amostras para validação, treino e teste. Usei o método "oversample" para aumentar amostras na classe "open", visto que esta classe nesta altura possui muito menos amostras que a outra classe. O excesso de amostras foi colocado na diretoria de treino. É necessário colocar as amostras criadas em excesso pela biblioteca "split-folders" na pasta do conjunto de dados.
Depois disto, consegui fazer um script para então gerar os ficheiros .json, mas, os ficheiros tem ordem sequencial e não aleatória como tinham os ficheiros .json do conjunto de dados anterior.
\bigskip
Sexta-feira - 11/10/2019
Depois de ter conseguido transformar e construir um mini conjunto de dados com o mesmo modelo do conjunto de dados usado no repositório, "shapenet", a rede devolveu o erro: "len() of unsized object". O script do treino da rede corre mas a certa altura, antes de acabar a 1ª época, ocorre este erro. Acho que o problema é possuir dados que são muito pequenos... não têm qualquer tipo de informação... tenho de ver melhor isto, mas o melhor primeiro é construir um script que filtra estes dados.
O problema é que o conjunto de dados possuía algumas amostras com apenas 2bytes de tamanho, e eram essas amostras que causavam o erro anterior. Bastou as mesmas serem eliminadas e já foi possível correr a rede.
Alterei o número de classes que a base de dados shapenet tinha, para apenas 2 classes, Door-Open e Door-Closed.
Quando corro o script "show\_cls", que no fundo, faz uma classificação com o conjunto de dados de teste, a mesma é sempre aleatória. Isto acontece porque a rede usada para treino e para teste é a mesma e a mesma têm "dropout" que é uma propriedade aleatória, o que faz com que os resultados de teste sejam sempre diferentes mesmo utilizando os mesmos dados ordenados e o mesmo modelo.
\bigskip
Segunda-feira - 14/10/2019
Consegui correr a PointNet no meu conjunto de dados, mas o problema é que parece que a mesma não está a aprender nada e entra em sobre-ajuste aos dados do conjunto de treino. Existem outros problemas no conjunto de dados, nomeadamente quando é feita a segmentação semântica.
Já foi desenvolvido um programa para manualmente filtrar algumas imagens da base de dados.
É necessário alterar o programa para quando a maior área para a classe "porta" detectada for inferior a determinado tamanho. Quando esta condição acontece, a mesma imagem deve ser eliminada e não utilizada no conjunto de dados. Ainda há muito que posso melhorar no conjunto de dados sem ser aumentando o tamanho do mesmo.
Um dos problemas da implementação da PointNet na plataforma "Pythorch" é que simplesmente, a rede não estava a utilizar o conjunto de validação do conjunto de dados. O conjunto de teste estava a ser utilizado como o de validação durante o treino da rede.
Treinei a rede PointNet com o meu conjunto de dados, com 683 amostras de portas abertas e 683 amostras de portas fechadas.
1it [00:14, 14.37s/it]
final accuracy 0.6833333333333333, durante 7 épocas.
1it [00:17, 17.12s/it]
final accuracy 0.6724137931034483, durante 7 épocas.
[...]
Primeiro meter tudo numa pasta, todas as imagens, independentemente se as mesmas vão dar bons resultados de segmentação ou não.
-> transform-directory-Imagens
Tornar o semanticSeg-DataSet.py automático e que funcione sempre que se adicionam novas amostras ao conjunto de dados completo/original.
Depois criar outra pasta, DataSet-Slim e correr segmentação semântica e fica igual à anterior mas croped.
Depois utilizar data augmentation.
só depois disto tudo é que vou gerar os ficheiros pts.
\bigskip
Terça-feira 15/10/2019
No teste não posso usar data augmentation.
\bigskip
Quinta-feira 17/10/2019
Construí um conjunto de dados com o total de 10680 amostras. 10450 para treino, 220 para validação e 10 para teste. Inicialmente 495 amostras da classe closed e 59 da classe open. Foi feito uma sobreamostragem para aumentar o número de amostras na classe "open" de forma a que as duas classes tenham o mesmo número de amostras. De seguida as mesmas foram divididas em 3 conjuntos, treino, teste e validação. Para o conjunto de validação 10 amostras de cada classe, para o teste igual e para o treino 475 amostras para cada classe. Para o conjunto de treino e de validação fiz "data augmentation", onde fiz um flip tanto à imagem RGB como à informação depth, aumentando para o dobro o número de amostras de treino e validação. Também fiz 10 rotações diferentes, aumentando 11 vezes mais o número de amostras de treino e validação. ((475 * 2) * 11) = 10450; ((10 * 2) * 11) = 220.
Frustum PointNets: Notas:
O problema base é deteção de objetos 3D em espaços indoor e outdoor através de informação RGB e de profundidade. Lidam diretamente com as nuvens de pontos tal e qual a PointNet. Ao contrário da PointNet não utilizam só informação de profundidade mas também usam a informação 3D para a deteção do objeto na imagem RGB. A deteção de objetos 3D classificar a classe do objeto e faz uma estimativa da "bounding box 3D", ou seja, interessa-me neste trabalho visto que para fazer a deteção de um objeto num espaço 3D, é necessário primeiro classificá-lo corretamente. Tal como a PointeNet, esta abordagem usa diretamente as nuvens de pontos visto que outras representações dos dados poderiam obscurecer os padrões e as invariâncias 3D. Primeiro fazem um pré-processamento das nuvens de pontos fazendo com que os padrões 3D sejam mais evidentes. A rede utilizada divide-se em 3 partes, proposta frustum, segmentação de instâncias 3d e estimativa da caixa 3D. Na "proposta frustum" transformam a bounding box 2D num frustum no espaço 3D. Esse "frustum" é então normalizado para um determinado ângulo para o modelo ser invariante à rotação. O frustum é convertido para uma nuvem de pontos.
Sexta-feira - 18/10/2019
Depois de correr a implementação da PointNet no PyTorch durante 7 épocas, não obtive bons resultados visto que a precisão do conjunto de teste era igual a 0.55. Como só existem para já duas classes, porta aberta e porta fechada, pode-se dizer que os resultados foram bastantes negativos e fracos. Decidi ir explorar outras redes neuronais que usam informação de profundidade (nuvens de pontos) para classificação de objetos 3D.
Para começar, explorei uma implementação tensorflow da PointNet original. Para tal foi necessário instalar-se o Tensorflow:
-pip install --upgrade pip
-pip3 install tensorflow-gpu
import tensorflow já funciona.
Instalar a biblioteca h5py:
-sudo apt-get install libhdf5-dev
-pip3 install h5py
Para instalar corretamente o tensorflow, é necessário instalar o cuDNN.
https://developer.nvidia.com/rdp/cudnn-download
Instalar primeiro cuDNN Runtime Library for Ubuntu18.04 (Deb)
Instalar depois cuD
NN Developer Library for Ubuntu18.04 (Deb)
Instalar cuDNN Code Samples and User Guide for Ubuntu18.04 (Deb)
Verifiquei a instalação do cuDNN:
https://docs.nvidia.com/deeplearning/sdk/cudnn-install/index.html\#veriy
Foi necessário criar outro ambiente virtual para se utilizar o tensorflow: tf-human-vision
Foi instalado o "tensorboard", para acompanhar o treino da rede.
A implementação da PointNet usa a versão 1 do tensorflow.
Para a construção do dataset para este repositório é necessário converter os ficheiros pts para ply e coloca-los todos já em pastas /test e train/ e separados por pastas de diferentes classes. Neste caso o que depois posso fazer é juntar test com val.
segunda-feira 21/10/2019
\section{Ricardo work}
I started to read the final project report of Ricardo Domingos about artificial vision for blind people. His work was also to build a portable system that helps impaired visually people day by day, using semantic segmentation algorithms and computing vision.
Ricardo work is important in this project because it has the roots for the construction of the portable system and it has what type of vision computing algorithms it uses. The report has also all the difficulties that he went through and the main problems that visually impaired people have in indoor spaces.
As an initial goal, I try to replicate his work in the lab computer.
I implemented the semantic segmentation algorithm that Ricardo used in his work to detect the door in the input RGB image. The model used was the fully convolutional network "EncNet", with ResNet\_50 as the backbone network and pre-trained in the ADE dataset. I used the benchmark "Encoding", implemented in Py-Torch to do the semantic segmentation.
I worked with code that Ricardo provide me so I could see if the camera Realsense was working correctly and also if I was getting the same results as his.
In the final version of Ricardo work, the depth information was not being used, derived from the problems that Ricardo had with the point clouds. I changed the code that Ricardo built to save not just RGB images but also depth images from the Realsense camera.
\section{Portable system}
The next step is to build the portable system that visually impaired people will use in indoor spaces. I built a simple prototype system that includes a single-board computer, a portable battery, a 3D camera and a smartphone. The single-board computer is a Raspberry PI 3B+ with a 16Gb micro SD card. The 3D camera used in this project is an Intel Realsense Depth Camera D435.
\bigskip
For the camera to communicate with Raspberry PI I had to install in this last one, the Intel® RealSense™ SDK and other libraries that were needed to install the SDK. Before installing "RealSense" software on Raspberry PI, I installed it on the lab computer so that I could better test and explore the library. Still on the lab computer, I built a simple program that saves RGB image from the Camera plus the depth information.
\bigskip
I had a lot of difficulties installing pyrealsense(Cross-platform ctypes/Cython wrapper to the librealsense library) on raspberry PI. Unlike the lab computer I had to install this library manually, \url{-https://github.com/IntelRealSense/librealsense/blob/master/doc/RaspberryPi3.md}. This last URL is a website that is specific to install the librealsense in the Raspberry Pi, but it had some errors in it. After various researches, I found the following tutorial, \url{https://github.com/IntelRealSense/librealsense/blob/master/doc/installation_raspbian.md}.
\bigskip
One of the dependencies of the librealsense is the opencv library. The installation of this last library is also different in the Raspberry Pi, \url{https://www.pyimagesearch.com/2017/09/04/raspbian-stretch-install-opencv-3-python-on-your-raspberry-pi/}. Another dependency that was also installed differently than the lab computer was the protocol-buffer library. \url{https://osdevlab.blogspot.com/2016/03/how-to-install-google-protocol-buffers.html}.
\bigskip
If we want to use the librealsense it's necessary, in the Raspberry Pi system, to have the python executable program in the same directory where is located the realsense.so file so we can import it.
\bigskip
It's important to say that the Raspberry Pi 3 B+ is not going to be the final single-board computer to be used in the portable system. After installing all the libraries and its dependencies, the system stayed with only 2.5Gb free in the disk space. It's still necessary to install the neural network benchmarks and implementations via Tensorflow or Py-Torch. The system must have also some disk space available to store the RGB and depth information.
\bigskip
Passing the program that I built in the lab computer to the Raspberry Pi system I could already start building my dataset of RGB plus depth information. The smartphone was used in this system so the user could communicate with Raspberry PI while executing this program. The program has been modified once again, so the user can classify while storing the image. If the key "o" is pressed, the image RGB + depth will be stored in the "open" directory, meaning that the class of this image is "open". The following scheme show what options do the program has to store the images:
\begin{itemize}
\item "o" - store image of class "open"
\item "c" - store image of class "closed"
\item "u" - store image of class "stair up"
\item "d" - store image of class "stair down"
\end{itemize}
\section{Virtual environment}
I created a virtual environment so I could be sure that I was not creating conflicts with all the packages and libraries installed in the system. It was created one virtual environment for the machine learning platform TensorFlow and one virtual environment for the PyTorch platform.
\section{Semantic Segmentation PyTorch-Encoding}
I started to explore some algorithms of semantic segmentation. I started to explore the benchmark that Ricardo used in his project, the PyTorch-Encoding. I started to install manually this benchmark and all its dependencies in the lab computer.
The version of torch that it was required, was the version 1.0.0 and only that version worked. I follow the following tutorial, \url{https://hangzhang.org/PyTorch-Encoding/experiments/segmentation.htm}. I ran the script to build the dataset ADE20K which was the same dataset that Ricardo used for the pre-trained model in semantic segmentation. As I told before, I used the network "EncNet", with the backbone "ResNet" and with the weights pre-trained on the ADE20K dataset. I tested the demo.py script and everything was running fine, without any problems or errors.
\section{Implementation and testing of Ricardo's work}
Although in Ricardo's work he does not use depth information to classify objects, some previous programming was made that uses RGB plus depth. Using first the RGB image, he would use semantic segmentation to identify 3 different classes from ADE20K dataset, "door", "wall" and "floor". For each class the biggest area was calculated and store the bounding box of that area. After finding this bounding box, the next step was to crop the RGB image and the Depth image according the bounding box. He would then create 3 different point clouds for each class (door, wall, floor) and see the angle between those point clouds to classify if the door was open or if the door was closed. If the angle between the door and the wall was 0, than it would mean that the door was close and if the angle was bigger than 0, it would mean that the door was open.
\bigskip
One problem with this method is that some point clouds had swings that would interfere with the calculations of the angles, but the biggest problem is that there are cases where the wall detected in the semantic segmentation algorithm it's not the wall that has the door. We can think in a wall corner, where the door does an angle of 90 degrees with the wall but is closed, but if we follow the previous method it would mean that the door was open which is not true.
I implement what was implement in Ricardo's work, namely, the use of semantic segmentation to calculate the biggest area of each class. In my case, the interest classes were "door" and "stair". I would also use the bounding box resulting of the calculation of the biggest area to crop the RGB and Depth image. After that I would create the cropped point cloud, using the pcl toolkit, "png2pcl" for each class.
\bigskip
The next step is to study neural networks for object classification that use depth plus RGB information.
\section{Mini-DataSet}
I started creating a small/prototype dataset using the prototype portable system with the raspberry PI 3B+ so I can start exploring neural networks for 3D object classification and see their behaviour. I went to several places to take photos of doors in indoor spaces. If the door is open and one human can fit in that door if he walks in a straight line, that means that the door is open, otherwise the door is closed. The main objective in the "door problem" is not to see if the door is really open or closed, but to see if the visually impaired people can pass through it or not. For us, not visually impaired people, the door may be open but for the visually impaired the door is closed.
I store not only the tradition RGB image but as well its depth component. Every photo taken has one RGB image and one depth image.
\section{PointNet}
The first neural network for 3D object classification that I started exploring was the PointNet. The goal is to use a method that uses both RGB plus depth information to classify if the door is open or closed if the stair is up or down and other problems that visually impaired people have. I studied the PointNet because it is a foundation network that uses depth information as input and many networks derive from it. The original PointNet doesn't use RGB information to object classification and other computing vision tasks. It uses only depth information, namely, array that represents the coordinates of all points in one point cloud with no RGB.
The PointNet was one of the first neural networks that used point clouds as input. They can be used to object classification, semantic segmentation, part object segmentation and others. The main advantage of this network is that they don't need any type of voxelization of the input point cloud. This will decrease the time of training the train set because the data is not so bulky as it would be if the point cloud was converted to a 3D voxel grid.
To implement and explore the PointNet I used the following repository, \url{ https://github.com/fxia22/pointnet.pytorch}, that is an implementation of PointNet in PyTorch. I tested with the same dataset that they used in the paper, the shapenet dataset and everything was working correctly except for the Test and Val set. They were using the Test set during the training of the network when they should be using the Val set. I change this mistake simply using the val set in during the training and only using the test set in the final of the training.
With the prototype dataset that I built early, I could now use it in this network to test both the network and the dataset. I needed to convert the depth image to a numpy array with the file format .pts that represent the coordinates of the points in the point cloud. These files needed to be placed in different folders dependently on their class (open or closed).
It was also necessary to create the .seg files although the same didn't needed to be used in the object classification task and only in the part object segmentation task. These .seg files represented the sub parts of an object. They aren't needed to do the object classification but in this implementation of PointNet they are required anyway. The objects in the database weren't divided into subparts so I simply stipulated that there was only, for each object, one subpart of the same.
\section{Dataset for PointNet}
After getting an acceptable quantity of samples I started to build the dataset in the same format of the shapenet dataset. I was doing this because it was necessary if I wanted to use my dataset in the implementation of PointNet in PyTorch. The following list is the structure of the dataset directory without any filtering and data augmentation.
\bigskip
/DataSet
\begin{itemize}
\item open
\begin{itemize}
\item color (157 samples)
\item depth (157 samples)
\end{itemize}
\item closed
\begin{itemize}
\item color (731 samples)
\item depth (731 samples)
\end{itemize}
\end{itemize}
The next step was to do the semantic segmentation to the object "door" in the RGB images. The advantages is that I will reduce the size of my samples that I will send to the network PointNet. I only need to show the area around the door and not all the area that the camera 3D Realsense captured. I used the benchmark Encoding in PyTorch, the same that Ricardo used in his work. I use the Encnet with the network backbone Resnet101 pre-trained in the ADE20K dataset. For each RGB image I generated a semantic segmentation image where I was only looking at the door class. The result of the semantic segmentation was stored in the "DataSeg" directory with the following structure:
\bigskip
/DataSeg
\begin{itemize}
\item open (157 samples)
\item closed (731 samples)
\end{itemize}
Using the semantic segmentation images, I built the "DataSet-Slim". This dataset is equal to the original DataSet, but the RGB and depth images are cropped according to the result of the semantic segmentation. The semantic segmentation doesn't work for all the samples, and some images were cropped wrong or weren't cropped at all. To solve this problem I built a simple script to filter the images in the DataSet-Slim, for example, if in the region cropped the door isn't visible, that image will not be used in the dataset. This script requires a real user to filter out. It was built because it makes the process of filtering more efficiently and we don't have the problem of eliminating the wrong RGB image or it's depth component. I built another script that for himself, without the need of a real user, filters the images that are generated. If the crop of the image is too small, for other words, the semantic segmentation didn't almost detect any door object in the image, the sample isn't used and its eliminated.
After all the filtering, the structure of the DataSet-Slim was the following:
\bigskip
DataSet-Slim/
\begin{itemize}
\item open
\begin{itemize}
\item color (59 samples)
\item depth (59 samples)
\end{itemize}
\item closed
\begin{itemize}
\item color (495 samples)
\item depth (495 samples)
\end{itemize}
\end{itemize}
It was necessary to separate each class set in train, test and val sets. To do that I used the library "split\_folders" that already does that division of the data and also if some class has much more samples than another it can do oversample. That was my case because after all the filtering I had almost 10 times more samples of class closed than class open. For each class I used 10 samples for testing, 10 samples for validation and the rest for training. only the training set data has suffered oversampling. I created 2 directories related to each other, "DataIMGS3" and "DataDepth3". The first one is the division of train, test and val of the RGB images of the dataset, with the following structure:
\begin{itemize}
\item test
\begin{itemize}
\item closed (10 samples)
\item open (10 samples)
\end{itemize}
\item train
\begin{itemize}
\item closed (475 samples)
\item open (475 samples)
\end{itemize}
\item val
\begin{itemize}
\item closed (10 samples)
\item open (10 samples)
\end{itemize}
\end{itemize}
The second has the same structure but instead of having the RGB images it has its depth component.
\bigskip
\subsection{Data augmentation}
I did data augmentation after I generated the dataset with this 3 partitions, train, test and val. The test dataset didn't suffer data augmentation because we want to use real images and cases that are different to see if the model or network is generating correctly.
At this moment, I used 2 data augmentation techniques. First I used Horizontal flip, that will increase by 2 the size of the val set (10 * 2 = 20) and the train set. (475 * 2 = 950). After flipping the images I used angle rotation between -25 and 25 degrees every 5 (-25, -20, -15, -10, -5, 0, 5, 10, 15, 20, 25). This increased by 11 the size of the val set (20 * 11 = 220) and the size of the train set(950 * 11 =10450).
\bigskip
After getting a bigger dataset thanks to the data augmentation I could now convert the .png image RGB plus the .png image depth to point cloud data using the PCL tool, "png2pcd". After getting all the .pcd files, I converted these files to .pts files, which was the format required to use the implementation of the PointNet. The .seg files aforementioned, were also created although they are not needed in the object classification task.
The only thing missing was the .json files that contains the information about the set (train, test, val) that each sample belongs to. The final structure of the dataset I built for PointNet was the following:
\bigskip
Dataset-PointNet
\begin{itemize}
\item closed
\begin{itemize}
\item points (10680 samples)
\item points\_label (10680 samples)
\end{itemize}
\item open
\begin{itemize}
\item points (10680 samples)
\item points\_label (10680 samples)
\end{itemize}
\item train\_test\_split
\begin{itemize}
\item shuffled\_test\_file\_list.json
\item shuffled\_train\_file\_list.json
\item shuffled\_val\_file\_list.json
\end{itemize}
\end{itemize}
10680 samples because it aggregates all the 3 sets, train, test and val (10450 + 220 + 10 = 10680).
\section{Results of the implementation of PointNet}
After building my own set with only images and depth information of closed and open doors I started testing the PointNet. I run the script for training the network to distinguish between "open-door" and "closed-door" with the following parameters:
\begin{itemize}
\item batch size = 20
\item number of epoch = 7
\item number of points = 2500
\item learning rate = 0.001
\end{itemize}
After training the model, I tested it with the evaluation script and the accuracy was only 0.55, which means the network nearly learned anything about distinguish the 2 classes. The value 0.55 means that the network classified well 11 samples in 20 samples.
\bigskip
I research a little more the implementation of PointNet and how the training is done and I find that the problem was in the number of points used to training and testing. The parameter, number of points define the number of points that will be random choose in each sample to train the model. The default value for this parameter is 2500 which in the case of the "shapenet" makes sense because the point clouds samples have in average 2000 points. In the dataset that I built, the point clouds samples have in average 100000 points and the standard deviation can go between 500 points to 300000 points. Taking into account the previous, I train the model with the number of points parameter equal to 10000. The ideal case would be to use 100000 points or even 300000 points, but the memory capacity of the GPU couldn't take it so I used 10000 points.
This time, the parameter for training were:
\begin{itemize}
\item batch size = 20
\item number of epoch = 5
\item number of points = 10000
\item learning rate = 0.001
\end{itemize}
I saved the weights of the network (model) in every epoch so I can evaluate each model and see if the network learnt anything epoch by epoch. In the evaluation I used the same batch size and the same number of points. I only evaluate the models after the training. The following table shows the results that I get for evaluating each model. I evaluated five times each model and them I calculated the mean and standard deviation for both the loss and the accuracy value.
\bigskip
\begin{table}[h]
\centering
\begin{tabular}{|c|c|c|}
\hline
\textbf{Evaluation} & \textbf{Mean accuracy} & \textbf{Mean loss} \\ \hline
model after 1 epoch & 0.69±0.02 & 0.6945±0.007 \\ \hline
model after 2 epoch & 0.75±0 & 0.6161±0.006 \\ \hline
model after 3 epoch & 0.72±0.02 & 0.6398±0.007 \\ \hline
model after 4 epoch & 0.79±0.02 & \textbf{0.5728$\pm$0.007} \\ \hline
model after 5 epoch & \textbf{0.80±0} & 0.5884$\pm$0.012 \\ \hline
\end{tabular}
\caption{Evaluation results on 5 models from Pointnet trained in my own PointNet dataset}
\label{tab:table_results}
\end{table}
\section{Problems with the semantic segmentation}
There are several samples that are being wasted because of the semantic segmentation. The problem is with the cases when the door is open, the semantic segmentation can't detect very well the door jamb. The ideal was the semantic segmentation algorithm to detect the door jamb and not the door. There are cases when the door is wide open, 180 degrees, and the segmentation result is not the door jamb but the door itself which is open of course but with that context it looks like its closed and it will induce errors to the network.
Quinta-feira - 24/10/2019
Não consigo treinar no encoding... vou desistir deste e passar para a PSPNet. GPU not memory.
\section{FAZER:}
ler artigos científicos.
Tratar primeiro de filtrar conjunto de dados.
meter opção para escadas para subir e para descer. [v]
testar jetson nano - nvidia com sdcard.
Fazer data aug - pythorch, no sentido em alterar a cor das portas e das imagens
\bigskip
Melhorar segmentação semântica, por exemplo em vez de usar a maior área, posso juntar todas as áreas relativamente grandes, por exemplo mais do que 80 pixeis juntos, e considero os extremos como a bounding box. Acho que assim consigo detetar melhor os aros da porta
\bigskip
[PRIORIDADE]
Aumentar base de dados, com
DATA AUG flip vertical x10
DATA AUG rot 30º x10
DATA AUG color random x10
\section{LER:}
https://arxiv.org/pdf/1612.00593v2.pdf
https://arxiv.org/pdf/1711.08488v2.pdf
https://arxiv.org/pdf/1801.07791v5.pdf
https://arxiv.org/pdf/1909.12663v1.pdf
https://nbviewer.jupyter.org/github/yihui-he/Depth-estimation-with-neural-network/blob/master/latex/egpaper\_final.pdf
https://arxiv.org/pdf/1803.07289v3.pdf
\section{FUTURO:}
Fazer um pré-processamento da imagem que sai da rede, para saber se realmente a porta está correta ou não. Por exemplo se a porta não estiver em "contacto" com o chão, quer dizer que a mesma não está correta... A rede têm de saber isso.
Posso mudar a loss (normalmente é o cross entropy) center loss (class), forçar a rede a aprender certos padrões. diferentes loss diferentes resultados.
A ideia original, é enviar para a rede uma imagem com 4 canais, R+G+B+Depth, mas podemos enviar por exemplo 7 canais, estes 4 mais 3 da segmentação semântica por exemplo.
Utilizar as 2 pen's coral e nvidia no jetson e correr 3 redes ao mesmo tempo para se ter maior desempenho e utilização de recursos.
Ao fim de Dezembro ter uma rede "BETA" já a funcionar para o invisual puder testar e obter-mos feedback do mesmo para sabermos que aspetos estão bem e que aspetos estão ainda por melhorar.
\section{COMANDOS ÚTEIS:}
watch -n1 nvidia-smi -> meter um alias nvidia-smi.
Crtl+B -> shift+\% e Crtl+B -> shift+" ----------> tmux
ssh @socialab10.04.155, para sair basta fazer "exit".
nautilus é o file explorer, se for com sudo, tenho acesso a tudo.
updatedb -> para atualizar a base de dados, utilizar sempre que se quer fazer um locate do que ficou instalado.
\section{Train}
Train loss: 1.274: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:13<00:00, 1.41it/s]
pixAcc: 0.773, mIoU: 0.530: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.95it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 1, learning rate = 0.0037, previous best = 0.6516
Train loss: 0.827: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:15<00:00, 1.39it/s]
pixAcc: 0.699, mIoU: 0.350: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.89it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 2, learning rate = 0.0036, previous best = 0.6516
Train loss: 0.623: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:19<00:00, 1.35it/s]
pixAcc: 0.789, mIoU: 0.536: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.92it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 3, learning rate = 0.0035, previous best = 0.6624
Train loss: 0.580: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:13<00:00, 1.40it/s]
pixAcc: 0.782, mIoU: 0.529: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.84it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 4, learning rate = 0.0035, previous best = 0.6624
Train loss: 0.589: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.854, mIoU: 0.680: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.91it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 5, learning rate = 0.0034, previous best = 0.7670
Train loss: 0.553: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.880, mIoU: 0.730: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.90it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 6, learning rate = 0.0033, previous best = 0.8049
Train loss: 0.429: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.901, mIoU: 0.785: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.92it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 7, learning rate = 0.0033, previous best = 0.8430
Train loss: 0.406: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.830, mIoU: 0.625: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.93it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 8, learning rate = 0.0032, previous best = 0.8430
Train loss: 0.460: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.895, mIoU: 0.776: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.96it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 9, learning rate = 0.0031, previous best = 0.8430
Train loss: 0.409: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:10<00:00, 1.44it/s]
pixAcc: 0.917, mIoU: 0.817: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.94it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 10, learning rate = 0.0031, previous best = 0.8671
Train loss: 0.343: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.910, mIoU: 0.808: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.95it/s]
0%| | 0/188 [00:00<?, ?it/s]
=>Epoches 11, learning rate = 0.0030, previous best = 0.8671
Train loss: 0.392: 100%|████████████████████████████████████████████████████████████████████████| 188/188 [02:11<00:00, 1.43it/s]
pixAcc: 0.937, mIoU: 0.861: 100%|█████████████████████████████████████████████████████████████████| 22/22 [00:05<00:00, 3.93it/s]