diff --git a/enonce-resume/ITI_LOG_resume_diplome_Fanetti_2020.pdf b/enonce-resume/ITI_LOG_resume_diplome_Fanetti_2020.pdf new file mode 100644 index 0000000000000000000000000000000000000000..46a2418b35b5135c896e0efed1f761794a656940 Binary files /dev/null and b/enonce-resume/ITI_LOG_resume_diplome_Fanetti_2020.pdf differ diff --git a/enonce-resume/ITI_LOG_resume_diplome_Fanetti_2020.tex b/enonce-resume/ITI_LOG_resume_diplome_Fanetti_2020.tex new file mode 100644 index 0000000000000000000000000000000000000000..75d8d06dd8fc53746a702df989aad94206e1b135 --- /dev/null +++ b/enonce-resume/ITI_LOG_resume_diplome_Fanetti_2020.tex @@ -0,0 +1,60 @@ +% !TeX spellcheck = fr_FR +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% % +%% HEPIA BACHELOR ABSTRACT LATEX TEMPLATE % +%% version 0.10 - 2020/04/25 % % +%% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% To fill up by the student +\newcommand{\Session}{Printemps 2020} +\newcommand{\Author}{Simon FANETTI} +\newcommand{\Professor}{Paul ALBUQUERQUE et Adrien LESCOURT} +\newcommand{\Client}{Aucun} +\newcommand{\Convention}{non} +\newcommand{\Confidentiel}{non} + +\input{config/conf} +%\usepackage{showframe} % Prints document frame + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DOCUMENT STARTS BELOW %%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{document} +\chapter*{Résumé} +%% HEADER IMAGES +\tikz[remember picture,overlay] \node[shift={(4.655cm,-1.95cm)}] at (current page.north west) +{\includegraphics[width=5.86cm,height=3.31cm]{template/images/title/hepia_logo}}; +\begin{spacing}{0.956} +\vspace{0.5cm} + +%% CONTENT STARTS HERE +La création de maquettes physiques de terrains par les architectes paysagistes est un processus nécessaire lors de la réalisation de projet d’aménagement de territoire. Cependant, ces maquettes basées sur des matériaux comme le carton ou le bois, ne leur permettent pas de les modifier en cas de changements dans leur projets. C’est pourquoi nous proposons de substituer leurs maquettes par la technologie du bac à sable, qui leur permettra de vivre une expérience de réalité augmentée. Grâce aux projections d'images sur le bac, tenant compte de la topologie de celui-ci, les architectes paysagistes pourront modeler leur terrains dans le sable et avoir un rendu direct des aménagements, laissant place aux changements à tout instant. Toutefois, la création d’applications permettant ceci est pour le moment irréalisable, car aucune interface ne permet d’utiliser cette infrastructure. Après avoir reproduit l’infrastructure nécessaire au projet, constituée d’un bac à sable, d’une caméra de profondeur Intel RealSense, d’un beamer et d’un PC sous distribution Linux, nous avons commencé à développer notre interface C++ permettant son utilisation. Afin de permettre une flexibilité lors de l’installation de l’infrastructure, nous avons développé une API de calibration permettant l’obtention des paramètres nécessaires à la compensation de l’infrastructure permettant une expérience de réalité augmentée cohérente. De plus, une application de calibration basée sur cette API, permet à l’utilisateur de suivre la procédure de manière guidée et adaptée à différents environnements. Elle permet notamment de générer la configuration regroupant nos différents paramètres liés à l’infrastructure et est utilisée par notre API d’utilisation, qui a été développée par la suite. Cette API couplée à la configuration générée, permet l’utilisation du bac et finalement l’interface nécessaire aux développeurs permettant la création d’applications en réalité augmentée. C’est pourquoi finalement, nous avons développé une application affichant les niveaux du bac en couleurs. + + +\vfill +\begin{center} + {\includegraphics[scale=0.32]{template/images/abstract/image}}\\* +\vfill +%% CONTENT ENDS HERE + + + +{ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%% DO NOT MODIFY THE TABLE BELOW %%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + \begin{tabular*}{16cm}{p{7.59cm} p{7.58cm}} + \small Candidat-e: & \small Professeur-e(s) responsable(s):\\*[10pt] + \small\textbf{\textsc{\Author}} & \small\textbf{\textsc{\Professor}}\\*[10pt] + \footnotesize Filière d’études : ITI & \footnotesize \textbf{En collaboration avec:} -\\*[10pt] + \footnotesize {} & \footnotesize Travail de bachelor soumis à une convention de stage en entreprise: \Convention\\*[20pt] + \footnotesize {} & \footnotesize Travail soumis à un contrat de confidentialité: \Confidentiel\\*[10pt] + \end{tabular*}\\*[1.9cm] +} + + +\end{center} +\end{spacing} +\end{document} diff --git a/enonce-resume/config/conf.tex b/enonce-resume/config/conf.tex new file mode 100644 index 0000000000000000000000000000000000000000..506d79fe31327ccf957b062bb3698bca64642c3d --- /dev/null +++ b/enonce-resume/config/conf.tex @@ -0,0 +1,59 @@ +\documentclass[12pt] + {report} % Set document to report class +\usepackage[T1] + {fontenc} % Font enconding +\usepackage[utf8] + {inputenc} % Set input encoding to utf-8, thus allow for non-ASCII characters +\usepackage[french] + {babel} % set document to default language to french +\usepackage[cm] + {fullpage} % Set margins to full page +\usepackage[a4paper,includehead,headheight=24pt,left=2.5cm, right=2.5cm, bottom=2.5cm, top=1.26cm] + {geometry} % Configure document geometry + +\usepackage{tikz} % Image and drawing related package +\usepackage{helvet} % Helvetica font ~ Arial +\usepackage{mathptmx} % Times font ~ Times New Roman + + +\usepackage[sfmath,notextcomp]{kpfonts} % Calibri replacement, font is \sf + +\usepackage[scaled=0.85] + {beramono} % Vera mononspace {fvm} +\usepackage {berasans} % Vera sans {fvs} + +%% This defines the default sans serif, roman and monospace fonts +\renewcommand{\sfdefault} + {phv} % helvetica as sans serif font +\renewcommand{\rmdefault} + {ptm} % times as roman (serif) font +\renewcommand{\ttdefault} + {fvm} % Vera mononspace as monospace font +\usepackage{bold-extra} % Allow custom typsettings horrors like bold Small Caps +\usepackage{slantsc} % Allow custom typsettings horrors like slanted Small Caps +\usepackage{numprint} % number notation related package, e.g 10'000'000 +\usepackage{setspace} % linespacing related package + + +\usepackage{lipsum} % Lorem Ipsum generator +%\usepackage{showframe} % Print document frame + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CUSTOM HEADER %%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\usepackage{fancyhdr} +\pagestyle{fancy} +\renewcommand{\headrulewidth}{0pt} +\fancyhf{} +\fancypagestyle{plain}{ + \fancyhf{}% + \fancyhead[L,C]{} + \fancyhead[R]{\fontsize{11pt}{12.4pt} \sf \textbf{\\*\Session\\*[1.2pt]Session de bachelor}} + \fancyfoot[L,C,R]{} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} +} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CUSTOM CHAPTER TITLES %%%%%%%%%%%%%%%%%%%%%%%%% +\usepackage{titlesec} +\titleformat{\chapter}[hang]{\centering \bfseries\scshape\Large}{\thechapter.}{1pc}{} +\titleformat{name=\chapter,numberless}[hang]{\fontsize{15.5}{18.7}\centering\bfseries\scshape}{}{1pc}{} +\titlespacing{\chapter}{0pt}{3em}{-12pt} \ No newline at end of file diff --git a/enonce-resume/template/images/abstract/image.png b/enonce-resume/template/images/abstract/image.png new file mode 100644 index 0000000000000000000000000000000000000000..5eabe050c6ed46faf004e471db7122bd44eff8b8 Binary files /dev/null and b/enonce-resume/template/images/abstract/image.png differ diff --git a/enonce-resume/template/images/title/hepia_logo.jpg b/enonce-resume/template/images/title/hepia_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4cc3147652641f1b5e3171cedbd0d4e412651883 Binary files /dev/null and b/enonce-resume/template/images/title/hepia_logo.jpg differ diff --git a/enonce-resume/template/images/title/hes-so_geneve_logo.emf b/enonce-resume/template/images/title/hes-so_geneve_logo.emf new file mode 100644 index 0000000000000000000000000000000000000000..16c24b590748ed1a212df1aadbc92f2eeaa320a5 Binary files /dev/null and b/enonce-resume/template/images/title/hes-so_geneve_logo.emf differ diff --git a/enonce-resume/template/images/title/hes-so_geneve_logo.png b/enonce-resume/template/images/title/hes-so_geneve_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..90403e3e4c5829acf0a7e75507c64ef8fce032b1 Binary files /dev/null and b/enonce-resume/template/images/title/hes-so_geneve_logo.png differ diff --git a/enonce-resume/template/images/title/hes-so_geneve_logo.svg b/enonce-resume/template/images/title/hes-so_geneve_logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..b9f547e9f625665fcb01e3ecd7f872af510dbe05 --- /dev/null +++ b/enonce-resume/template/images/title/hes-so_geneve_logo.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg width="80mm" height="23mm" viewBox="0 0 8000 2300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-width="28.222" stroke-linejoin="round" xml:space="preserve"> + <image x="0" y="0" width="8000" height="2290" preserveAspectRatio="none" xlink:href="data:image/png;base64,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"/> +</svg> \ No newline at end of file diff --git a/enonce-resume/template/images/title/image.png b/enonce-resume/template/images/title/image.png new file mode 100644 index 0000000000000000000000000000000000000000..0f96ed2e92f6dae5d7cfbdd718714655a7367a7b Binary files /dev/null and b/enonce-resume/template/images/title/image.png differ diff --git a/memoire/ITI_LOG_memoire_diplome_Fanetti_2020.pdf b/memoire/ITI_LOG_memoire_diplome_Fanetti_2020.pdf new file mode 100644 index 0000000000000000000000000000000000000000..7bf47e014a277fdd170f5d17cb683cf3a7c5e797 Binary files /dev/null and b/memoire/ITI_LOG_memoire_diplome_Fanetti_2020.pdf differ diff --git a/memoire/memoire_fanetti_simon.tex b/memoire/ITI_LOG_memoire_diplome_Fanetti_2020.tex similarity index 95% rename from memoire/memoire_fanetti_simon.tex rename to memoire/ITI_LOG_memoire_diplome_Fanetti_2020.tex index be39e46fc8ebbd39db05e43065ff660d44473b39..753e9d174d9945a981bd4e2a55e3cc5d554724b0 100644 --- a/memoire/memoire_fanetti_simon.tex +++ b/memoire/ITI_LOG_memoire_diplome_Fanetti_2020.tex @@ -12,6 +12,9 @@ ]{report} %% should use memoir documentclass \input{config/thesis} +\usepackage[style=iso-authoryear]{biblatex} +\addbibresource{biblio/sandbox.bib} + %% To fill up by the student \newcommand{\Author}{Simon FANETTI} \newcommand{\TitleImage}{template/images/title/title} @@ -52,19 +55,14 @@ \end{spacing} %\clearpage \cleardoublepage -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEDICATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% TABLE OF CONTENT %%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{spacing}{1} \input{chapters/globaltoc} \end{spacing} %\clearpage \cleardoublepage -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% DEDICATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{spacing}{1.5} -\input{chapters/dedication} -%\clearpage -\cleardoublepage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ACKNOWLEDGEMENTS %%%%%%%%%%%%%%%%%%%%%%%%%%% +\begin{spacing}{1.5} \input{chapters/acknowledgements} %\clearpage \cleardoublepage @@ -106,8 +104,8 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CHAPTERS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Add your chapters here %%%%%%%%%%%%%%%%%%%%%%%%% %\input{chapters/chapXXX} -\input{chapters/content/dispositif} \input{chapters/content/existant} +\input{chapters/content/dispositif} \input{chapters/content/besoins} \input{chapters/content/architecture} \input{chapters/content/technologies} diff --git a/memoire/biblio/sandbox.bib b/memoire/biblio/sandbox.bib new file mode 100644 index 0000000000000000000000000000000000000000..a7ac7851c0c4892996613edc2c07946677ab6f07 --- /dev/null +++ b/memoire/biblio/sandbox.bib @@ -0,0 +1,459 @@ + +@online{uc_davis_augmented_2016, + title = {Augmented Reality Sandbox}, + url = {https://arsandbox.ucdavis.edu/}, + titleaddon = {{UC} Davis Augmented Reality Sandbox}, + author = {{UC Davis}}, + urldate = {2020-08-13}, + date = {2016}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/NR24WM4S/arsandbox.ucdavis.edu.html:text/html} +} + +@online{universal_terminal_systems_llc_augmented_nodate, + title = {Augmented reality sandbox {\textbar} Award-winning, certified {\textbar} Ships internationally}, + url = {http://ar-sandbox.com/}, + abstract = {3D interactive sandbox for education, entertainment, therapy. 25 interactive modes: topography, contour lines, rivers, volcanoes. You can use your hardware.}, + titleaddon = {ar-sandbox.com}, + author = {{Universal Terminal Systems (LLC)}}, + urldate = {2020-08-13}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/7SRREIEW/ar-sandbox.com.html:text/html} +} + +@online{uc_davis_augmented_2016-1, + title = {Augmented Reality Sandbox}, + url = {https://arsandbox.ucdavis.edu/}, + titleaddon = {{UC} Davis Augmented Reality Sandbox}, + author = {{UC Davis}}, + urldate = {2020-08-13}, + date = {2016}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/Q3FQAE52/arsandbox.ucdavis.edu.html:text/html} +} + +@online{michele_brusasca_jean_2012, + title = {Jean Nouvel Design}, + url = {https://www.figurasfondo.fr/maquette-darchitecture-en-carton-gris/}, + titleaddon = {Atelier Figura/Sfondo}, + author = {{Michele Brusasca}}, + urldate = {2020-08-13}, + date = {2012-03-26}, + langid = {french}, + note = {Section: Maquettes d'architecture}, + file = {Snapshot:/home/simon/Zotero/storage/BBXV7F25/maquette-darchitecture-en-carton-gris.html:text/html} +} + +@online{uc_davis_hardware_2016, + title = {Hardware – Augmented Reality Sandbox}, + url = {https://arsandbox.ucdavis.edu/instructions/hardware-2/}, + titleaddon = {{UC} Davis Augmented Reality Sandbox}, + author = {{UC} Davis}, + urldate = {2020-08-13}, + date = {2016}, + langid = {american} +} + +@inreference{noauthor_kinect_2020, + title = {Kinect}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://fr.wikipedia.org/w/index.php?title=Kinect&oldid=173049699}, + abstract = {Kinect, initialement connu sous le nom de code Project Natal, est un périphérique destiné au matériel Microsoft avec la Xbox 360 pour la V1 et la Xbox One et Windows depuis la V2 permettant de contrôler une interface sans utiliser de manette. Il a été conçu par Microsoft en septembre 2008. +Le mot-valise « Kinect » est issu des mots anglais « kinetic » (qu'on peut traduire par « cinétique ») et « connect » (qu'on peut traduire par « connecter »),. La sortie européenne a eu lieu le 10 novembre 2010. +Le 5 janvier 2011, deux mois après sa sortie, Microsoft annonce avoir vendu 8 millions de Kinect, dont un million en seulement 10 jours. Le 11 mars 2011, Kinect entre au Livre Guinness des records comme étant « l'accessoire high-tech le plus vendu dans un court laps de temps » avec 10 millions d'unités vendues, soit une moyenne de 130 000 Kinect vendus chaque jour à travers le monde. +Les ventes se sont ensuite érodées, jusqu'à ce que Microsoft décide de ne pas intégrer de port Kinect dans la Xbox One S sortie en août 2016. Finalement, en octobre 2017, le fabricant annonce l'arrêt du développement et de la production de Kinect.}, + booktitle = {Wikipédia}, + urldate = {2020-08-13}, + date = {2020-07-19}, + langid = {french}, + note = {Page Version {ID}: 173049699}, + file = {Snapshot:/home/simon/Zotero/storage/3RYIIRNI/index.html:text/html} +} + +@online{microsoft_buy_2020, + title = {Buy the Azure Kinect developer kit – Microsoft}, + url = {https://www.microsoft.com/en-us/p/azure-kinect-dk/8pp5vxmd9nhq}, + abstract = {Azure Kinect {DK} is a developer kit that contains a best-in-class 1MP depth camera, 360˚ microphone array, 12MP {RGB} camera, and orientation sensor for building advanced computer vision and speech models.}, + titleaddon = {Microsoft Store}, + author = {{Microsoft}}, + urldate = {2020-08-13}, + date = {2020}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/G3Y2UI3U/8pp5vxmd9nhq.html:text/html} +} + +@online{universal_terminal_systems_llc_augmented_nodate-1, + title = {Augmented reality sandbox {\textbar} Award-winning, certified {\textbar} Ships internationally}, + url = {http://ar-sandbox.com/}, + abstract = {3D interactive sandbox for education, entertainment, therapy. 25 interactive modes: topography, contour lines, rivers, volcanoes. You can use your hardware.}, + titleaddon = {ar-sandbox.com}, + author = {{Universal Terminal Systems (LLC)}}, + urldate = {2020-08-13}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/NK3CBHQK/ar-sandbox.com.html:text/html} +} + +@online{opencv_dev_team_mat_2019, + title = {Mat - The Basic Image Container — {OpenCV} 2.4.13.7 documentation}, + url = {https://docs.opencv.org/2.4/doc/tutorials/core/mat_the_basic_image_container/mat_the_basic_image_container.html}, + titleaddon = {{OpenCV}}, + author = {{opencv dev team}}, + urldate = {2020-08-13}, + date = {2019-12-31}, + file = {Mat - The Basic Image Container — OpenCV 2.4.13.7 documentation:/home/simon/Zotero/storage/257UG8J5/mat_the_basic_image_container.html:text/html} +} + +@online{opencv_dev_team_opencv_nodate, + title = {{OpenCV}: cv::Mat Class Reference}, + url = {https://docs.opencv.org/3.4/d3/d63/classcv_1_1Mat.html}, + titleaddon = {{OpenCV}}, + author = {{opencv dev team}}, + urldate = {2020-08-13}, + file = {OpenCV\: cv\:\:Mat Class Reference:/home/simon/Zotero/storage/9WQY9RP6/classcv_1_1Mat.html:text/html} +} + +@online{intel_realsense_get_2020, + title = {Get started}, + url = {https://dev.intelrealsense.com/docs}, + abstract = {Choose the section: {InstallationFirmware} {updateCode} {samplesWrappersWhitepapersSDK} knowledge {baseCalibrationDatasheetsAPICAD} {FilesCommunity} Projects Links: Product {SupportCommunityGitHub} {ProjectStart} testing in Jupyter notebooks}, + titleaddon = {Intel® {RealSense}™ Developer Documentation}, + author = {{Intel RealSense}}, + urldate = {2020-08-13}, + date = {2020-08-08}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/JK3QSF7W/docs.html:text/html} +} + +@software{beder_jbederyaml-cpp_2020, + title = {jbeder/yaml-cpp}, + rights = {{MIT} License , {MIT} License}, + url = {https://github.com/jbeder/yaml-cpp}, + abstract = {A {YAML} parser and emitter in C++. Contribute to jbeder/yaml-cpp development by creating an account on {GitHub}.}, + author = {Beder, Jesse}, + urldate = {2020-08-13}, + date = {2020-08-13}, + note = {original-date: 2015-03-30T02:52:32Z} +} + +@online{qt_company_ltd_qt_2019, + title = {Qt Documentation}, + url = {https://doc.qt.io/}, + titleaddon = {Qt}, + author = {{Qt Company Ltd}}, + urldate = {2020-08-13}, + date = {2019}, + file = {Qt Documentation:/home/simon/Zotero/storage/LBLN3PF5/doc.qt.io.html:text/html} +} + +@online{mantidproject_profiling_nodate, + title = {Profiling with Valgrind}, + url = {https://developer.mantidproject.org/ProfilingWithValgrind.html}, + titleaddon = {mantidproject}, + author = {{mantidproject}}, + urldate = {2020-08-13}, + file = {Profiling with Valgrind:/home/simon/Zotero/storage/KRTXYVRZ/ProfilingWithValgrind.html:text/html} +} + +@online{sanjay_ghemawat_gperftools_2008, + title = {Gperftools {CPU} Profiler}, + url = {https://gperftools.github.io/gperftools/cpuprofile.html}, + titleaddon = {gperftools.github.io}, + author = {{Sanjay Ghemawat}}, + urldate = {2020-08-13}, + date = {2008-05-09}, + file = {Gperftools CPU Profiler:/home/simon/Zotero/storage/7UN5TJIR/cpuprofile.html:text/html} +} + +@online{sugih_jamin_eecs_nodate, + title = {{EECS} 380: gprof Quick-Start Guide}, + url = {http://web.eecs.umich.edu/~sugih/pointers/gprof_quick.html}, + titleaddon = {Umich.edu}, + author = {{Sugih Jamin}}, + urldate = {2020-08-13}, + file = {EECS 380\: gprof Quick-Start Guide:/home/simon/Zotero/storage/WGAUK5TW/gprof_quick.html:text/html} +} + +@online{opencv_dev_team_geometric_2019, + title = {Geometric Image Transformations — {OpenCV} 2.4.13.7 documentation}, + url = {https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#resize}, + titleaddon = {{OpenCV}}, + author = {{opencv dev team}}, + urldate = {2020-08-13}, + date = {2019-12-31}, + file = {Geometric Image Transformations — OpenCV 2.4.13.7 documentation:/home/simon/Zotero/storage/6GW6TSG3/geometric_transformations.html:text/html} +} + +@online{opencv_dev_team_changing_2019, + title = {Changing the contrast and brightness of an image! — {OpenCV} 2.4.13.7 documentation}, + url = {https://docs.opencv.org/2.4/doc/tutorials/core/basic_linear_transform/basic_linear_transform.html}, + titleaddon = {{OpenCV}}, + author = {{opencv dev team}}, + urldate = {2020-08-13}, + date = {2019-12-31}, + file = {Changing the contrast and brightness of an image! — OpenCV 2.4.13.7 documentation:/home/simon/Zotero/storage/45ZRA5HE/basic_linear_transform.html:text/html} +} + +@online{opencv_dev_team_feature_2019, + title = {Feature Detection — {OpenCV} 2.4.13.7 documentation}, + url = {https://docs.opencv.org/2.4/modules/imgproc/doc/feature_detection.html?highlight=houghcircles#houghcircles}, + titleaddon = {{OpenCV}}, + author = {opencv dev team}, + urldate = {2020-08-13}, + date = {2019-12-31}, + file = {Feature Detection — OpenCV 2.4.13.7 documentation:/home/simon/Zotero/storage/6XPEJ27F/feature_detection.html:text/html} +} + +@online{paul_bourke_point_nodate, + title = {Point, Line, Plane}, + url = {http://paulbourke.net/geometry/pointlineplane/}, + titleaddon = {paulbourke.net}, + author = {{Paul Bourke}}, + urldate = {2020-08-13}, + file = {Point, Line, Plane:/home/simon/Zotero/storage/A6K7XG7Y/pointlineplane.html:text/html} +} + +@online{opencv_dev_team_affine_2019, + title = {Affine Transformations — {OpenCV} 2.4.13.7 documentation}, + url = {https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html}, + titleaddon = {{OpenCV}}, + author = {{opencv dev team}}, + urldate = {2020-08-13}, + date = {2019-12-31}, + file = {Affine Transformations — OpenCV 2.4.13.7 documentation:/home/simon/Zotero/storage/JTKA5EV2/warp_affine.html:text/html} +} + +@online{opencv_dev_team_geometric_2019-1, + title = {Geometric Image Transformations — {OpenCV} 2.4.13.7 documentation}, + url = {https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?highlight=warpaffine#warpaffine}, + titleaddon = {{OpenCV}}, + author = {{opencv dev team}}, + urldate = {2020-08-13}, + date = {2019-12-31}, + file = {Geometric Image Transformations — OpenCV 2.4.13.7 documentation:/home/simon/Zotero/storage/H9WWDB7M/geometric_transformations.html:text/html} +} + +@online{intel_realsense_projection_2019, + title = {Projection in Intel {RealSense} {SDK} 2.0}, + url = {https://dev.intelrealsense.com/docs/projection-in-intel-realsense-sdk-20#distortion-models}, + abstract = {This document describes the projection mathematics relating the images provided by the Intel {RealSense} depth devices to their associated 3D coordinate systems, as well as the relationships between those coordinate systems. These facilities are mathematically equivalent to those provided by previous ...}, + titleaddon = {Intel® {RealSense}™ Developer Documentation}, + author = {{Intel RealSense}}, + urldate = {2020-08-13}, + date = {2019-08-08}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/2H9AU4NQ/projection-in-intel-realsense-sdk-20.html:text/html} +} + +@online{noauthor_table_nodate, + title = {Table 1 . Comparative specifications of Microsoft Kinect v1 and v2.}, + url = {https://www.researchgate.net/figure/Comparative-specifications-of-Microsoft-Kinect-v1-and-v2_tbl1_313333776}, + abstract = {Download Table {\textbar} Comparative specifications of Microsoft Kinect v1 and v2. from publication: Real Time Apnoea Monitoring of Children Using the Microsoft Kinect Sensor: A Pilot Study {\textbar} The objective of this study was to design a non-invasive system for the observation of respiratory rates and detection of apnoea using analysis of real time image sequences captured in any given sleep position and under any light conditions (even in dark environments). A... {\textbar} Kinect, Real Time and Sensors {\textbar} {ResearchGate}, the professional network for scientists.}, + titleaddon = {{ResearchGate}}, + urldate = {2020-08-14}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/Z9QHUGAR/Comparative-specifications-of-Microsoft-Kinect-v1-and-v2_tbl1_313333776.html:text/html} +} + +@online{sandbox_software_nodate, + title = {Software}, + url = {https://isandbox.co.uk/software/}, + titleaddon = {The home of augmented reality sandbox}, + author = {sandbox, The home of augmented reality}, + urldate = {2020-08-14}, + file = {Snapshot:/home/simon/Zotero/storage/3R99TXT6/software.html:text/html} +} + +@online{intel_realsense_depth_nodate, + title = {Depth Camera D415}, + url = {https://www.intelrealsense.com/depth-camera-d415/}, + abstract = {Depth camera D415 has a narrower field of view, a rolling shutter that are ideally suited for high accuracy applications such as 3D scanning.}, + titleaddon = {Intel® {RealSense}™ Depth and Tracking Cameras}, + author = {{Intel RealSense}}, + urldate = {2020-08-15}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/FVM9H5HM/depth-camera-d415.html:text/html} +} + +@online{intel_realsense_depth_nodate-1, + title = {Depth Camera D435}, + url = {https://www.intelrealsense.com/depth-camera-d435/}, + abstract = {Depth Camera D435 offers the widest field of view of all our cameras, global shutter on the depth sensor that is ideal for fast moving applications.}, + titleaddon = {Intel® {RealSense}™ Depth and Tracking Cameras}, + author = {{Intel RealSense}}, + urldate = {2020-08-15}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/AT4LQAK4/depth-camera-d435.html:text/html} +} + +@online{intel_realsense_intelrealsenselibrealsense_nodate, + title = {{IntelRealSense}/librealsense}, + url = {https://github.com/IntelRealSense/librealsense}, + abstract = {Intel® {RealSense}™ {SDK}. Contribute to {IntelRealSense}/librealsense development by creating an account on {GitHub}.}, + titleaddon = {{GitHub}}, + author = {{Intel RealSense}}, + urldate = {2020-08-15}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/5ZX28S46/Projection-in-RealSense-SDK-2.html:text/html} +} + +@inreference{noauthor_opencv_2020, + title = {{OpenCV}}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://en.wikipedia.org/w/index.php?title=OpenCV&oldid=972100697}, + abstract = {{OpenCV} (Open Source Computer Vision Library) is a library of programming functions mainly aimed at real-time computer vision. Originally developed by Intel, it was later supported by Willow Garage then Itseez (which was later acquired by Intel). The library is cross-platform and free for use under the open-source {BSD} license.}, + booktitle = {Wikipedia}, + urldate = {2020-08-15}, + date = {2020-08-10}, + langid = {english}, + note = {Page Version {ID}: 972100697}, + file = {Snapshot:/home/simon/Zotero/storage/TDKQSTIS/index.html:text/html} +} + +@inreference{noauthor_opencv_2020-1, + title = {{OpenCV}}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://fr.wikipedia.org/w/index.php?title=OpenCV&oldid=166957581}, + abstract = {{OpenCV} (pour Open Computer Vision) est une bibliothèque graphique libre, initialement développée par Intel, spécialisée dans le traitement d'images en temps réel. La société de robotique Willow Garage et la société {ItSeez} se sont succédé au support de cette bibliothèque. Depuis 2016 et le rachat de {ItSeez} par Intel, le support est de nouveau assuré par Intel. +Cette bibliothèque est distribuée sous licence {BSD}. +{NVidia} a annoncé en septembre 2010 qu'il développerait des fonctions utilisant {CUDA} pour {OpenCV}.}, + booktitle = {Wikipédia}, + urldate = {2020-08-15}, + date = {2020-02-01}, + langid = {french}, + note = {Page Version {ID}: 166957581}, + file = {Snapshot:/home/simon/Zotero/storage/XP5N94P7/index.html:text/html} +} + +@inreference{noauthor_qt_2020, + title = {Qt}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://fr.wikipedia.org/w/index.php?title=Qt&oldid=170935077}, + abstract = {Qt (prononcé officiellement en anglais cute (/kjuːt/) mais couramment prononcé Q.T. (/ˈkjuː.ˈtiː/)) : + +une {API} orientée objet et développée en C++, conjointement par The Qt Company et Qt Project. Qt offre des composants d'interface graphique (widgets), d'accès aux données, de connexions réseaux, de gestion des fils d'exécution, d'analyse {XML}, etc. ; +par certains aspects, elle ressemble à un framework lorsqu'on l'utilise pour concevoir des interfaces graphiques ou que l'on conçoit l'architecture de son application en utilisant les mécanismes des signaux et slots par exemple.Qt permet la portabilité des applications qui n'utilisent que ses composants par simple recompilation du code source. Les environnements pris en charge sont les Unix (dont {GNU}/Linux) qui utilisent le système graphique X Window System ou Wayland, Windows, Mac {OS} X, Tizen et également Genode. Le fait d'être une bibliothèque logicielle multiplateforme attire un grand nombre de personnes qui ont donc l'occasion de diffuser leurs programmes sur les principaux {OS} existants. +Qt intègre des bindings avec plus d'une dizaine de langages autres que le C++, comme Ada, C\#, Java, Python, Ruby, Visual Basic, etc. +Qt est notamment connu pour être le framework sur lequel repose l'environnement graphique {KDE} Plasma, l'un des environnements de bureau par défaut de plusieurs distributions {GNU}/Linux.}, + booktitle = {Wikipédia}, + urldate = {2020-08-15}, + date = {2020-05-16}, + langid = {french}, + note = {Page Version {ID}: 170935077}, + file = {Snapshot:/home/simon/Zotero/storage/Q48ISQ8M/index.html:text/html} +} + +@online{chris_demetriou_google_2007, + title = {Google {CPU} Profiler Binary Data File Format}, + url = {https://gperftools.github.io/gperftools/cpuprofile-fileformat.html}, + titleaddon = {gperftools.github.io}, + author = {{Chris Demetriou}}, + urldate = {2020-08-15}, + date = {2007-08-27}, + file = {Google CPU Profiler Binary Data File Format:/home/simon/Zotero/storage/ZVDBEYBN/cpuprofile-fileformat.html:text/html} +} + +@online{valgrind_developpers_valgrind_nodate, + title = {Valgrind Home}, + url = {https://valgrind.org/}, + titleaddon = {Valgrind}, + author = {{Valgrind Developpers}}, + urldate = {2020-08-15}, + file = {Valgrind Home:/home/simon/Zotero/storage/ANNQAK4J/valgrind.org.html:text/html} +} + +@online{intel_realsense_stereo_nodate, + title = {Stereo Depth}, + url = {https://www.intelrealsense.com/stereo-depth/}, + abstract = {Intel® {RealSense}™ Stereo Depth Technology brings 3D to devices and machines that only see 2D today. Check out our latest active stereo depth cameras.}, + titleaddon = {Intel® {RealSense}™ Depth and Tracking Cameras}, + author = {{Intel RealSense}}, + urldate = {2020-08-16}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/5MZ6XCVV/stereo-depth.html:text/html} +} + +@inreference{noauthor_gprof_2016, + title = {Gprof}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://fr.wikipedia.org/w/index.php?title=Gprof&oldid=127793681}, + abstract = {Gprof est un logiciel {GNU} Binary Utilities qui permet d'effectuer du profilage de code.}, + booktitle = {Wikipédia}, + urldate = {2020-08-16}, + date = {2016-07-12}, + langid = {french}, + note = {Page Version {ID}: 127793681}, + file = {Snapshot:/home/simon/Zotero/storage/JENPTFC7/index.html:text/html} +} + +@online{intel_realsense_intel_nodate, + title = {Intel® {RealSense}™ Technology}, + url = {https://www.intel.com/content/www/us/en/architecture-and-technology/realsense-overview.html}, + abstract = {Intel® {RealSense}™ technology takes perceptual computing to the next level by understanding sensory input and movement-supported platforms.}, + titleaddon = {Intel}, + author = {{Intel RealSense}}, + urldate = {2020-08-16}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/G6JP9RZZ/realsense-overview.html:text/html} +} + +@online{noauthor_augmented_nodate, + title = {Augmented reality sandbox {\textbar} Award-winning, certified {\textbar} Ships internationally}, + url = {http://ar-sandbox.com/}, + abstract = {3D interactive sandbox for education, entertainment, therapy. 25 interactive modes: topography, contour lines, rivers, volcanoes. You can use your hardware.}, + titleaddon = {ar-sandbox.com}, + urldate = {2020-08-16}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/TMDAETWP/ar-sandbox.com.html:text/html} +} + +@online{noauthor_intel_nodate, + title = {Intel {RealSense} {SDK} 2.0 – Intel {RealSense} Depth and Tracking cameras}, + url = {https://www.intelrealsense.com/sdk-2/}, + abstract = {Free Cross-platform {SDK} for depth cameras (lidar, stereo, coded light). Windows, Linux and other. 10+ wrappers including {ROS}, Python, C/C++, C\#, unity. Try!}, + titleaddon = {Intel® {RealSense}™ Depth and Tracking Cameras}, + urldate = {2020-08-16}, + langid = {american}, + file = {Snapshot:/home/simon/Zotero/storage/MCZTTCTN/sdk-2.html:text/html} +} + +@inreference{noauthor_yaml_2020, + title = {{YAML}}, + rights = {Creative Commons Attribution-{ShareAlike} License}, + url = {https://fr.wikipedia.org/w/index.php?title=YAML&oldid=173456652}, + abstract = {{YAML}, acronyme de Yet Another Markup Language dans sa version 1.0, il devient l'acronyme récursif de {YAML} Ain't Markup Language (« {YAML} n’est pas un langage de balisage ») dans sa version 1.1, est un format de représentation de données par sérialisation Unicode. Il reprend des concepts d'autres langages comme {XML}, ou encore du format de message électronique tel que documenté par {RFC} 2822. {YAML} a été proposé par Clark Evans en 2001, et implémenté par ses soins ainsi que par Brian Ingerson et Oren Ben-Kiki. +Son objet est de représenter des informations plus élaborées que le simple {CSV} en gardant cependant une lisibilité presque comparable, et bien plus grande en tout cas que du {XML}. +En 2015, Symfony 2, Drupal 8 et {phpMyAdmin}, entre autres, l'utilisent pour leurs formats d'entrée et de sortie.}, + booktitle = {Wikipédia}, + urldate = {2020-08-16}, + date = {2020-08-01}, + langid = {french}, + note = {Page Version {ID}: 173456652}, + file = {Snapshot:/home/simon/Zotero/storage/LU4BWLCA/index.html:text/html} +} + +@online{noauthor_libxrandr_nodate, + title = {libxrandr}, + url = {https://www.x.org/wiki/libraries/libxrandr/}, + urldate = {2020-08-16}, + file = {libxrandr:/home/simon/Zotero/storage/TCA2LDVR/libxrandr.html:text/html} +} + +@online{noauthor_rs-align_nodate, + title = {rs-align}, + url = {https://dev.intelrealsense.com/docs/rs-align}, + abstract = {Overview This example introduces the concept of spatial stream alignment.For example usecase of alignment, please check out align-advanced and measure demos.The need for spatial alignment (from here "align") arises from the factthat not all camera streams are captured from a single viewport. Align p...}, + titleaddon = {Intel® {RealSense}™ Developer Documentation}, + urldate = {2020-08-16}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/EDIUJ37J/rs-align.html:text/html} +} + +@online{sinha_circle_nodate, + title = {Circle Hough Transform - {AI} Shack}, + url = {https://aishack.in/tutorials/circle-hough-transform/}, + titleaddon = {{AI} Shack}, + author = {Sinha, Utkarsh}, + urldate = {2020-08-16}, + langid = {english}, + file = {Snapshot:/home/simon/Zotero/storage/6XXKFIWC/circle-hough-transform.html:text/html} +} \ No newline at end of file diff --git a/memoire/chapters/abstract.tex b/memoire/chapters/abstract.tex index b4e14a7e3af59faf8908b279284d6ac64c895d56..b92f65011fea3409c0cfcb05e7d4269c6c561fea 100644 --- a/memoire/chapters/abstract.tex +++ b/memoire/chapters/abstract.tex @@ -4,13 +4,7 @@ \addcontentsline{toc}{chapter}{Résumé} % Adding toc entry \thispagestyle{noheader} -\vspace{118pt} - -\begin{center} - {\Large < Insérez ici la page d’énoncé complété et signé\\*[-0.8em] - par l’enseignant-e responsable (cf. feuille de style fournie) >\\*[1em] - - (obligatoire)\\*[1em] - - \textit{Attention : Tout l’énoncé doit tenir sur une seule page}} -\end{center} \ No newline at end of file +\begin{figure}[H] + \centering + \includegraphics[scale=0.8]{resume.jpg} +\end{figure} diff --git a/memoire/chapters/acknowledgements.tex b/memoire/chapters/acknowledgements.tex index f5ecaa6f1312267e5843d3e13685e946a90b9864..d370680c1ac45cfc86c6746b522148a44df0838e 100644 --- a/memoire/chapters/acknowledgements.tex +++ b/memoire/chapters/acknowledgements.tex @@ -2,4 +2,4 @@ \chapter*{Remerciements} % No (numbered) toc entry with * \addcontentsline{toc}{chapter}{Remerciements} % Adding toc entry -\textit{< Formulez ici vos remerciements aux personnes qui vous ont aidé dans la réalisation de votre travail. >} \ No newline at end of file +Je remercie M. Paul Albuquerque, M. Adrien Lescourt et M. Pierre Kunzli de m'avoir suivi tout au long de ce projet. diff --git a/memoire/chapters/acronyms.tex b/memoire/chapters/acronyms.tex index cc76d50e8fd42d78d538d298762c554a79ed88b1..500ac7f8fa5e8e6978f421f123d05e441fa8da07 100644 --- a/memoire/chapters/acronyms.tex +++ b/memoire/chapters/acronyms.tex @@ -1,12 +1,2 @@ % !TeX spellcheck = fr_FR \printnoidxglossary[type=\acronymtype,title={Liste de acronymes}] - -% Use the acronyms -\vspace{5cm} -\textit{NB : Vous pouvez utiliser des acronymes en les définissant dans le fichier externe \texttt{/glossary/acronyms}. Une page dans la table des matières sera automatiquement ajoutée. Vous pourrez ensuite les référencer dans votre texte comme dans l'exemple ci-après:}\medskip - -\gls{utc} is 3 hours behind \gls{adt} and 10 hours ahead of \gls{est}.\medskip - -\textit{Lors de la première déclaration, l'acronyme est accompagné de sa définition, mais lors des utilisations suivantes, il ne l'est plus, comme illustré ci-dessous:}\medskip - -\gls{utc} is 3 hours behind \gls{adt} and 10 hours ahead of \gls{est}. \ No newline at end of file diff --git a/memoire/chapters/annexes.tex b/memoire/chapters/annexes.tex index bc8f847c2266f2ec231c5f044cbd3e0bf8e12c8a..70b0c6cd497a480cea3bd9254192913593fccce7 100644 --- a/memoire/chapters/annexes.tex +++ b/memoire/chapters/annexes.tex @@ -6,25 +6,34 @@ %%% /COMMENT THESES LINES IF YOU DO NOT USE DEDICATED TOC FOR ANNEXES \chapter*{Annexes} -\begin{center} -\textit{Imprimer idéalement cette page sur une page de couleur.} -\textit{Chaque annexe doit commencer sur une nouvelle page et doit être numérotée : Annexe 1 puis Annexe 2, etc.} -\end{center} - -\chapter*{Annexe 1} -\addcontentsline{toc}{chapter}{Annexe 1} - - -\chapter*{Annexe 2} -\addcontentsline{toc}{chapter}{Annexe 2} - - -\chapter*{Annexe 3} -\addcontentsline{toc}{chapter}{Annexe 3} +\chapter*{Annexe 1 : Arborescence Gperftools} +\addcontentsline{toc}{chapter}{Annexe 1 : Arborescence Gperftools} +\begin{figure}[H] + \centering + \includegraphics[scale=0.32]{gperftools_graph.jpg} +\end{figure} + +\chapter*{Annexe 2 : Interface Valgrind} +\addcontentsline{toc}{chapter}{Annexe 2 : Interface Valgrind} +\begin{figure}[H] + \centering + \includegraphics[angle=90,scale=0.4]{valgrind.png} +\end{figure} + +\chapter*{Annexe 3 : Exemple d'utilisation de la librairie} +\addcontentsline{toc}{chapter}{Annexe 3 : Exemple d'utilisation de la librairie} +\begin{figure}[H] + \centering + \includegraphics[scale=0.6]{exemple_code_main.png} +\end{figure} +\begin{figure}[H] + \centering + \includegraphics[scale=0.5]{exemple_code_display_levels.png} +\end{figure} %%% COMMENT THESES LINES IF YOU DO NOT USE DEDICATED TOC FOR ANNEXES \stopcontents[annexes] \resumecontents[default] -%%% /COMMENT THESES LINES IF YOU DO NOT USE DEDICATED TOC FOR ANNEXES \ No newline at end of file +%%% /COMMENT THESES LINES IF YOU DO NOT USE DEDICATED TOC FOR ANNEXES diff --git a/memoire/chapters/content/architecture.tex b/memoire/chapters/content/architecture.tex index 2a73050f65ceb3de4a0551463e5746c0bcc95922..6896626795ae277fd785094b709ca48047c4a424 100644 --- a/memoire/chapters/content/architecture.tex +++ b/memoire/chapters/content/architecture.tex @@ -1,37 +1,44 @@ +% !TeX spellcheck = fr_FR \chapter{Architecture logicielle} \section{Librairies} \begin{figure}[H] \centering - \includegraphics[scale=0.5]{archi_sandbox_api.jpg} + \includegraphics[scale=0.6]{archi_sandbox_api.jpg} + \caption{Relations entre les classes de l'\gls{api}} + \label{fig:archi_archi_sandbox_api} \end{figure} -Dans cette architecture, les classes sont assez représentatives de l'infrastructure réelle. Nous avons \textit{Beamer} qui représente les informations liées au vidéoprojecteur et méthodes liées à l'étape de calibration. Elle contient aussi FrameProcessProfil, qui est un profil contenant des informations liées au traitement d'images et est utilisé lors de configuration de la librairie. \textit{Camera} est l'interface utilisant la librairie realsense 2, permettant l'utilisation de la camera Intel. Elle est notamment utilisée par Beamer. +Dans cette architecture, les classes sont assez représentatives de l'infrastructure réelle. Nous avons \textit{Beamer} qui représente les informations liées au vidéoprojecteur utilisé et les méthodes spécifiques au beamer liées à l'étape de calibration. Elle contient aussi \textit{FrameProcessProfil}, qui est un profil contenant des informations liées au traitement d'images et est utilisé lors de la calibration. \textit{Camera} est l'interface utilisant la librairie realsense 2 \parencite{noauthor_intel_nodate}, permettant l'utilisation de la camera d'Intel. Elle est notamment utilisée par \textit{Beamer} lors de la calibration et par \textit{Projection} lors de l'utilisation. \\ -Ensuite nous avons Projection, qui contient les traitements nécessaires à appliquer à une image projetée. Puis il y a SandboxConfig, qui est une classe permettant de lire et écrire les informations liées à la configuration de la librairie dans un fichier yaml. +Ensuite nous avons \textit{Projection}, qui contient les traitements nécessaires à appliquer à une image projetée. Puis il y a \textit{SandboxConfig}, qui est une classe permettant de lire et écrire les informations liées à la configuration de la librairie dans un fichier. \\ -Enfin nous avons les interfaces de la librairie sandbox, respectivement Sandbox pour les applications utilisateur et SandboxSetup pour les applications permettant génération de la configuration utilisée par Sandbox. +Enfin nous avons les interfaces de la librairie, respectivement \textit{Sandbox} correspondant à la librairie d'utilisation permettant de développer les applications utilisateur et \textit{SandboxSetup} correspondant à la librairie de calibration et permettant de développer les applications de calibration qui généreront la configuration utilisée par \textit{Sandbox}. -\section{API Sandbox} -Sandbox instancie Camera, Beamer et Projection et fait le lien entre le tout. Elle va s'occuper de fournir de quoi initlialiser la camera et charger la configuration. Elle fournira les méthodes permettant de récupérer les images de profondeur et de couleur de la camera adaptées à la zone d'affichage du vidéoprojecteur, et de quoi ajuster une image à projeter sur le bac à sable. +\section{Librairie d'utilisation} +La librairie d'utilisation, aussi appelée \textit{Sandbox} instancie \textit{Camera}, \textit{Beamer} et \textit{Projection} et fait le lien entre le tout. Elle va s'occuper de fournir de quoi initlialiser la caméra et charger la configuration. Elle fournira les méthodes permettant de récupérer les images de profondeur et de couleur de la caméra adaptées à la zone d'affichage du beamer, et de quoi ajuster une image à projeter sur le bac à sable, qui tiendra compte de la position du beamer, de sa rotation par rapport à la caméra, ainsi que de sa distance avec le sommet du bac à sable. -\section{API SandboxSetup} -SandboxSetup instancie aussi Camera, Beamer et Projection et permet d'accéder aux méthodes de configuration de la librairie. Elle permet de déterminer les variables liées à l'infrastructure qui serviront à avoir un rendu correcte sur le bac à sable. Hormis le fait que nous n'allons pas utiliser les méthodes de traitement d'images de Projection, Camera et Beamer seront solicités pour déterminer la position du Beamer par rapport à la caméra et pour récupérer les images capturés sans traitement. Une fois que la configuration déterminé, SandboxConfig permettra de la sauvegarder. +\section{Librairie de calibration} +La librairie de calibration \textit{SandboxSetup} instancie aussi \textit{Camera}, \textit{Beamer} et \textit{Projection} et permet d'accéder aux méthodes de configuration de la librairie. Elle permet de déterminer les variables liées à l'infrastructure qui serviront à avoir un rendu correcte sur le bac à sable. Hormis le fait que nous n'allons pas utiliser les méthodes de traitement d'images de \textit{Projection}, \textit{Camera} et \textit{Beamer} seront solicités pour déterminer la position du \textit{Beamer} par rapport à la caméra et pour récupérer les images capturées sans traitement. Une fois la configuration déterminée, \textit{SandboxConfig} permettra de la sauvegarder. \section{Application de calibration} -Pour faciliter la génération du fichier de configuration, il a fallut faire une application plus sympa pour l'utilisateur. L'application de configuration utilise la librairie SandboxSetup et est basé sur le framework Qt. +Pour faciliter la génération du fichier de configuration, il a fallu faire une application plus agréable pour l'utilisateur. L'application de calibration utilise la librairie de calibration \textit{SandboxSetup}. \begin{figure}[H] \centering - \includegraphics[scale=0.4]{archi_setup_app.jpg} + \includegraphics[scale=0.45]{archi_setup_app_main.jpg} + \caption{Relations entre les éléments principaux de l'application de calibration} + \label{fig:archi_archi_sandbox_api} \end{figure} -Cette application est basé sur MainWindow, qui sera l'interface parent tout au long de la procédure de configuration. Elle instancie SandboxSetup, afin qu'elle puisse utiliser l'infrastructure du bac à sable, et toutes les classes héritant de SubApp. SubApp représente une étape de la configuration, donc chaque classes en héritant, correspondra à une phase de la configuration. En l'occurence les classes InitCameraGui, MonitorGui, ProjectionGui, CameraFocusGui, CroppingMaskGui, BeamerLocationGui et SaveConfigGui. +Cette application est basée sur MainWindow, qui sera l'interface parente tout au long de la procédure de calibration. Elle instancie \textit{SandboxSetup}, afin qu'elle puisse utiliser l'infrastructure du bac à sable, puis instancie toutes les classes héritant de \textit{SubApp}. \textit{SubApp} représente une étape de la calibration, donc chaque classes en héritant correspondra à une phase de la configuration. En l'occurence les classes \textit{InitCameraGui}, \textit{MonitorGui}, \textit{ProjectionGui}, \textit{CameraFocusGui}, \textit{CroppingMaskGui}, \textit{BeamerLocationGui} et \textit{SaveConfigGui}. \\ -InitCameraGui sert à initialiser la caméra et vérifier qu'elle soit disponible. MonitorGui sert à sélectionner la sortie correspondant au vidéoprojecteur et sa résolution. ProjectionGui sert à correctement placer le vidéoprojecteur et la caméra. CameraFocusGui permet d'établir le FrameProcessProfil qui contient des valeurs permettant un meilleur rendu de l'image capturée par la caméra. CroppingMaskGui permet de déterminer la matrice de rotation et la zone intéréssante dans les images de la caméra, qui seront utilisées lors de l'ajustement de l'image projetée. BeamerLocationGui permet d'executer la routine permettant d'établir la position du vidéoprojecteur. Enfin SaveConfigGui permet de sauvegarder la configuration dans un fichier. +\textit{InitCameraGui} sert à initialiser la caméra et vérifier qu'elle soit disponible. \textit{MonitorGui} sert à sélectionner la sortie correspondant au vidéoprojecteur et sa résolution. \textit{ProjectionGui} permet de faciliter la mise en place du vidéoprojecteur et de la caméra. \textit{CameraFocusGui} permet d'établir le profil \textit{FrameProcessProfil} qui contient les valeurs permettant un meilleur rendu de l'image de la caméra lors de la calibration. \textit{CroppingMaskGui} permet de déterminer la matrice de rotation liée à la rotation du beamer, ainsi que la zone d'intérêt des images de la caméra et la distance avec le plan se trouvant au dessus du bac à sable. Tout ces paramètres seront nécessaires à l'ajustement des images projetées. \textit{BeamerLocationGui} permet d'exécuter la routine permettant d'établir la position du vidéoprojecteur, qui sera elle aussi utilisée lors de l'ajustement des projections. Enfin \textit{SaveConfigGui} permet de sauvegarder la configuration dans un fichier. -\section{Applications utilisateur} -Lorsqu'un utilisateur veut utiliser la librairie Sandbox, il devra toujours passer par ces étapes. +\section{Applications utilisateurs} +Lorsqu'un utilisateur veut utiliser la librairie d'utilisation \textit{Sandbox}, il devra toujours passer par ces étapes. \begin{figure}[H] \centering \includegraphics[scale=0.4]{sandbox_activity_diagram.jpg} + \caption{Etapes d'initialisation de la librairie utilisateur} + \label{fig:archi_archi_sandbox_api} \end{figure} -Il devra initialiser la librairie pour s'assurer que l'infrastructure est disponible. Puis charger la configuration et s'assurer qu'elle soit présente, pour ensuite exécuter son application avec la confirmation que la librairie fonctionnera correctement. +Il devra initialiser la librairie pour s'assurer que l'infrastructure est disponible. Puis charger la configuration en s'assurant qu'elle soit présente, pour ensuite exécuter son application avec la confirmation que la librairie fonctionnera correctement. diff --git a/memoire/chapters/content/besoins.tex b/memoire/chapters/content/besoins.tex index 105cb784c43b521bb18e015f4aece7b6959c596d..c716cf27d40ee44d32caeae9de238a2ff95166cc 100644 --- a/memoire/chapters/content/besoins.tex +++ b/memoire/chapters/content/besoins.tex @@ -1,21 +1,24 @@ +% !TeX spellcheck = fr_FR \chapter{Besoins et Fonctionnalités} \section{Définition des besoins} -Lors du montage de l'infrastructure du bac à sable, la caméra et le vidéoprojecteur peuvent ne pas être exactement positionnés comme ils le devraient, c'est pourquoi nous prenons en compte les paramètres décrient dans \textit{problématiques géométriques}. Mais ces paramètres ne sont pas facilement déterminables, c'est pourquoi il faut mettre en place une application de calibration permettant de déterminer ces paramètres de manière guidée. De plus cette application devra se baser sur une librairie de calibration, afin de pouvoir créer différentes applications de calibration si besoin.\\ -De plus, il faudrait aussi éviter de réitérer la procédure de calibration à chaque utilisations de la librairie.\\ -Enfin, il faudra fournir une librairie d'utilisation du bac à sable, afin que les développeurs puissent utiliser le bac de manière simple. C'est à dire, charger la configuration établi lors de la calibration et initialiser le système, ainsi que récupérer les images prises par la caméra et ajuster correctement l'image à projeter. Le tout en essayant de minimiser le temps des traitements, afin de rendre les applications le plus dynamique possible. +Les utilisateurs du bac sont variés. Il y a tout d'abord les utilisateurs qui voudront développer des applications sur le bac à sable et ensuite les utilisateurs qui voudront utiliser les applications développées pour le bac. Comme il n'existe actuellement pas de librairie permettant aux développeurs de faire des applications, il faudra fournir une librairie d'utilisation du bac à sable le leur permettant. Cette librairie devra permettre de corriger les problématiques indiquées précédemment dans la section \textit{problématiques géométriques}. De plus, elle devra permettre aux applications de réalité augmentée d'être affichées correctement et le plus dynamiquement possible, afin de garder une fluidité dans l'expérience de réalité augmentée.\\ +Lorsqu'un utilisateur d'application voudra utiliser le bac, il devra tout d'abord le construire et passer par l'étape de calibration qui permet de déterminer les facteurs géométriques liés à l'infrastructure, afin de pouvoir les corriger lors de l'utilisation des applications basées sur la librairie d'utilisation. C'est pourquoi une application de calibration permettant de déterminer ces facteurs de manière guidée est nécessaire.\\ + +Une fois ces facteurs déterminés, les applications devront en prendre connaissance afin d'être cohérentes avec l'infrastructure présente. De plus, comme ces facteurs sont nécessaire aux applications, il faudra permettre la sauvegarde de cette configuration, afin de ne pas réitérer la procédure de calibration à chaque utilisation des applications. Car cette procédure n'est nécessaire que lors du montage du système ou lors de sa modification. \section{Fonctionnalités} La librairie devra être séparée en deux parties distinctes. Une devra fournir les fonctionnalités de calibration de la librairie, et l’autre devra fournir les fonctionnalités d’utilisation de la -librairie.\\ +librairie. Ces deux librairies devront permettre la création des applications de réalité augmentée et de calibration.\\ + \subsection*{Librairie d'utilisation} -La librairie d'utilisation devra permettre ces points clé : +La librairie d'utilisation devra répondre à ces attentes : \begin{itemize} \item capture les photos de profondeurs et couleurs avec la camera \item ajuste une image à projeter sur le bac à sable - \item charge la configuration depuis le fichier + \item charge la configuration depuis un fichier de configuration \item initialise le bac à sable \end{itemize} @@ -32,7 +35,7 @@ Une fois les étapes de configuration et initialisation effectuées avec succès \subsection*{Librairie de calibration} La librairie de calibration devra permettre à l'application d'exécuter correctement les routines et sauvegarder la configuration. Elle devra donc : \begin{itemize} - \item charger certaines informations du fichier de config si nécessaire + \item charger certaines informations du fichier de configuration si nécessaire \item fournir les méthodes de calibration permettant de déterminer les données de configuration \item sauvegarder la configuration dans un fichier pour la rendre persistante \end{itemize} @@ -44,4 +47,4 @@ La librairie de calibration devra permettre à l'application d'exécuter correct \label{fig:besoins_diagram_sequence_sandbox_setup} \end{figure} -Dans ce scénario, nous allons récupérer les données de configuration en effectuant les routines de calibration, puis les sauvegarder dans un fichier. Ainsi nous avons notre configuration de prête pour les applications utilisateurs. +Dans ce scénario, nous allons récupérer les données de configuration en effectuant les routines de calibration, puis les sauvegarder dans un fichier. Ainsi nous avons notre configuration prête pour les applications utilisateurs. diff --git a/memoire/chapters/content/conclusion.tex b/memoire/chapters/content/conclusion.tex index 2ffcd31f921f9f28d82d0f7a4ced4b311c1206b5..36610299dac4f48c788dc61943944c26b3cd34a0 100644 --- a/memoire/chapters/content/conclusion.tex +++ b/memoire/chapters/content/conclusion.tex @@ -1,9 +1,14 @@ % !TeX spellcheck = fr_FR -\chapter*{Conclusion} -\addcontentsline{toc}{chapter}{Conclusion} % Adding toc entry - -Les paysagistes et architectes peinent à modifier leurs maquettes une fois qu’elles sont créées. C’est pourquoi nous proposons de mettre à disposition un bac à sable de réalité augmentée qui leur servira de substitue à leur maquette tant que leurs plans ne sont pas définitifs. Les diverses applications basées sur le bac utiliseront l’API C++ refaite, permettant une utilisation similaire aux autres librairies C++ standard. Grâce à l’amélioration de la précision et de l’affichage de la librairie, les applications seront plus justement rendues. De plus, comme la librairie nécessite des données de configuration, une application de calibration a été créée afin qu’il soit plus facile de saisir ces données en cas de configuration et qu’il ne soit plus nécessaire de le faire à chaque utilisations.\\ -Ce travail m’a permis de développer des compétences avec le langage C++ et le framework Qt. Ainsi que de me pousser à mieux maîtriser la librairie OpenCV durant la phase d’optimisation et d’avoir une introduction à l’utilisation d’outils de profiling. J’ai aussi appris à tout d’abord réaliser une solution fonctionnelle avant de l’améliorer, comme ce fut le cas lors de l’utilisation de la librairie xrandr. -\section{Amélioration} -La manière de déterminer la matrice de rotation pourrait être revue, afin de prendre en compte le centre du rectangle dessiné par l’utilisateur lors de la phase de calibration, cela permettrait à la mise en place du vidéoprojecteur d’être un peu plus permissive. De plus, il serait judicieux d’essayer d’améliorer la vitesse de l’application des filtres sur les images prises par la caméra. Puis, l’amélioration de la vitesse d’ajustement d’une image projetée permettra d’améliorer la réactiver des applications utilisateurs. Ensuite, les différentes données de calibration pourraient toutes être regroupées dans une classe de calibration. Finalement, nous pourrions faciliter l’installation de la librairie, afin de permettre aux développeurs C++ d’inclure la librairie comme tout autre librairie système. Mais encore, la présence direct d’un exécutable pour l’application de calibration et la possibilité de choisir le lieu de sauvegarde du fichier de configuration en fin de calibration.\\ -Donc je pense que globalement le projet est stable et que la prochaine étape est l’amélioration des performances et la facilitation de l’expérience utilisateur/développeur. Ainsi, les différents projets de réalité augmentée utilisant le bac à sable et la librairie pourront voir le jour. +\chapter{Conclusion} + +Les architectes paysagistes peinent à modifier leurs maquettes de terrain une fois qu’elles sont créées. C’est pourquoi en se basant sur le projet de réalité augmentée de l'UC Davis, nous avons mis en place un bac à sable de réalité augmentée qui leur servira de substitut à leurs maquettes. De plus, il est désormais facile de déterminer la configuration d'autres infrastructures et dans différents milieux, grâce à l'application de calibration réalisée en Qt qui générera un fichier YAML contenant la configuration. L'application produite est basée sur notre \gls{api} de calibration en C++, afin de permettre la création d'autres applications de calibration si la nôtre ne convenait pas à leur besoin. En complément de la librairie de calibration, une autre librairie d'utilisation en C++ a été fournie afin de permettre la création d'applications utilisateurs. Cette dernière permet de lire la configuration déterminée grâce à l'application de calibration et permet d'utiliser la caméra et de projeter des images adaptées à l'infrastructure. Finalement une application de démonstration affichant les niveaux du bac en couleurs a été développée grâce à l'\gls{api} d'utilisation. + + +\section{Améliorations} +La manière de déterminer la matrice de rotation pourrait être revue, afin de prendre en compte le centre du rectangle dessiné par l’utilisateur lors de la phase de calibration, cela permettrait la mise en place du vidéoprojecteur plus permissive. De plus, il serait judicieux d’essayer d’améliorer la vitesse de l’application des filtres sur les images prises par la caméra. Ainsi que l’amélioration de la vitesse de traitement d'une image à projeter grâce à de la parallèlisation, ce qui permettrait aux applications utilisateurs d'être plus réactives. Finalement, nous pourrions faciliter l’installation de la librairie, afin de permettre aux développeurs C++ d’inclure la librairie directement à la racine du système d'exploitation. Ainsi que, la présence d’un exécutable pour l’application de calibration et la possibilité de choisir le lieu de sauvegarde du fichier de configuration en fin de calibration.\\ + + +\section{Perspectives} +La flexiblitée apportée lors de ce projet permet la création de différentes applications utilisateurs. Comme une application de reproduction de modèles de topologie, qui permettrait aux architectes paysagistes de faire une simple sauvegarde de leur topologie et de la reproduction dans le bac une fois qu'ils en auraient besoin. Ou encore une application de bac à distance, qui connecterait deux bacs distants afin que les utilisateurs voient en temps réel à travers le monde et concrètement la topologie envisagée par leur partenaire. + + diff --git a/memoire/chapters/content/dispositif.tex b/memoire/chapters/content/dispositif.tex index 6e29de421fb80211c1468eaaea76e6ec5f51f2b4..532654d65c2cf34dfc7bb274d7c9ebc8fc0db5fb 100644 --- a/memoire/chapters/content/dispositif.tex +++ b/memoire/chapters/content/dispositif.tex @@ -1,27 +1,74 @@ - +% !TeX spellcheck = fr_FR \chapter{Description du dispositif} -Le projet utilise une camera pour récupérer la topologie du bac à sable qui nous permettra d’ajuster en conséquence l’image à projetée par le vidéoprojecteur sur le bac à sable. +\section{Dispositif} +Afin de reproduire cet outil de réalité augmentée, nous nous sommes basés sur le projet open source de l'\gls{ucdavis}. + \begin{figure}[H] \centering - \includegraphics[scale=0.5]{dispositif.jpg} - \caption{Dispositif} - \label{fig:dispositif_dispositif} + \includegraphics[scale=0.5]{ARSandboxLayout.jpg} + \caption{Infrastructure du bac à sable de l'\gls{ucdavis}. Source : tiré de arsandbox.ucdavis.edu, ref. URL03} + \label{fig:dispositif_ARSandboxLayout} \end{figure} -Contrairement au projet décrit dans l'introduction, nous utilisons la caméra d'Intel D415 avec la librairie realsense 2, ainsi que le vidéoprojecteur PLC-XU116 de la marque Sanyo. + +Nous avons donc monté notre propre bac à sable (100cm x 75cm x 20cm), posé un beamer à courte focale qui se trouve à environ 1.2 mètres au-dessus du bac afin de recouvrir l'entièreté du bac, ainsi qu'une caméra de profondeur positionnée à un mètre au dessus du bac à sable. De plus nous utilisons un ordinateur standard basé sur une distribution linux. + +\begin{figure}[H] + \centering + \includegraphics[scale=0.1]{dispositif_sandbox.jpg} + \caption{Dispositif du bac à sable de réalité augmentée à HEPIA} + \label{fig:dispositif_dispositif_sandbox} +\end{figure} + +Cependant, comme énoncé précédement dans le projet d'\gls{ucdavis}, la Kinect utilisée dans leur projet est désormais obsolète. Nous avons donc dû choisir une autre caméra de profondeur pouvant fonctionner correctement à un mètre du bac. + + + +\section{Caméra} + +Lors du choix de la caméra, il faut prendre en compte ses performances, ainsi que ses spécificités d'objectif. Le but étant de trouver une caméra pouvant être positionnée à un mètre au-dessus du bac, nous avons comparé les caractéristiques de la Realsense D415 \parencite{intel_realsense_depth_nodate} et de la D435 \parencite{intel_realsense_depth_nodate-1}. + +\begin{table} +\begin{center} + \begin{tabular}{|m{2cm} m{2cm} m{2cm} m{2cm} m{2cm}|} + \hline + Caméra & Ouvertures objectif & Distance minimum & Résolution profondeur & Vitesse de rafraîchissement \\ + \hline + D415 & 65°±2° × 40°±1° & 0.16 m & Up to 1280 × 720 & Up to 90 fps \\ + \hline + D435 & 86° × 57° (±3°) & 0.105 m & Up to 1280 × 720 & Up to 90 fps \\ + \hline + \end{tabular} +\end{center} +\caption{Tableau comparatif des caméra de profondeur de Intel RealSense. Source : tiré de www.intelrealsense.com, ref URL07} +\label{tab:dispositif_table_realsense_depth_camera} +\end{table} + +Les deux caméras ont globalement les mêmes caractéristiques, avec la D435 qui est plus imposante que la D415. Mais ce qui détermina notre choix, c'est l'ouverture des caméras. La D435 a une ouverture plus grande que la D415, ce qui implique que si nous voulons avoir notre bac à sable complètement dans l'objectif, nous devrons poser la D435 plus bas que la D415. Mais comme nous voulons poser notre caméra à un mètre et que notre bac à sable est de dimensions 100cm x 75cm, nous avons déduit que la D415 s'approchait le plus de cette hauteur. + + + + +\section{Applications} +Les applications fournies par le projet de l'\gls{ucdavis} fonctionnent correctement avec leur projet. Malheureusement, le projet ne propose pas de librairie permettant d'exploiter le bac à sable. Il est donc impossible en l'état de développer des applications avec ce projet et aucune de leurs applications ne peut foncionner sur notre infrastructure. + + + \section{Problématiques géométriques} -Normalement, lorsque nous voulons projeter une image avec un vidéoprojecteur, nous le faisons sur une surface plane. Hors dans notre cas, l'image est projetée sur le sable avec une certaine topologie. +Afin de pouvoir exploiter cet outils, nous devons résoudre quelques problématiques géométriques liées à la disposition de l'infrastructure.\\ +Normalement, lorsque nous voulons projeter une image avec un vidéoprojecteur, nous le faisons sur une surface plane. Or dans notre cas, l'image est projetée sur le sable avec une certaine topologie. \begin{figure}[H] \centering - \includegraphics[scale=0.4]{adjust_pixel.jpg} - \caption{Projection pixel} + \includegraphics[scale=0.5]{adjust_pixel.jpg} + \caption{Correction de la projection d'un pixel} \label{fig:dispositif_adjust_pixel} \end{figure} Comme notre vidéoprojecteur doit pouvoir projeter sur une surface plane, nous avons défini le sommet du bac à sable comme repère pour projeter notre image. Ainsi le champ de vision de la caméra correspond à la zone de projection du vidéoprojecteur. \\ -Dans ce schéma, nous avons la caméra qui récupère la hauteur à un certain point (orange) et nous avons notre vidéoprojecteur qui projette un pixel. Ce pixel sera projeté à la position bleu sans ajustement, car l'image projetée correspondant au champ de vision de la caméra. C'est seulement en corrigeant la position sur notre plan (sommet du bac à sable), que nous pouvons adapter notre affichage à la position du vidéoprojecteur. Donc en ajustant le pixel qui serait projeté à la position bleu, vers la position orange, nous arrivons à projeter une image cohérente sur le sable.\\ +Dans ce schéma, nous avons la caméra qui récupère la hauteur à un certain point (orange) et nous avons notre vidéoprojecteur qui projette un pixel. Ce pixel sera projeté à la position bleu sans ajustement, car l'image projetée correspond au champ de vision de la caméra. C'est seulement en corrigeant la position sur notre plan (sommet du bac à sable), que nous pouvons adapter notre affichage à la position du vidéoprojecteur. Donc en ajustant le pixel qui serait projeté à la position bleu, vers la position orange, nous arrivons à projeter une image cohérente sur le sable.\\ Malheureusement, l'infrastructure mise en place ne sera pas toujours aussi exacte que celle sur le schéma. Notamment la position de la caméra et du vidéoprojecteur, ainsi que la taille du bac à sable. C'est pourquoi il faut ajuster la taille de l'image projetée à celle de la capture de la caméra. + \begin{figure}[H] \centering \includegraphics[scale=0.35]{camera_zones.jpg} @@ -29,7 +76,7 @@ Malheureusement, l'infrastructure mise en place ne sera pas toujours aussi exact \label{fig:dispositif_camera_zones} \end{figure} -Ainsi, en ajustant seulement les pixels de la projection, nous conservons la cohérence entre la zone de projection et la zone capturée par la caméra.\\ +Ainsi, en déterminant la zone de projection par rapport au point de vue de la caméra, nous pouvons ajuster seulement les pixels de la projection et ainsi conserver la cohérence entre la zone de projection et la zone capturée par la caméra.\\ Enfin il se peut que le vidéoprojecteur ne soit pas parfaitement droit et qu'il y ait une rotation de l'image projetée par rapport à la caméra. \begin{figure}[H] @@ -39,5 +86,5 @@ Enfin il se peut que le vidéoprojecteur ne soit pas parfaitement droit et qu'il \label{fig:dispositif_rotation} \end{figure} -En corrigeant cette rotation lors de l'affichage, nous aurons une projection juste par rapport à la caméra. +En corrigeant cette rotation centrée à la projection lors de l'affichage, nous aurons une projection alignée au point de vue de la caméra. diff --git a/memoire/chapters/content/existant.tex b/memoire/chapters/content/existant.tex index d215abc497882c0a19308fa8596491eeecae5722..ba6ceb5a70364f2b6f2932c27519e2fcbfc9bc3d 100644 --- a/memoire/chapters/content/existant.tex +++ b/memoire/chapters/content/existant.tex @@ -1,47 +1,88 @@ - +% !TeX spellcheck = fr_FR \chapter{Etude de l'existant} -\section{UCDavis} -Comme vue précédemment dans l'introduction, ce projet se base sur d'autres projets de réalité augmentée de bac à sable. Nous avons entrevu le projet de l'université de Californie à Davis qui fonctionnait ainsi : + +\section{UC Davis} +L'\gls{ucdavis} a créé son propre prototype de bac à sable de réalité augmentée. Leur but est de fournir un outil pédagogique interactif basé sur des applications d'affichage de topographie et de simulutation de fluide. + \begin{figure}[H] \centering - \includegraphics[scale=1]{ARSandboxLayout.jpg} - \caption{Infrastructure du bac à sable de l'université de Californie à Davis, \url{https://arsandbox.ucdavis.edu/instructions/hardware-2/}} - \label{fig:existant_ARSandboxLayout} + \includegraphics[scale=0.3]{uclaSandboxWater.jpg} + \caption{\gls{ucla} démonstration de bac à sable avec simulutation d'eau. Source : tiré de arsandbox.ucdavis.edu, ref. URL02} + \label{fig:existant_uclaSandboxWater} \end{figure} -Le projet utilise la Kinect 3D de Microsoft, ainsi qu'un vidéoprojecteur courte portée avec un ratio d'affichage de 4:3, afin que la zone projetée corresponde à la zone de capture de la Kinect. Enfin nous avons les applications qui s'exécutent sur l'ordinateur connecté.\\ -Ce projet est abouti, malheureusement, la Kinect utilisée dans ce projet n'est plus en production depuis octobre 2017(\url{https://fr.wikipedia.org/wiki/Kinect}). Bien qu'un nouveau modèle de la Kinect soit sortie (Azur Kinect DK,\url{https://www.microsoft.com/en-us/p/azure-kinect-dk/8pp5vxmd9nhq}), le projet ne la supporte pas, par contre il supporte les caméra Realsense de Intel.\\ -Toutefois, le projet fournit directement ces application et ne propose pas de librairie permettant de développer des application pour le bac. De plus, les infrastructures utilisant les applications disponibles doivent respecter cet infrastructure. -\section{Adow} -Le second projet est celui de Mr. Adow, réalisé dans le cadre de son travail de bachelor. Son projet était basé toujours sur la même infrastructure de bac à sable en réalité augmentée, mais il utilisait la caméra d'Intel D415, avec le vidéoprojecteur PLC-XU116 à focale courte de la marque Sanyo.\\ -De plus le projet proposait une API qui était accessible au travers d'un serveur local. Cela permettait une flexibilité sur le langage de l'interface de la librairie. +Afin de produire ces applications, le projet se base sur cette infrastructure : \begin{figure}[H] \centering - \includegraphics[scale=0.3]{old_lib_srv.jpg} - \caption{Architecture API client-serveur du projet de M. Adow, \url{https://arsandbox.ucdavis.edu/instructions/hardware-2/}} + \includegraphics[scale=0.5]{ARSandboxLayout.jpg} + \caption{Infrastructure du bac à sable de l'\gls{ucdavis}. Source : tiré de arsandbox.ucdavis.edu, ref. URL03} \label{fig:existant_ARSandboxLayout} \end{figure} -Une fois le serveur exécuté et la calibration du bac à sable complétée, nous pouvions utiliser le bac en envoyant l'image à projeter au serveur.\\ -Bien que ce projet offre un API pour développer des applications, certains points restent à améliorer comme le fait que l'étape de calibration soit nécessaire à chaque exécution du serveur, ainsi que le manque d'une véritable application de calibration. +Ils utilisent la Kinect v1 de Microsoft \parencite{noauthor_kinect_2020} comme caméra de profondeur, ainsi qu'un beamer courte portée avec un ratio d'affichage de 4:3, afin que la zone projetée corresponde à la zone de capture de la Kinect. Le tout interconnecté à l'ordinateur exécutant les applications de réalité augmentée. Grâce à la topologie récupérée du bac à sable par la caméra, l'image peut être ajustée et projetée correctement sur le bac.\\ +\begin{figure}[H] + \centering + \includegraphics[scale=0.2]{kinect_v1.png} + \caption{Kinect v1 utilisée dans le projet UC Davis. Source : tiré de fr.wikipedia.org, ref URL04} + \label{fig:existant_kinect} +\end{figure} -\section{Camera} - -Lors du choix de la caméra, il faut prendre en compte ses performances, ainsi que ses spécificités d'objectif. Le but étant de trouver une caméra pouvant être positionné à un mètre au-dessus du bac, nous avons comparé les caractéristiques de la Realsense D415 et de la D435. +\begin{table} \begin{center} - \begin{tabular}{|m{2cm} m{2cm} m{2cm} m{2cm} m{2cm}|} - \hline - Caméra & Ouvertures objectif & Distance minimum & Résolution profondeur & Vitesse de rafraîchissement \\ - \hline - D415 & 65°±2° × 40°±1° & 0.16 m & Up to 1280 × 720 & Up to 90 fps \\ - \hline - D435 & 86° × 57° (±3°) & 0.105 m & Up to 1280 × 720 & Up to 90 fps \\ - \hline - \end{tabular} +\begin{tabular}{ |c|c| } +\hline +Caméra & Microsoft KinectV1 \\ +\hline +Couleurs - Résolution & 640 × 480 jusqu'à 30 images par seconde\\ +\hline +Profondeurs - Résolution & 320 × 240 jusqu’à 30 images par seconde\\ +\hline +Taille & 35.5cm x 17.8cm x 7.6cm\\ +\hline +\end{tabular} \end{center} +\caption{Tableau des caractéristiques de la caméra de profondeur Kinect V1. Source : tiré de researchgate.net, ref URL05} +\label{tab:existant_tableau_kinect} +\end{table} + + + +Malheureusement pour les utilisateurs du projet, Microsoft annonce l'arrêt de la production de ces caméras en octobre 2017 \parencite{noauthor_kinect_2020}. +Cependant, le projet permet tout de même d'utiliser les autres modèles Kinect-for-Xbox 1414 et 1473, Kinect pour Windows, et Kinect pour Xbox One, ainsi que les caméras RealSense d'Intel \parencite{intel_realsense_intel_nodate} \parencite{uc_davis_hardware_2016}. De plus une version permettant d'utiliser la version deux de la Kinect est en développement. +\\ +Comme ce projet fait partie des premiers et qu'il est open source, \gls{ucdavis} ajoute les projets de bac à sable reproduisant ce projet dans le monde. + +\begin{figure}[H] + \centering + \includegraphics[scale=0.3]{ucdavis_world.jpg} + \caption{Projets UC Davis à travers le monde. Source : tiré de arsandbox.ucdavis.edu, ref. URL02} + \label{fig:existant_ucdavis_world} +\end{figure} + +Tout ces projets sont des bacs, qui ont été montés dans le monde en suivant les indications données dans leur guide. + + +\section{iSandBOX} +Le projet iSandBOX est un projet de bac à sable en réalité augmentée réalisé par Universal Terminal Systems pour le monde professionnel et le divertissement pour les enfants \parencite{noauthor_augmented_nodate}.\\ +Cette entreprise propose plusieurs applications de réalité augmentée différentes comme : + +\begin{figure}[H] + \centering + \includegraphics[scale=0.2]{isandbox_volcan.png} + \caption{Simulation de volcan avec iSandBOX. Source : tiré de isandbox.co.uk, ref. URL06} + \label{fig:existant_isandbox_vlocan} +\end{figure} +Cette simulation de volcan qui brûle tout sur son passage et projette des nuages de cendres. + +\begin{figure}[H] + \centering + \includegraphics[scale=0.2]{isandbox_ice_age.png} + \caption{Simulation de l'âge de glace avec iSandBOX. Source : tiré de isandbox.co.uk, ref. URL06} + \label{fig:existant_isandbox_ice_age} +\end{figure} +Ou encore cette simulation de l'âge de glace avec de vraies statuettes de dinosaures. -Les deux caméras ont globalement les mêmes caractéristiques, avec la D435 qui est plus imposante que la D415. Mais ce qui détermina notre choix, c'est l'ouverture des caméras. La D435 a une ouverture plus grande que la D415, ce qui implique que si nous voulons avoir notre bac à sable complètement dans l'objectif, nous devrons poser la D435 plus bas que la D415. Mais comme nous voulons poser notre caméra à un mètre et que notre bac à sable est de dimensions 100cmx75cm. Nous avons déduit que la D415 s'approchait le plus de cette hauteur. diff --git a/memoire/chapters/content/implementation.tex b/memoire/chapters/content/implementation.tex index 727f81d42b2d95ae5b382d7cdc7eb00a07cc610f..a762170e71f6cf7bb88696e01860d1b97aef6102 100644 --- a/memoire/chapters/content/implementation.tex +++ b/memoire/chapters/content/implementation.tex @@ -1,155 +1,174 @@ \chapter{Conception et implémentation} -\section{Sandbox} +\section{Librairie d'utilisation} \subsection*{Principe} -La librairie Sandbox doit fournir une interface permettant l'affichage d'une image dans le bac à sable adapté à la topologie de celui-ci. Comme vu précédemment dans la description, plusieurs ajustement sont nécessaires. Nous allons donc voir plus précisément comment l'ajustement de l'image ce fait.\\ -En appelant la fonction adjustProjection, l'utilisateur passe son image en couleur à projeter : +La librairie d'utilisation \textit{Sandbox} doit fournir une interface permettant l'affichage d'une image dans le bac à sable adapté à la topologie de celui-ci. Comme vu précédemment dans la description, plusieurs ajustements sont nécessaires. Nous allons donc voir plus précisément comment l'ajustement de l'image se fait.\\ +En appelant la fonction \textit{adjustProjection}, l'utilisateur passe son image en couleur à projeter : \begin{itemize} \item capture de la topologie du bac à sable \item initialisation du buffeur de sortie \item appels à la fonction adjustFrame de la classe Projection \item retour du buffeur de sortie \end{itemize} -Nous avons donc un buffeur pour l'image de sortie, ainsi qu'un autre contenant les profondeurs du bac à sable (représentées par des floats équivalent à des mètres). Pour rappels, notre but est de corriger la valeur des pixels à afficher à une position donnée. +Nous avons donc un buffeur pour l'image de sortie, ainsi qu'un autre contenant les profondeurs du bac à sable (représentées par des floats équivalent à des mètres). Pour rappel, notre but est de corriger la valeur des pixels à afficher à une position donnée. \begin{figure}[H] \centering \includegraphics[scale=0.5]{adjust_pixel.jpg} + \caption{Correction de la projection d'un pixel} + \label{fig:imp_adjust_pixel} \end{figure} -Il faut donc ce baser sur le point de vue de la caméra pour connaître la position du point depuis le point de vue du vidéoprojecteur. C'est à dire trouver la position verte, sinon la rouge sera par défaut et ne sera pas représentative de la réalité.\\ -En regardant de plus près la fonction adjustFrame, on peut voir qu'elle suit cette démarche pour ajuster l'image :\\ +Il faut donc se baser sur le point de vue de la caméra pour connaître la position du point depuis le point de vue du vidéoprojecteur. C'est à dire trouver la position verte, sinon la rouge sera par défaut et ne sera pas représentative de la réalité.\\ +En regardant de plus près la fonction \textit{adjustFrame}, on peut voir qu'elle suit cette démarche pour ajuster l'image :\\ \begin{figure}[H] \centering \includegraphics[scale=0.5]{projection_pipeline.jpg} + \caption{Fil d'exécution de la correction d'une projection} + \label{fig:imp_projection_pipeline} \end{figure} -Maintenant nous avons une compréhension plus précise de ce qu'il se passe lors du traitement d'une image. Nous verrons plus en détails la fonction adjustFrame dans Projection. +Maintenant nous avons une compréhension plus précise de ce qu'il se passe lors du traitement d'une image. Nous verrons plus en détails la fonction \textit{adjustFrame} dans \textit{Projection}. \subsection*{SandboxConfig} -Bien que nous ayons vu le principe de l'ajustement d'une image, il est irréalisable tant que nous ne possédons pas les informations de configuration. C'est pourquoi dans la librairie, il y a une méthode permettant de lire le fichier de configuration yaml et charger les informations dans leurs variables respectives. Si on regarde dans cette méthode, on s'aperçoit qu'elle utilise les méthodes statiques de la classe SadnboxConfig, afin de charger les informations nécessaires lors du processus d'ajustement de l'image projetée. Grâce à la librairie yaml-cpp, il est très facile d’interagir avec les données. Il suffit de charger les données dans un nœud, pour ensuite interagir avec ce nœud comme avec un tableau associatif. De plus, il est aussi facile d'écrire les données dans un fichier, il suffit de traiter le nœud comme du texte lors d'un affichage dans la sortie standard en C++. +Bien que nous ayons vu le principe de l'ajustement d'une image, il est irréalisable tant que nous ne possédons pas les informations de configuration. C'est pourquoi dans la librairie, il y a une méthode permettant de lire le fichier de configuration écrit en YAML et de charger les informations dans leurs variables respectives. Si on regarde dans cette méthode, on s'aperçoit qu'elle utilise les méthodes statiques de la classe \textit{SandboxConfig}, afin de charger les informations nécessaires lors du processus d'ajustement de l'image projetée. Grâce à la librairie yaml-cpp, il est très facile d’interagir avec les données. Il suffit de charger les données dans un nœud, pour ensuite interagir avec ce nœud comme avec un tableau associatif. De plus, il est aussi facile d'écrire les données dans un fichier, il suffit de traiter le nœud comme du texte lors d'un affichage dans la sortie standard en C++. \subsection*{Camera} -La librairie utilise la caméra D415 de Intel. Elle comprend deux récepteurs stéréo avec un projeteur qui servent à capturer l'image de profondeur et un récepteur RGB qui sert à capturer l'image de couleur. https://www.intelrealsense.com/wp-content/uploads/2020/06/Intel-RealSense-D400-Series-Datasheet-June-2020.pdf (p.108) +La librairie utilise la caméra D415 de Intel. Elle comprend deux récepteurs stéréo avec un projeteur qui servent à capturer l'image de profondeur et un récepteur RGB qui sert à capturer l'image de couleur. + \begin{figure}[H] \centering \includegraphics[scale=0.5]{camera_archi.jpg} + \caption{Module de la RealSense D415. Source : Intel RealSense D400 Series Datasheet June 2020 (p.108)} + \label{fig:implementation_camera_archi} \end{figure} -https://www.intelrealsense.com/depth-camera-d415/ -La caméra peut fournir une résolution allant jusqu'à 1920x1080 pour la caméra de couleur et 1280x720 pour celle de profondeur. Comme les résolutions et potentiellement les champs de vision des objectifs diffères, Intel a mis en place une méthode permettant de s'assurer que l'image récupérer en couleur corresponde au champs de vision de celle de profondeur. Il s'agit de la la classe align disponibles dans la librairie realsense 2. + +La caméra peut fournir une résolution allant jusqu'à 1920x1080 pour la caméra de couleur et 1280x720 pour celle de profondeur. Comme les résolutions et potentiellement les champs de vision des objectifs diffères, Intel a mis en place une méthode permettant de s'assurer que l'image récupérer en couleur corresponde au champs de vision de celle de profondeur. Il s'agit de la la classe \textit{align} disponibles dans la librairie realsense 2. \begin{figure}[H] \centering \includegraphics[scale=0.3]{camera_pov.jpg} + \caption{Point de vue des objectifs de profondeur et de couleur de la caméra RealSense} + \label{fig:imp_camera_pov} \end{figure} -Dans notre cas, align a été paramétré pour s'aligner sur le flux de profondeurs, donc les images de profondeurs et couleurs seront basés sur l'objectif de profondeur. https://dev.intelrealsense.com/docs/rs-align -Lorsque nous récupérons les images de profondeurs et couleurs, nous avons des matrices de 1280x720. Mais dans la librairie sandbox, nous ne renvoyons pas directement l'image capturée par la caméra, elle est rognée pour correspondre à la zone de projection du vidéoprojecteur. +Dans notre cas, \textit{align} a été paramétrée pour s'aligner sur le flux de profondeurs, donc les images de profondeur et couleur seront basées sur l'objectif de profondeur \parencite{noauthor_rs-align_nodate}.\\ +Lorsque nous récupérons les images de profondeur et couleur, nous avons des matrices de 1280x720. Mais dans la librairie sandbox, nous ne renvoyons pas directement l'image capturée par la caméra, elle est rognée pour correspondre à la zone de projection du vidéoprojecteur. \begin{figure}[H] \centering \includegraphics[scale=0.3]{camera_zones.jpg} + \caption{Zone de l'image projetée par rapport au point de vue de la caméra} + \label{fig:imp_camera_zones} \end{figure} -Autrement dit, on ne récupère que la zone bleu par rapport au point de vue de la caméra. Ce qui définie cette délimitation est un rectangle que nous avons appelé CroppingMask et qui est sauvegardé dans la classe Camera. -Notons qu'il est important de permettre à la caméra de chauffer les capteurs de profondeurs, autrement ceux-ci ne capteront qu'une partie avec leur objectifs, voir rien du tout, ce qui retournera une image de profondeur vide. +Autrement dit, on ne récupère que la zone bleue par rapport au point de vue de la caméra. Ce qui définit cette délimitation est un rectangle que nous avons appelé \textit{CroppingMask} et qui est sauvegardé dans la classe \textit{Camera}. +Notons qu'il est important de permettre à la caméra de "chauffer" les capteurs de profondeurs, autrement ceux-ci ne capteront qu'une partie avec leur objectifs, voir rien du tout, ce qui retournera une image de profondeur vide.\\ -Dans la classe Camera, nous utilisons les fonctions de projection et déprojection. Ces méthodes nous sont nécessaires pour passer de la matrice de profondeurs à un repère 3D et inversement. Les valeurs contenus dans la matrice de profondeur correspondent à la profondeur Z sur un repère 3D et non à la profondeur direct entre l'objet et l'objectif, ici appelée Range. Une méthode permettant de récupérer la Range existe dans la librairie realsense 2, mais nous n'utiliserons pas. -https://www.intelrealsense.com/wp-content/uploads/2020/06/Intel-RealSense-D400-Series-Datasheet-June-2020.pdf (p.17) +Dans la classe Camera, nous utilisons les fonctions de projection et déprojection. Ces méthodes nous sont nécessaires pour passer de la matrice de profondeur à un repère 3D et inversement. Les valeurs contenus dans la matrice de profondeur correspondent à la profondeur Z sur un repère 3D et non à la profondeur directe entre l'objet et l'objectif, ici appelée Range. Une méthode permettant de récupérer la Range existe dans la librairie realsense 2, mais nous ne l'utiliserons pas. \begin{figure}[H] \centering \includegraphics[scale=0.5]{depth_frame_content.jpg} + \caption{Contenu de l'image de la caméra de profondeur. Source : Intel RealSense D400 Series Datasheet June 2020 (p.17)} + \label{fig:imp_depth_frame_content} \end{figure} -https://dev.intelrealsense.com/docs/projection-in-intel-realsense-sdk-20 -La méthode de déprojection rs2-deproject-pixel-to-point permet de déprojeter un pixel en un point 3D ou le point (0,0,0) est défini par la caméra. La méthode est défini par des coordonnées correspondant à celles d'un pixel, de la profondeur qu'il y aurait à ce pixel et d'un profil intrinsèque défini par la caméra. La méthode de projection permet l'inverse, soit de passer d'un point 3D aux coordonnées d'un pixel. Dans les deux cas nous avons besoin de ce profil intrinsèque. C'est dans celui-ci qu'est décrit le profil de la camera, le type de déformation lié à la lentille de l'objectif, la résolution de l'image et les informations lié à la position de la matrice produite par l'objectif.\\ -Dans notre cas, le modèle de déformation est le Brown-Conrady, la librairie intel fait donc une simple adaptation de repère. C'est à dire : -\begin{figure}[H] - \centering - \includegraphics[scale=0.5]{camera_point.jpg} -\end{figure} -float x = point.x / point.z; -\\float y = point.y / point.z; -\\return cv::Point2i( x*f.x+pp.x, y*f.y+pp.y); -\\\\ -On calcule x' tel que la matrice ce trouve à 1 mètre de l'objectif, ensuite on multiplie par le coefficient permettant de correspondre à la bonne résolution de la caméra, puis on ajoute pp pour remettre l'origine en haut à gauche, puisque on passe d'un repère ou le (0,0) est au centre de l'objectif à une matrice ou le (0,0) est en haut à gauche.\\ -Nous nous sommes permis de réimplémenter ces deux fonctions, car nous avions besoins de modifier les valeurs f et pp, et nous ne voulions pas être dépendant de la librairie realsense 2 dans le cas où une optimisation sur GPU ce ferait et que realsense 2 ne propose pas de solution sur GPU pour le moment.\\ -Comme les images capturées par la caméra et le profil intrinsèque sont liés, s'il l'on veut adapter les valeurs de f et pp tout en restant cohérent avec une image de dimensions différentes, il faut adapter l'image à la matrice capturée par la caméra pour qu'elles correspondent lorsqu'on les déprojettent. C'est pourquoi nous avons la méthode getAdaptedIntrinsics qui retourne ces deux paramètres ajustées à l'image à projetée.\\ -Les images de profondeurs subissent aussi un filtre spatiale et temporelle. Le spatiale permet de réduire le nombre d'information manquante dans l'image de profondeurs et le temporelle permet de stabiliser les valeurs, car les valeurs varient légèrement entre deux images même si rien n'a changé physiquement.\\ +La méthode de déprojection \textit{\texttt{rs2\_deproject\_pixel\_to\_point}} permet de déprojeter un pixel en un point 3D ou le point (0,0,0) est défini par la caméra \parencite{intel_realsense_projection_2019}. La méthode est définie par des coordonnées correspondant à celles d'un pixel, de la profondeur qu'il y aurait à ce pixel et d'un profil intrinsèque défini par la caméra. La méthode de projection permet l'inverse, soit de passer d'un point 3D aux coordonnées d'un pixel. Dans les deux cas nous avons besoin de ce profil intrinsèque. C'est dans celui-ci qu'est décrit le profil de la camera, le type de déformation lié à la lentille de l'objectif, la résolution de l'image et les informations liées à la position de la matrice produite par l'objectif.\\ +Dans notre cas, le modèle de déformation est le Brown-Conrady, la librairie realsense fait donc une simple adaptation de repère. C'est à dire :\\ +{\fontfamily{pcr}\selectfont +float x = point.x / point.z;\\ +float y = point.y / point.z;\\ +return cv::Point2i( x*f.x+pp.x, y*f.y+pp.y); +}\\ + +Où \textit{point} est notre point en 3D, puis les variables \textit{x} et \textit{y} multipliées aux coefficients de \textit{f} qui permettent de passer du repère 3D à celui d'une matrice de pixels, tels que les coefficients de \textit{f} correspondent à des multiples de pixels proportionnels à la taille de l'image produite par le capteur. De plus, il faut ajuster les coordonnées du pixel par rapport à son origine dans l'espace ou la matrice avec \textit{pp}, car l'origine (0,0) dans l'image capturée se situe dans le coin haut-gauche, alors que l'origine (0,0,0) dans l'espace 3D se situe aux coordonnées indiquées par la variable \parencite{intel_realsense_projection_2019}.\\ + + +Nous nous sommes permis de réimplémenter ces deux fonctions, car nous avions besoins de modifier les valeurs \textit{f} et \textit{pp}, et nous ne voulions pas être dépendants de la librairie realsense 2 dans le cas où une optimisation par parallélisation du traitement se ferait, car realsense 2 ne propose pas de solution sur \gls{gpu} pour le moment.\\ +Comme les images capturées par la caméra et le profil intrinsèque sont liés, si l'on veut adapter les valeurs de \textit{f} et \textit{pp} tout en restant cohérent avec une image de dimensions différentes, il faut adapter l'image à la matrice capturée par la caméra pour qu'elles correspondent lorsqu'on les déprojettent. C'est pourquoi nous avons la méthode \textit{getAdaptedIntrinsics} qui retourne ces deux paramètres ajustés à l'image à projeter.\\ +Les images de profondeurs subissent aussi un filtre spatial et temporel. Le spatial permet de réduire le nombre d'informations manquantes dans l'image de profondeur et le temporel permet de stabiliser les valeurs, car les valeurs varient légèrement entre deux images même si rien n'a changé physiquement.\\ \subsection*{Projection} -Projection -Projection est la classe qui nous permet d'ajuster l'image projetée sur le bac à sable en tenant compte des données de l'environnement. C'est but est donc principalement tourné vers l'utilisation de la fonction adjustFrame. Dans cette fonction nous utilisons plusieurs buffeurs qui ont tous les mêmes dimensions : resized-src, resized-depth, deprojectMap et frameMap. Ainsi avec le pseudo code suivant nous pouvons reconstruire l'image à projeter: +\textit{Projection} est la classe qui nous permet d'ajuster l'image projetée sur le bac à sable en tenant compte des données de l'environnement. Son but est donc principalement tourné vers l'utilisation de la fonction \textit{adjustFrame}. Dans cette fonction nous utilisons plusieurs buffeurs qui ont tous les mêmes dimensions : \textit{\texttt{resized\_src}}, \textit{\texttt{resized\_depth}}, \textit{deprojectMap} et \textit{frameMap}. Ainsi avec le pseudo code suivant nous pouvons reconstruire l'image à projeter: \begin{itemize} \item initialisation des buffeurs - \item redimensionne les buffeurs (comprends l'image source et l'image de profondeurs) à la taille de l'image de sortie - \item dé-projette resized-depth par rapport à la position du vidéoprojecteur dans deprojectMap (indique où les pixels seront positionnés dans l'image de sortie) - \item filtre les points dé-projetés aux mêmes coordonnées et ne garde que le point le plus haut en sauvegardant les coordonnées du pixel dans deprojectMap dans frameMap (indique les coordonnées du pixel source) - \item construit l'image en lisant deprojectMap pour connaître le pixel de resized-src à sélectionner et mettre dans le buffeur de sortie - \item rebouche les trous dans le buffeur de sortie pour les pixels n'ayant pas de correspondance dans frameMap + \item redimensionne les buffeurs (comprends l'image source et l'image de profondeur) à la taille de l'image de sortie + \item dé-projette \textit{\texttt{resized\_depth}} par rapport à la position du vidéoprojecteur dans \textit{deprojectMap} (indique où les pixels seront positionnés dans l'image de sortie) + \item filtre les points dé-projetés aux mêmes coordonnées et ne garde que le point le plus haut en sauvegardant les coordonnées du pixel dans \textit{deprojectMap} dans \textit{frameMap} (indique les coordonnées du pixel source) + \item construit l'image en lisant \textit{deprojectMap} pour connaître le pixel de \textit{\texttt{resized\_src}} à sélectionner et mettre dans le buffeur de sortie + \item rebouche les trous dans le buffeur de sortie pour les pixels n'ayant pas de correspondance dans \textit{frameMap} \item applique la rotation à l'image de sortie \end{itemize} -Nous avons donc une initialisation des buffeurs à la taille de la projection de l'image. Suivit d'une redimension de la matrice de profondeur (depth devient resized-depth) et de l'image source (src devient resized-src) où la méthode resize d'opencv applique une interpolation bilinéaire par défaut.\\ -\url{https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html#resize} +Nous avons donc une initialisation des buffeurs à la taille de la projection de l'image. Suivi d'une redimension de la matrice de profondeur (\textit{depth} devient \textit{\texttt{resized\_depth}}) et de l'image source (\textit{src} devient \textit{\texttt{resized\_src}}) où la méthode \textit{resize} d'OpenCV applique une interpolation bilinéaire par défaut \parencite{opencv_dev_team_geometric_2019}.\\ + +Pour mieux comprendre à quoi servent les buffeurs dédiés à la fonction, voici de quoi imager la démarche et à quel moment ils interviennent :\\ \begin{figure}[H] \centering \includegraphics[scale=0.5]{projection_buffers.jpg} + \caption{Aperçu des buffers et leurs données lors de l'ajustement d'une image projetée} + \label{fig:imp_projection_buffers} \end{figure} -Pour mieux comprendre à quoi servent les buffeurs dédiés à la fonction, voici de quoi imagé la démarche et à quel moment ils interviennent:\\ -Donc si nous revenons à l'étape de déprojection, le but est de trouver à quel pixel de l'image projetée correspond le pixel de la matrice de profondeurs, soit P' dans le schéma ci-dessous. +Donc si nous revenons à l'étape de déprojection, le but est de trouver à quel pixel de l'image projetée correspond le pixel de la matrice de profondeur, soit P' dans le schéma ci-dessous. \begin{figure}[H] \centering \includegraphics[scale=0.5]{deprojection.jpg} + \caption{Géométrie de l'adaptation d'un pixel lors de sa projection} + \label{fig:imp_deprojection} \end{figure} -Comme vu précédemment dans Principe, le but est de trouver P', car sans adaptation, P sera projetée à P2. Mais pour trouver P', il faut déjà connaître P. Grâce à la méthode deprojectPixelToPoint fournit par Camera, nous pouvons connaître les coordonnées de P en spécifiant ces coordonnées dans la matrice de profondeurs et la profondeur (donc sa valeur).\\ -Comme nous nous basons sur les valeurs de la matrice de profondeur pour établir un environnement 3D, cela implique que la base de ce repère est la caméra. De plus comme notre but est de calculer CP' qui se base sur le même plan que P2', cela implique que la caméra soit perpendiculaire au plan, qui est le dessus du bac à sable. Enfin comme la position du vidéoprojecteur (Beamer) est relative à la caméra, nous pouvons assumer que BDP' et BEP sont des triangles rectangles.\\ -Ce qui nous amènes au calcul de P' en connaissant déjà au préalable : la hauteur du dessus du bac à sable h, la position du vidéoprojecteur B, la position du point P. Ainsi nous pouvons trouver P' grâce à la formule ci-dessous. +Comme vu précédemment dans \textit{Principe}, le but est de trouver P', car sans adaptation, P sera projeté à P2. Mais pour trouver P', il faut déjà connaître P. Grâce à la méthode \textit{deprojectPixelToPoint} fournit par \textit{Camera}, nous pouvons connaître les coordonnées de P en spécifiant ces coordonnées dans la matrice de profondeur et la profondeur (donc sa valeur).\\ +Comme nous nous basons sur les valeurs de la matrice de profondeur pour établir un environnement 3D, cela implique que la base de ce repère est la caméra. De plus comme notre but est de calculer CP' qui se base sur le même plan que P2', cela implique que la caméra soit perpendiculaire au plan, qui est le dessus du bac à sable. Enfin comme la position du vidéoprojecteur (Beamer) est relative à la caméra (Camera), nous pouvons assumer que BDP' et BEP sont des triangles rectangles.\\ +Ce qui nous amène au calcul de P' en connaissant déjà au préalable : la hauteur du dessus du bac à sable h, la position du vidéoprojecteur B, la position du point P. Ainsi nous pouvons trouver P' grâce à la formule ci-dessous. \begin{figure}[H] \centering \includegraphics[scale=0.5]{deprojection_algo.jpg} + \caption{Logique de l'algorithme de deprojection} + \label{fig:imp_deprojection_algo} \end{figure} -Une fois CP' trouvé, il suffit d'utiliser la méthode projectPointToPixel pour récupérer les coordonnées correspondantes dans la matrice de profondeurs et les sauver dans notre matrice deprojectMap.\\ -Une fois que tout notre matrice deprojectMap est remplie, nous allons essayer de commencer à reconstruire notre image à projeter. Pour ce faire, nous allons lire deprojectMap et assigner l'index de la cellule de deprojectMap dans le pixel cible. Comme si nous inversions les index avec les valeurs. Sauf qu'il se peut que plusieurs pixels de deprojectMap pointent vers la même cellule, nous devons donc vérifier que seul le pixel de deprojectMap ayant le sommet le plus haut (donc la valeur la plus petite, puisque les valeurs sont relatives à la caméra) soit assigné aux coordonnées cible dans frameMap.\\ -Ensuite nous parcourons frameMap pour connaître à quel autre pixel correspond le pixel actuel et nous récupérons la valeur de l'image source à l'image de sortie. En faisant cette étape, il se peut que frameMap ait des pixels manquants, car les points de vues entre le vidéoprojecteur et la caméra diffèrent.\\ -C'est pourquoi il s'en suit l'étape de rebouchage de trous. Dans cette étape, nous parcourons à nouveau frameMap, mais cette fois à la recherche de valeurs manquantes. Lorsque nous en trouvons une, nous copions la valeur du premier voisin non vide ce trouvant à une distance d'une case. +Une fois CP' trouvé, il suffit d'utiliser la méthode \textit{projectPointToPixel} pour récupérer les coordonnées correspondantes dans la matrice de profondeur et les sauver dans notre matrice \textit{deprojectMap}.\\ +Une fois que toute notre matrice \textit{deprojectMap} est remplie, nous allons essayer de commencer à reconstruire notre image à projeter. Pour ce faire, nous allons lire \textit{deprojectMap} et assigner l'index de la cellule de \textit{deprojectMap} dans le pixel cible. Comme si nous inversions les index avec les valeurs. Sauf qu'il se peut que plusieurs pixels de \textit{deprojectMap} pointent vers la même cellule, nous devons donc vérifier que seul le pixel de \textit{deprojectMap} ayant le sommet le plus haut (donc la valeur la plus petite, puisque les valeurs sont relatives à la caméra) soit assigné aux coordonnées cible dans \textit{frameMap}.\\ +Ensuite nous parcourons \textit{frameMap} pour connaître à quel autre pixel correspond le pixel actuel et nous récupérons la valeur de l'image source à l'image de sortie. En faisant cette étape, il se peut que \textit{frameMap} ait des pixels manquants, car les points de vues entre le vidéoprojecteur et la caméra diffèrent.\\ +C'est pourquoi il s'ensuit l'étape de rebouchage de trous. Dans cette étape, nous parcourons à nouveau \textit{frameMap}, mais cette fois à la recherche de valeurs manquantes. Lorsque nous en trouvons une, nous copions la valeur du premier voisin non vide se trouvant à une distance d'une case. Enfin, il ne reste plus qu'à appliquer la matrice de rotation à notre image de sortie.\\ \subsection*{Beamer} -Dans le cas de la librairie sandbox, la classe Beamer sert à fournir la position 3D relative à la caméra de celui-ci et sa résolution. Ces informations sont toutes deux utilisées lors de l'adaptation de l'image projetée. +Dans le cas de la librairie d'utilisation, la classe \textit{Beamer} sert à fournir la position 3D relative à la caméra de celui-ci et sa résolution. Ces informations sont toutes deux utilisées lors de l'adaptation de l'image projetée. -\section{SandboxSetup} -La classe SandboxSetup sert de deuxième interface à la librairie sandbox, mais son but est de fournir les méthodes nécessaires à la génération d'un fichier de configuration complet. La classe SandboxSetup fournit les éléments comme la classe Sandbox, c'est à dire l'accès aux classes Beamer, Camera et Projection, mais aussi à SandboxConfig. Le principe est de paramétrer les classes comme si nous allions utiliser l'interface Sandbox, sauf que nous allons sauvegarder la configuration dans un fichier yaml grâce à la méthode fournit par SandboxSetup, elle permet de sauvegarder tout les éléments nécessaires en utilisant les fonctions de SandboxConfig. -La classe fournit aussi de quoi calculer la matrice de rotation et la zone d’intérêt de la capture de la caméra, car à ce stade, aucun traitement n'est fait sur les images. Nous utilisons simplement la camera et renvoyons les informations telles quelles. Il est aussi possible de charger le FrameProcessProfil qui sera utile lors du traitement d'images durant la calibration. Nous verrons plus en détails dans la partie Beamer. +\section{Librairie de calibration} +La librairie de calibration \textit{SandboxSetup} sert de deuxième interface, mais son but est de fournir les méthodes nécessaires à la génération d'un fichier de configuration complet. La classe \textit{SandboxSetup} fournit les éléments comme la classe \textit{Sandbox}, c'est à dire l'accès aux classes \textit{Beamer}, \textit{Camera} et \textit{Projection}, mais aussi à \textit{SandboxConfig}. Le principe est de paramétrer les classes comme si nous allions utiliser l'interface \textit{Sandbox}, sauf que nous allons sauvegarder la configuration dans un fichier yaml grâce à la méthode fournie par \textit{SandboxSetup}, elle permet de sauvegarder tout les éléments nécessaires en utilisant les fonctions de \textit{SandboxConfig}.\\ +La classe fournit aussi de quoi calculer la matrice de rotation et la zone d’intérêt de la capture de la caméra, car à ce stade, aucun traitement n'est fait sur les images. Nous utilisons simplement la caméra et renvoyons les informations telles quelles. Il est aussi possible de charger le profil \textit{FrameProcessProfil} qui sera utile lors du traitement d'images durant la calibration. Nous verrons plus en détails dans la partie Beamer. \subsection*{AdjustMatrix} -La méthode permettant de déterminer la matrice de rotation dans la classe SandboxSetup prend simplement la liste des coins d'un rectangle et son centre, afin de déterminer son angle de rotation grâce aux points P0 et P3, où le coin de référence pour la rotation dépendra de P0. Une fois la matrice déterminée, nous la sauvegardons dans la classe Projection. +La méthode permettant de déterminer la matrice de rotation dans la classe \textit{SandboxSetup} prend simplement la liste des coins d'un rectangle et son centre, afin de déterminer son angle de rotation grâce aux points P0 et P3, où le coin de référence pour la rotation dépendra de P0. Une fois la matrice déterminée, nous la sauvegardons dans la classe \textit{Projection}. \begin{figure}[H] \centering - \includegraphics[scale=0.5]{projection_rotation.jpg} + \includegraphics[scale=0.4]{projection_rotation.jpg} + \caption{Rotation nécessaire à la projection pour la redresser} + \label{fig:imp_projection_rotation} \end{figure} -doc adow p.30 -\\ Il est important de noter que comme la matrice redresse l'image, elle est dépendante de la rotation de la caméra si on applique la matrice à une image prise avec celle-ci. \subsection*{CroppingMask} -La méthode permettant de déterminer le masque de découpage utilise les mêmes points que pour la déterminer la matrice de rotation, sauf qu'on applique la rotation aux coins pour avoir un rectangle droit. Puis nous la sauvegardons dans la classe Camera. +La méthode permettant de déterminer le masque de découpage utilise les mêmes points que pour la déterminer la matrice de rotation, sauf qu'on applique la rotation aux coins pour avoir un rectangle droit. Puis nous la sauvegardons dans la classe \textit{Camera}. \subsection*{Beamer} -La classe Beamer propose elle aussi des méthodes liées à la calibration. En effet c'est même le cas pour la majorité d'entre elles. +La classe \textit{Beamer} propose elle aussi des méthodes liées à la calibration. En effet c'est même le cas pour la majorité d'entre elles. + \subsubsection*{Procédure} -Ces méthodes sont basées sur une procédure de calibration précise. L’utilisateur devra ce munir d’une cible comme ci-dessous afin de la réaliser. +Ces méthodes sont basées sur une procédure de calibration précise. L’utilisateur devra se munir d’une cible comme ci-dessous afin de la réaliser. \begin{figure}[H] \centering \includegraphics[scale=0.4]{circle_target.jpg} + \caption{Cible blanche nécessaire à la calibration} + \label{fig:imp_circle_target} \end{figure} Une fois cette cible acquise, l’utilisateur pourra suivre la procédure suivante : @@ -157,6 +176,8 @@ Une fois cette cible acquise, l’utilisateur pourra suivre la procédure suivan \begin{figure}[H] \centering \includegraphics[scale=0.3]{beamer_location_routine.jpg} + \caption{Routine de calibration permettant d'approximer la position du beamer} + \label{fig:imp_beamer_location_routine} \end{figure} Afin de trouver la position du vidéoprojecteur à la fin de cette procédure, les différentes méthodes devront suivre cette démarche: @@ -164,57 +185,67 @@ Afin de trouver la position du vidéoprojecteur à la fin de cette procédure, l \begin{figure}[H] \centering \includegraphics[scale=0.3]{beamer_location_pseudo_code.jpg} + \caption{Routine d'exécution détaillé de la calibration permettant d'approximer la position du beamer} + \label{fig:imp_beamer_location_pseudo_code} \end{figure} -L’utilisateur positionnera sa cible à l’endroit où les croix seront projetées. La méthode getCrossList nous permet de récupérer les positions des croix à afficher. Lorsqu’une croix est projetée, nous roix projetée, une capture est prise afin de localiser la cible, après l’avoir convertie en noir et blanc, nous pouvons modifier le constraste et la luminosité (avec editContrast), puis la passer à la méthode findCircles qui nous retournera les cercles détectés. Ensuite nous pouvons construire l’image à afficher avec la croix à l’aide de buildCrossFrame, qui affichera la croix à suivre et si la cible est détectée, en plus d’indiquer à quelle étape du processus nous en sommes.\\ -Lors de la validation d’un point de l’utilisateur, il faut s’assurer d’avoir une cible détectée, car c’est à ces coordonnées que nous allons établir un point sur un répère en 3D, pour cela il suffira d’utiliser deprojectPixel. Une fois plusieurs points validés, nous pouvons calculer la droite passant au mieux par ces points grâce à la méthode findLinearLineFrom. Enfin, lorsque nous avons assez de droites, nous pouvons approximer la position du vidéoprojecteur avec approximatePosition. +L’utilisateur positionnera sa cible à l’endroit où les croix seront projetées. La méthode \textit{getCrossList} nous permet de récupérer les positions des croix à afficher. Lorsqu’une croix est projetée, une capture est prise afin de localiser la cible, après l’avoir convertie en noir et blanc, nous pouvons modifier le constraste et la luminosité (avec \textit{editContrast}), puis la passer à la méthode \textit{findCircles} qui nous retournera les cercles détectés. Ensuite nous pouvons construire l’image à afficher avec la croix à l’aide de \textit{buildCrossFrame}, qui affichera la croix à suivre et si la cible est détectée, en plus d’indiquer à quelle étape du processus nous en sommes.\\ +Lors de la validation d’un point de l’utilisateur, il faut s’assurer d’avoir une cible détectée, car c’est à ces coordonnées que nous allons établir un point sur un répère en 3D, pour cela il suffira d’utiliser \textit{deprojectPixel}. Une fois plusieurs points validés, nous pouvons calculer la droite passant au mieux par ces points grâce à la méthode \textit{findLinearLineFrom}. Enfin, lorsque nous avons assez de droites, nous pouvons approximer la position du vidéoprojecteur avec \textit{approximatePosition}. + \subsubsection*{getCrossList} Retourne une liste de coordonnées correspondant aux croix à viser lors de la calibration. Elles devront être affichées les unes après les autres. + \subsubsection*{editConstrast} -Cette méthode adapte le constraste et la luminosité d’une image en noir et blanc en suivant cette equation :\\ +Cette méthode adapte le constraste et la luminosité d’une image en noir et blanc en suivant cette equation \parencite{opencv_dev_team_changing_2019}:\\ g(i,j) = alpha * f(i,j) + beta où alpha > 0\\ -\url{https://docs.opencv.org/2.4/doc/tutorials/core/basic_linear_transform/basic_linear_transform.html} + + \subsubsection*{findCircles} -Cette méthode permet de récupérer la position des cercles détectés. Elle est basée sur la méthode houghCircles d’OpenCV définit par : -void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 ) -HoughCircle est basé sur une matrice de compteurs, appelée accumulateur. Pour détecter un cercle, il faut tout d’abord appliquer un filtre Canny permettant de ne garder que les contours des formes dans l’image. Puis nous allons parcourir chaques pixels de notre image de contours et lorsque nous rencontrons un pixel de valeur non vide/noir, nous allons tracer un cercle autour de ces pixel, en traçant ce cercle, nous incrémentons de un aux mêmes coordonnées dans notre accumulateur. Une fois l’image parcourue, nous pouvons controller notre accumulateur pour trouver les cercles potentiels. Si les valeurs de l’accumulateur dépasse un certain seuil, alors nous avons un cercle centré à cette endroit de l’image de radius égal à celui avec lequel nous avons parcourue notre image de contours précédement. +Cette méthode permet de récupérer la position des cercles détectés. Elle est basée sur la méthode \textit{houghCircles d’Ope}nCV définit par : +\textit{void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 )}\\ +HoughCircle est basé sur une matrice de compteurs, appelée accumulateur. Pour détecter un cercle, il faut tout d’abord appliquer un filtre Canny permettant de ne garder que les contours des formes dans l’image. Puis nous allons parcourir chaque pixel de notre image de contours et lorsque nous rencontrons un pixel de valeur non vide/noir, nous allons tracer un cercle autour de ces pixels, en traçant ce cercle, nous incrémentons de un aux mêmes coordonnées dans notre accumulateur. Une fois l’image parcourue, nous pouvons contrôler notre accumulateur pour trouver les cercles potentiels. Si les valeurs de l’accumulateur dépasse un certain seuil, alors nous avons un cercle centré à cette endroit de l’image de radius égal à celui avec lequel nous avons parcouru notre image de contours précédement. \begin{itemize} \item "image" est une image en niveaux de gris \item "circles" est une liste permettant à la fonction de sauvegarder les cercles détectés - \item "method" indique à la fonction quelle méthode utiliser pour détecter les cercles. Dans notre cas, nous utilisons la méthode Hough-Gradient, c’est aussi la seul disponible pour le moment par OpenCV - \item "dp" correspond au ratio inverse de la taille de l’accumulateur. Elle sera de même taille que l’image passée en paramètre si "dp" est égale à un + \item "method" indique à la fonction quelle méthode utiliser pour détecter les cercles. Dans notre cas, nous utilisons la méthode Hough-Gradient, c’est aussi la seule disponible pour le moment par OpenCV + \item "dp" correspond au ratio inverse de la taille de l’accumulateur. Elle sera de même taille que l’image passée en paramètre si "dp" est égale à un \item "minDist" est la distance minimum entre deux cercles détectés - \item "param1" correspond au seuil suppérieur de la méthode Canny, donc le seuil indiquant un contour + \item "param1" correspond au seuil supérieur de la méthode Canny, donc le seuil indiquant un contour \item "param2" est le seuil indiquant si le centre d’un cercle existe dans notre accumulateur - \item "minRadius" et "maxRadius" permettent de gérer le rayon minimum et maximum du cercle lors du parcoure de l’image de contours incrémentant l’accumulateur + \item "minRadius" et "maxRadius" permettent de gérer le rayon minimum et maximum du cercle lors du parcours de l’image de contours incrémentant l’accumulateur \end{itemize} -\url{https://docs.opencv.org/2.4/modules/imgproc/doc/feature_detection.html?highlight=houghcircles#houghcircles} +\parencite{opencv_dev_team_feature_2019} + \subsubsection*{buildCrossFrame} Construit une image où l’on indique la position de la croix à placer. Indique si un cercle a été trouvé, si c’est le cas, un carré vert sera visible, sinon il sera rouge. Il est aussi indiqué à quelle étape nous nous trouvons sur le total. \subsubsection*{deprojectPixel} -Permet de récupérer les coordonnées 3D à partir d’un cercle détecté et de la matrice de profondeurs. +Permet de récupérer les coordonnées 3D à partir d’un cercle détecté et de la matrice de profondeur. \subsubsection*{findLinearLineFrom} -Cette methode permet de trouver la droite passant le mieux entre les points données. Elle utilise la méthode fitLine d’OpenCV. +Cette méthode permet de trouver la droite passant le mieux entre les points donnés. Elle utilise la méthode \textit{fitLine} d’OpenCV. \begin{figure}[H] \centering \includegraphics[scale=0.5]{linear_regression.jpg} + \caption{Régression linéaire} + \label{fig:imp_beamer_location_pseudo_code} \end{figure} -Regression linéaire Adow .p37 + \subsubsection*{approximatePosition} -Cette méthode permet d’approximer la position 3D du vidéoprojecteur grâce à une liste de droites (qui sont définies par un point et une direction). Elle fait appel à la méthode LineLineIntersect qui permet de trouver les points les plus proches entre deux droites :\\ -Pa = P1 + mua * (P2 - P1) -Pb = P3 + mub * (P4 - P3) -\url{http://paulbourke.net/geometry/pointlineplane/} +Cette méthode permet d’approximer la position 3D du vidéoprojecteur grâce à une liste de droites (qui sont définies par un point et une direction). Elle fait appel à la méthode \textit{LineLineIntersect} qui permet de trouver les points les plus proches entre deux droites \parencite{paul_bourke_point_nodate}:\\ +Pa = P1 + mua * (P2 - P1)\\ +Pb = P3 + mub * (P4 - P3)\\ +\\ Où Pa et Pb sont les points les plus proches. \begin{figure}[H] \centering \includegraphics[scale=0.5]{shortest_distance.jpg} + \caption{Distance la plus courte entre deux droites} + \label{fig:imp_shortest_distance} \end{figure} -Distance la plus courte entre deux droite Adow p.40 -\\ -Une fois les points trouvés, nous faisons la moyenne de tout nos points pour approximer la position du vidéoprojecteur. + +Une fois les points trouvés, nous faisons la moyenne de tous nos points pour approximer la position du vidéoprojecteur. + \subsubsection*{FrameProcessProfil} -Cette classe sert à accompagner la classe Beamer lors de la phase de calibration, son but est de contenir les différents paramètres liés au traitement d’images que nous utiliserons plus tard dans les fonctions de Beamer. Elle contient notamment les variables de luminosité et constraste utilisable dans "editContrast", ainsi que les paramètres utilisés lors dans la fonction "findCircles" liés au traitement de "HoughCircles" d’OpenCV. Plus précisement : "minDist", "param1", "param2", "minRadius" et "maxRadius". Où "param1" fait référence au seuil supérieur lié à la méthode de contour Canny, et "param2" au seuil déterminant un cercle dans notre accumulateur dans la méthode de Hough. Les variables "minDist", "minRadius" et "maxRadius" sont tout trois en pourcentage par rapport à la largeur de l’image traitée. +Cette classe sert à accompagner la classe \textit{Beamer} lors de la phase de calibration, son but est de contenir les différents paramètres liés au traitement d’images que nous utiliserons plus tard dans les fonctions de \textit{Beamer}. Elle contient notamment les variables de luminosité et constraste utilisable dans "editContrast", ainsi que les paramètres utilisés lors dans la fonction "findCircles" liés au traitement de "HoughCircles" d’OpenCV. Plus précisement : "minDist", "param1", "param2", "minRadius" et "maxRadius". Où "param1" fait référence au seuil supérieur lié à la méthode de contour Canny, et "param2" au seuil déterminant un cercle dans notre accumulateur dans la méthode de Hough. Les variables "minDist", "minRadius" et "maxRadius" sont tous trois en pourcentage par rapport à la largeur de l’image traitée. Donc nous avons : \begin{itemize} \item contrast : contraste de "editContrast" @@ -226,76 +257,91 @@ Donc nous avons : \item maxRadius : "maxRadius" de "HoughCircles" \end{itemize} \section{Fichier de configuration} -Le fichier de configuration est le fichier permettant de sauvegarder les données nécessaires à l’utilisation de la classe Sandbox et déterminées lors de la calibration. Il écrit au format YAML et est donc facilement lisible et modifiable. +Le fichier de configuration est le fichier permettant de sauvegarder les données nécessaires à l’utilisation de la classe \textit{Sandbox} et déterminées lors de la calibration. Il est écrit au format YAML et est donc facilement lisible et modifiable. + \subsection*{AdjustingMatrix} Cette variable contient la matrice qui permet de corriger la rotation du vidéoprojecteur. Elle est sauvegardée dans le fichier sous forme de vecteur, mais il s’agit bien d’une matrice de 2x3 comme l’indiqueront la hauteur et la largeur. L’angle sur lequel est basé la matrice de rotation est aussi disponible. -Si la matrice a de telles dimensions, c’est parce qu’elle est basé sur les transformations affines, on doit donc pouvoir appliquer une rotation, une translation ou un changement d’échelle avec celle-ci. +Si la matrice a de telles dimensions, c’est parce qu’elle est basée sur les transformations affines, on doit donc pouvoir appliquer une rotation, une translation ou un changement d’échelle avec celle-ci. \begin{figure}[H] \centering \includegraphics[scale=0.5]{rotationMatrix2d.jpg} + \caption{Formules déterminant la matrice de rotation. Source : docs.opencv.org, ref. URL08} + \label{fig:imp_rotationMatrix2d} \end{figure} -\url{https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html} -De plus si l’on regarde la fonction d’OpenCV warpAffine, qui applique notre matrice, on voit comment est appliqué la matrice : + +De plus si l’on regarde la fonction d’OpenCV "warpAffine", qui applique notre matrice, on voit comment est appliquée la matrice : \begin{figure}[H] \centering \includegraphics[scale=0.5]{warpAffine.jpg} + \caption{Formules applicant la matrice de rotation. Source : docs.opencv.org, ref. URL08} + \label{fig:imp_rotationMatrix2d} \end{figure} -\url{https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?highlight=warpaffine#warpaffine} -Avec cette formule, on observe que seul les deux premières colonnes sont multipliés aux coordonnées, donc la troisième contient le décalage lié au centre de rotation en cas de translation de l’image et les deux priemières sont celles liées à la rotation et à l’ajustement de l’échelle. + +Avec cette formule, on observe que seules les deux premières colonnes sont multipliées aux coordonnées, donc la troisième contient le décalage lié au centre de rotation en cas de translation de l’image et les deux premières sont celles liées à la rotation et à l’ajustement de l’échelle. + \subsection*{DistanceTopSandbox} -Cette variable sert à déterminer la distance entre la caméra et le dessus du bac à sable, car c’est à cette distance que l’image virtuelle reconstruite pour le vidéoprojecteur se trouve. Comme la matrice de profondeur fournit par la caméra, est en float, cette distance l’est aussi. +Cette variable sert à déterminer la distance entre la caméra et le dessus du bac à sable, car c’est à cette distance que l’image virtuelle reconstruite pour le vidéoprojecteur se trouve. Comme la matrice de profondeur fournie par la caméra, est en float, cette distance l’est aussi. \subsection*{CroppingMask} -Le CroppingMask est le rectangle permettant de rogner l’image de la caméra afin d’avoir uniquement la zone où le vidéoprojecteur affiche dans le bac à sable. Comme c’est un rectangle dans le même sense que la caméra, il n’a pas de rotation et est dépendant de la résolution de la caméra. Nous pouvons donc manipuler sa position et ses dimensions si nous connaissons le matériel. +Le \textit{CroppingMask} est le rectangle permettant de rogner l’image de la caméra afin d’avoir uniquement la zone où le vidéoprojecteur affiche dans le bac à sable. Comme c’est un rectangle dans le même sens que la caméra, il n’a pas de rotation et est dépendant de la résolution de la caméra. Nous pouvons donc manipuler sa position et ses dimensions si nous connaissons le matériel. \subsection*{BeamerResolution} -BeamerResolution permet de connaître la résolution de l’image à reconstruire et projeter. Elle est simplement constituer d’une largeur et d’une hauteur. +\textit{BeamerResolution} permet de connaître la résolution de l’image à reconstruire et projeter. Elle est simplement constituée d’une largeur et d’une hauteur. \subsection*{BeamerPosition} -BeamerPosition est la position du vidéoprojecteur en 3D basée sur la caméra en mètres. Où dans le cas de la librairie realsense 2, le point (0,0,0) représente le centre, l’axe des x positif va vers la droite, celui des y positif vers le bas et celui des z positif pointe tout droit. En sachant cela, nous pouvons, si besoin est, approximer directement la position du vidéoprojecteur par rapport à la caméra et la modifier. Les valeurs sont séparées par les trois axes et sont en float. -\url{https://dev.intelrealsense.com/docs/projection-in-intel-realsense-sdk-20#distortion-models} +\textit{BeamerPosition} est la position du vidéoprojecteur en 3D basée sur la caméra en mètres. Où dans le cas de la librairie realsense 2, le point (0,0,0) représente le centre, l’axe des x positifs va vers la droite, celui des y positifs vers le bas et celui des z positifs pointe tout droit. En sachant cela, nous pouvons, si besoin est, approximer directement la position du vidéoprojecteur par rapport à la caméra et la modifier. Les valeurs sont séparées par les trois axes et sont en float \parencite{intel_realsense_projection_2019}. + \subsection*{FrameProcessProfil} -Cette variable est la seul qui nous est utile uniquement pour l’application de calibration. Son but est de contenir les informations de la classe FramProcessProfil, car il est fastidieux de saisir ce profil à chaque calibration, si certains éléments de l’environnement où ce trouve le bac à sable ne change pas. Comme énoncé précédemment et avec des précisions : +Cette variable est la seule qui nous est utile uniquement pour l’application de calibration. Son but est de contenir les informations de la classe \textit{FramProcessProfil}, car il est fastidieux de saisir ce profil à chaque calibration, si certains éléments de l’environnement où ce trouve le bac à sable ne changent pas. Comme énoncé précédemment et avec des précisions : \begin{itemize} - \item contrast doit être supérieur à 0. - \item brightness n’a pas de restriction, sachant qu’un pixel doit contenir une valeur comprise entre 0 et 255. - \item minDistance est en pourcentage par rapport à la largeur de l’image traitée supérieur à 0. - \item cannyEdgeThreshold est compris entre 0 et 255 - \item houghAccThreshold est compris entre 0 et la largeur multiplié à la hauteur de l’image traitée - \item minRadius est en pourcentage par rapport à la largeur de l’image traitée supérieur à 0 et est plus petit ou égal à maxRadius. - \item maxRadius est en pourcentage par rapport à la largeur de l’image traitée supérieur à 0 et est plus grand ou égal à minRadius. + \item "contrast" doit être supérieur à 0. + \item "brightness" n’a pas de restriction, sachant qu’un pixel doit contenir une valeur comprise entre 0 et 255. + \item "minDistance" est en pourcentage par rapport à la largeur de l’image traitée supérieur à 0. + \item "cannyEdgeThreshold" est compris entre 0 et 255 + \item "houghAccThreshold" est compris entre 0 et la largeur multiplié à la hauteur de l’image traitée + \item "minRadius" est en pourcentage par rapport à la largeur de l’image traitée supérieur à 0 et est plus petit ou égal à maxRadius. + \item "maxRadius" est en pourcentage par rapport à la largeur de l’image traitée supérieur à 0 et est plus grand ou égal à minRadius. \end{itemize} + \section{Application de calibration} -L’application de calibration est l’application permettant de créer le fichier de configuration complet et qui se base sur la classe SandboxSetup. Comme vu précédemment dans l’architecture +L’application de calibration est l’application permettant de créer le fichier de configuration complet et qui se base sur la classe \textit{SandboxSetup}. Comme vu précédemment dans l’architecture \textit{SubApp} correspond à une étape de calibration et \textit{MainWindow} est la classe utilisant ces étapes. + \subsection*{SubApp} -Cette classe représente une étape de la calibration, soit une forme dans l’application. Elle hérite de la classe Widget de Qt, afin de permettre une insertion de la classe qui en découle d’être traitée comme un Widget. Cette classe SubApp fournit quleques fonctions permettant de la gérer comme une étape d’un processus. Elle propose donc les méthodes clés suivantes : +Cette classe représente une étape de la calibration, soit une forme dans l’application. Elle hérite de la classe Widget de Qt, afin de permettre une insertion de la classe qui en découle d’être traitée comme un Widget. Cette classe \textit{SubApp} fournit quelques fonctions permettant de la gérer comme une étape d’un processus. Elle propose donc les méthodes clés suivantes : \begin{itemize} - \item checkRoutine() : permet de vérifier si l’étape s’est bien déroulée en retourant un booléan + \item checkRoutine() : permet de vérifier si l’étape s’est bien déroulée en retournant un booléan \item valideRoutine() : permet de valider l’étape afin de passer à la suivante \item cancelRoutine() : permet d’annuler l’étape comme si celle-ci n’avait pas encore commencée \end{itemize} La classe permet aussi d’envoyer un signal avec "sendNotif" et contiendra un int comme état de l’étape en cours. Cela permet à celle-ci d’envoyer une notification d’état au parent, soit l’application de calibration qui gère les étapes. \subsection*{MainWindow} -MainWindow est la classe de notre application de calibration, c’est elle qui va regrouper et ordonner les différentes étapes afin de générer correctement le fichier de configuration final. Cette application va instancier les éléments nécessaire afin d’exécuté les étapes dans l’ordre ci-dessous. Les étapes sont directement représentées par leur classe respective héritant de SubApp. Nous avons donc une liste de SubApp exécutée dans cet ordre : +\textit{MainWindow} est la classe de notre application de calibration, c’est elle qui va regrouper et ordonner les différentes étapes afin de générer correctement le fichier de configuration final. Cette application va instancier les éléments nécessaire afin d’exécuter les étapes dans l’ordre ci-dessous. Les étapes sont directement représentées par leur classe respective héritant de \textit{SubApp}. Nous avons donc une liste de \textit{SubApp} exécutée dans cet ordre : \begin{figure}[H] \centering \includegraphics[scale=0.4]{setup_app_steps.jpg} + \caption{Ordre d'exécution des classes des étapes de calibration} + \label{fig:imp_setup_app_steps} \end{figure} Afin de naviguer entre chaque étapes avec les boutons de l’interface "précédent" et "suivant", notre classe parente va exécuter "cancelRoutine" de la forme actuelle en cas de clique de l’utilisateur sur "précédent" ou va exécuter "verifyRoutine" si le bouton "suivant" est pressé, si la méthode ne retourne rien d’anormal, "valideRoutine" est à son tour exécutée avant de passer à la forme suivante.\\ -Dans le cas où la forme actuelle à besoin d’intéragir avec MainWindow, la forme peut envoyer un signal à travers "sendNotif" qui sera lié au slot "receiveNotif" de MainWindow et ainsi envoyer l’état. +Dans le cas où la forme actuelle a besoin d’intéragir avec \textit{MainWindow}, la forme peut envoyer un signal à travers "sendNotif" qui sera lié au slot "receiveNotif" de \textit{MainWindow} et ainsi envoyer l’état. \subsection*{InitCameraGui} -Cette classe sert à vérifier la précense de la caméra et l’initialiser. Comme la routine d’initialisation est bloquante, elle est exécutée dans un thread à part. +Cette classe sert à vérifier la présence de la caméra et l’initialiser. Comme la routine d’initialisation est bloquante, elle est exécutée dans un thread à part. + \subsection*{MonitorGui} -MonitorGui permet de choisir la sortie correspondant au vidéoprojecteur. Elle utilise la librairie xrandr afin de récupérer les informations liées aux écrans connectés et leurs résolutions. De plus un apperçu de l’écran est visible lors de la sélection d’une sortie. Le but était utilisé Qt afin de récupérer les écrans et résolutions de ceux-ci. Malheureusement, Qt ne permet de récupérer que les résolutions actives des écrans actifs. En faisant des recherches, nous avons trouvé que le peu de personnes voulant accéder à ces informations sous les systèmes linux, uitilisaient xrandr, ou essayaient. La librairie offre une interface plus haut niveau, mais compatible uniquement avec Windows. Au vu du manque de documentation et du peu utilisation de la librairie sur les système linux, les utilisateurs ont tendances à executer la commande dans une console et traiter sa sortie. Comme il était fastidieux d’utiliser la librairie et que ça n’était pas une priorité, nous avons opté pour le traitement de la sortie de la console comme solution temporaire.\\ -Puis plus tard dans le développement, nous sommes revenus dessus et avons modifier le code pour qu’il utilise la librairie C. Afin de récupérer ces informations, il faut tout d’abords ouvrir une connexion avec le serveur gérant les différent écrans. Puis récupérer l’écran virtuel "screen", qui contient les informations des différentes fenêtres observant cet écran virtuel. Grâce à "screen" et ses informations, nous pouvons déterminer les sorties vidéo présentes et leurs résolution. De plus lorsqu’une sortie vidéo n’est pas connectée, elle possède une liste vide de résolution. +\textit{MonitorGui} permet de choisir la sortie correspondant au vidéoprojecteur. Elle utilise la librairie xrandr afin de récupérer les informations liées aux écrans connectés et leurs résolutions. De plus un aperçu de l’écran est visible lors de la sélection d’une sortie. Le but était d'utiliser Qt afin de récupérer les écrans et résolutions de ceux-ci. Malheureusement, Qt ne permet de récupérer que les résolutions actives des écrans actifs. En faisant des recherches, nous avons trouvé que le peu de personnes voulant accéder à ces informations sous les systèmes linux, uitilisaient xrandr, ou essayaient. La librairie offre une interface plus haut niveau, mais compatible uniquement avec Windows. Au vu du manque de documentation et du peu utilisation de la librairie sur les système linux, les utilisateurs ont tendances à exécuter la commande dans une console et traiter sa sortie. Comme il était fastidieux d’utiliser la librairie et que ça n’était pas une priorité, nous avons opté pour le traitement de la sortie de la console comme solution temporaire.\\ +Puis plus tard dans le développement, nous sommes revenus dessus et avons modifié le code pour qu’il utilise la librairie C. Afin de récupérer ces informations, il faut tout d’abord ouvrir une connexion avec le serveur gérant les différent écrans. Puis récupérer l’écran virtuel "screen", qui contient les informations des différentes fenêtres observant cet écran virtuel. Grâce à "screen" et ses informations, nous pouvons déterminer les sorties vidéo présentes et leurs résolution. De plus lorsqu’une sortie vidéo n’est pas connectée, elle possède une liste vide de résolution. + \subsection*{ProjectionGui} -Cette étape projette un écran bleu dans la sortie sélectionnée à l’étape MonitorGui. Grâce à l’aperçu de la caméra en couleur, l’utilisateur peut ajuster la position de la caméra, sa rotation, l’affichage du vidéoprojecteur et sa nettée. Il est important que la caméra soit perpendiculaire au plan au-dessus du bac à sable. +Cette étape projette un écran bleu dans la sortie sélectionnée à l’étape \textit{MonitorGui}. Grâce à l’aperçu de la caméra en couleur, l’utilisateur peut ajuster la position de la caméra, sa rotation, l’affichage du vidéoprojecteur et sa netteté. Il est important que la caméra soit perpendiculaire au plan au-dessus du bac à sable. + \subsection*{CameraFocusGui} Cette étape permet d’ajuster les paramètres de traitement d’image, afin d’améliorer la détection de notre cible. Cela nous sera utile lors de la procédure de localisation du vidéoprojecteur. Notre interface ressemble à ceci : \begin{figure}[H] \centering \includegraphics[scale=0.4]{camera_focus_app.jpg} + \caption{Interface graphique de l'application de calibration, étape d'ajustement du traitement d'images} + \label{fig:imp_camera_focus_app} \end{figure} -Tout d’abord, nous pouvons voir que nous avons deux retours vidéos. Le premier applique la méthode "editContrast" vu précédement dans la classe Beamer. Le deuxième retour montre le première retour, mais avec l’application de la fonction Canny d’OpenCV. Dans les deux cas, l’image traité est une image en niveau de gris.\\ -Ensuite obesrvons la partie interactive de notre interface. Elle est composée de barres et de saisies numériques. Tout d’abord, nous avons les paramètres de contraste "Contrast" et luminosité "Brightness" affectant notre premier rendu. -Puis nous avons les paramètres liés à la fonction HoughCircles d’OpenCV : +Tout d’abord, nous pouvons voir que nous avons deux retours vidéos. Le premier applique la méthode "editContrast" vu précédement dans la classe \textit{Beamer}. Le deuxième retour montre le premier retour, mais avec l’application de la fonction "Canny" d’OpenCV. Dans les deux cas, l’image traitée est une image en niveau de gris.\\ +Ensuite observons la partie interactive de notre interface. Elle est composée de barres et de saisies numériques. Tout d’abord, nous avons les paramètres de contraste "Contrast" et luminosité "Brightness" affectant notre premier rendu. +Puis nous avons les paramètres liés à la fonction "HoughCircles" d’OpenCV : \begin{itemize} \item Upper Canny threshold : Seuil affectant la détection de contours de la méthode Canny \item Hough accumulator threshold : Seuil déterminant un cercle dans notre accumulateur @@ -304,19 +350,21 @@ Puis nous avons les paramètres liés à la fonction HoughCircles d’OpenCV : \item Minimum circle radius... : Taille minimum du rayon du cercle lors de la détection \item Maximum circle radois... : Taille maximum du rayon du cercle lors de la détection \end{itemize} -Finalement nous avons la checkbox "Unrestricted", actuellement, les valeurs sont bloquées à un interval de valeur raisonnable pour la majorité des cas. Mais si une des échelles ne convient pas à l’utilisateur, il peut cocher "Unrestricted" afin d’avoir le choix complet sur ses valeur dans la limite de la théorie. +Finalement nous avons la checkbox "Unrestricted", actuellement, les valeurs sont bloquées à un intervalle de valeur raisonnable pour la majorité des cas. Mais si une des échelles ne convient pas à l’utilisateur, il peut cocher "Unrestricted" afin d’avoir le choix complet sur ses valeur dans la limite de la théorie. + \subsection*{CroppingMaskGui} -Cette étape permet à l’utilisateur de définir le masque de découpage de la caméra. Cette classe utilise la classe MaskEdit, elle nous permet de dessiner le masque de découpage de l’utilisateur sur le flux vidéo de la caméra. Elle est nécessaire, car Qt ne fournit pas d’évenement de dessin, le seul disponible étant celui exécutée à l’apparition de l’élément et dessine donc tout l’élément. Nous avons donc créer un composant affichant uniquement l’image de la caméra avec le masque tracer par dessus.\\ +Cette étape permet à l’utilisateur de définir le masque de découpage de la caméra. Cette classe utilise la classe \textit{MaskEdit}, elle nous permet de dessiner le masque de découpage de l’utilisateur sur le flux vidéo de la caméra. Elle est nécessaire, car Qt ne fournit pas d’évenement de dessin, le seul disponible étant celui exécuté à l’apparition de l’élément et dessine donc tout l’élément. Nous avons donc créé un composant affichant uniquement l’image de la caméra avec le masque tracé par dessus.\\ Durant cette étape, l’utilisateur peut modifier la position des coins du masque en les attrapant et déplaçant.\\ -Lors de la validation, la rotation du masque afin de le redresser est appliqué autour du coin supérieur gauche, et la matrice de rotation sauvegardée est basé sur la rotation centrée au pixel haut gauche de l’image. +Lors de la validation, la rotation du masque afin de le redresser est appliquée autour du coin supérieur gauche, et la matrice de rotation sauvegardée est basée sur la rotation centrée au pixel haut gauche de l’image. + \subsection*{BeamerLocationGui} -Cette étape est celle où déterminons la position du vidéoprojecteur. Pour ce faire, l’application est basé sur la routine énoncé dans Beamer de SandboxSetup. L’application va laisser tourner dans un autre thread l’affichage et le traitement d’image de la photo capturée par la caméra, et ainsi laisser le thread principale s’occuper de valider un point lorsque l’utilisateur clique sur le bouton "Lock". +Cette étape est celle où nous déterminons la position du vidéoprojecteur. Pour ce faire, l’application est basée sur la routine énoncée dans \textit{Beamer} de \textit{SandboxSetup}. L’application va laisser tourner dans un autre thread l’affichage et le traitement d’image de la photo capturée par la caméra, et ainsi laisser le thread principal s’occuper de valider un point lorsque l’utilisateur clique sur le bouton "Lock". \\ Dans le thread secondaire, nous suivons cette démarche : \begin{itemize} - \item récupération des images de couleur et pronfondeurs de la caméra - \item cherche les cercles dans l’image de couleur avec application du traitement sur l’image (qui utilise notre profil établi dans CameraFocusGui) - \item traitement de l’image de couleur pour l’image d’aperçu (uniquement le contrast et luminosité) + \item récupération des images de couleur et pronfondeur de la caméra + \item cherche les cercles dans l’image de couleur avec application du traitement sur l’image (qui utilise notre profil établi dans \textit{CameraFocusGui}) + \item traitement de l’image de couleur pour l’image d’aperçu (uniquement le contraste et la luminosité) \item dessine les cercles sur l’image d’aperçu \item construit l’image à projeter avec la croix \item affiche l’image d’aperçu et projette la croix @@ -328,5 +376,6 @@ Dans le thread principal, nous avons la méthode de validation d’un point : \item fini la routine s’il y a assez de droite \item approxime la position du vidéoprojecteur à partir des droites estimées \end{itemize} + \subsection*{SaveConfigGui} -Cette dernière étape sauvegarde la configuration actuelle dans un fichier de configuration à l’endroit où l’appplication est exécutée. Elle affiche un message indiquant si la configuration a bien été sauvé. +Cette dernière étape sauvegarde la configuration actuelle dans un fichier de configuration à l’endroit où l’appplication est exécutée. Elle affiche un message indiquant si la configuration a bien été sauvée. diff --git a/memoire/chapters/content/intro.tex b/memoire/chapters/content/intro.tex index 2324f0a6f99b93454b26d3272e3ce94c21e0bfc5..6bfebf3037482d4549287b34aa5153b8fc61ca08 100644 --- a/memoire/chapters/content/intro.tex +++ b/memoire/chapters/content/intro.tex @@ -1,37 +1,46 @@ % !TeX spellcheck = fr_FR \chapter{Introduction} -\section{Contexte} -Les architectes et paysagistes doivent produire des maquettes afin de concrétiser leurs plans. Malheureusement ces maquettes basées sur divers matériaux comme le bois ou le carton, font de celles-ci des maquettes difficilement ajustable en cas de modifications souhaitées. + +\section{Contexte et problématique} +Les architectes paysagistes doivent produire des maquettes physiques de terrains afin de concrétiser leurs projets d'aménagement de territoire. Malheureusement ces maquettes basées sur divers matériaux comme le bois ou le carton, font de celles-ci des maquettes difficilement ajustables en cas de modifications souhaitées. + \begin{figure}[H] \centering \includegraphics[scale=0.2]{maquetteNiveaux.jpg} - \caption{maquette de niveaux, \url{https://www.figurasfondo.fr/maquette-darchitecture-en-carton-gris/}} + \caption{Maquette de terrains en carton. Source : tiré de www.figurasfondo.fr, ref. URL01} \label{fig:intro_maquetteNiveaux} \end{figure} -En conséquence ils doivent recommencer leur maquette à chaque modifications majeurs de leur plan. Ce manque de flexibilité lors de la moindre modification ne leur permet pas de visualiser rapidement différents plans et nécessite un travail mûrement réfléchi en amont.\\ -Cependant, un projet de bac à sable en réalité augmentée a été réalisé par l'université de Californie à Davis. Celui-ci est composé d'une caméra Microsoft Kinect 3D, d'un vidéoprojecteur et d'un bac rempli de sable. De plus, le projet propose des applications permettant l'interaction avec celui-ci, comme celle d'affichage des courbes de niveaux, ou de simulation de cours d'eau sur une topologie.\\ +En conséquence ils doivent recommencer leur maquette à chaque modification majeure de leur plan. Ce manque de flexibilité lors de la moindre modification ne leur permet pas de visualiser rapidement différents plans et nécessite un travail mûrement réfléchi en amont.\\ + + + +\section{Solutions envisagées et objectifs} +Afin de résoudre ce problème d'adaptation de terrains, nous allons réaliser un bac à sable de réalité augmentée qui permettra de modéliser les terrains des architectes paysagistes avec différentes applications de réalité augmentée. \begin{figure}[H] \centering - \includegraphics[scale=0.3]{uclaSandboxWater.jpg} - \caption{UCLA démo bac à sable avec simulutation d'eau, \url{https://arsandbox.ucdavis.edu/}} - \label{fig:intro_uclaSandboxWater} + \includegraphics[scale=0.6]{uclaSandboxLevels.jpg} + \caption{Bac à sable de réalité augmentée de \gls{ucdavis}. Source : tiré de arsandbox.ucdavis.edu, ref. URL02} + \label{fig:intro_maquetteNiveaux} \end{figure} +Notre bac à sable de réalité augmentée fonctionnant à l'aide d'une caméra de profondeur, ainsi qu'un beamer, devra permettre d'être flexbile sur le choix de ces composants et permettra ainsi le suivi de l'évolution de ces technologies. De plus, cette flexibilité implique qu'une adaptation dépendant de l'infrastructure devra être effectuée lors de l'utilisation du bac. + -Ainsi, grâce à ce concept, nous pourrions développer des applications plus complexes, qui serviraient d'outils de modélisation aux architectes et paysagistes. +\section{Résumé du travail réalisé, méthodologie et annonce du plan du rapport} +Sur la base de l'infrastructure présente à HEPIA, nous avons produit une librairie permettant d'utiliser le bac à sable de réalité augmentée, ainsi qu'une application de calibration basée sur celle-ci et permettant la sauvegarde de la configuration. Enfin, une application de démonstration a été développée aussi basée sur la librairie.\\ +La librairie et les applications sont disponibles sur les gits suivants : -\section{Problématique} -Bien que l'université de Californie à Davis propose ce projet, il est impossible en l'état de développer d'autres applications basées sur celui-ci, car le projet fournit directement les applications. Le but étant d'utiliser le bac à sable, afin de créer des applications pouvant répondre aux besoins des architectes et paysagistes. +\begin{itemize} + \item Librairie : \url{https://githepia.hesge.ch/ar_sandbox/ar_sandbox_lib} + \item Applications : \url{https://githepia.hesge.ch/ar_sandbox/ar_sandbox_app}\\ +\end{itemize} -\section{Solution envisagée et objectifs} -Afin de pouvoir réaliser ces applications, il faudra tout d'abord réaliser une librairie permettant l'utilisation de l'infrastructure mise en place. De plus, comme chaque installation peu légèrement différer, une application de calibration sera nécessaire, afin de faciliter sa configuration. +Lors de ce projet, nous avons été surpris par la crise du COVID-19, ce qui nous a forcé à pratiquer le travail à domicile. Or ce projet nécessitant de développer en présence du bac à sable, il nous a fallu trouver une alternative. En bricolant un bac à sable fait maison et à l'aide des réunions hebdomadaires, nous avons pu continuer le développement du projet. Le développement de notre application de calibration sur ce prototype et les tests effectués sur le bac présent à l'HEPIA en fin de crise ont démontrés la flexibilité qu'apportait l'application de calibration.\\ +Dans ce document, nous verrons au chapitre 2 une analyse de l'existant, puis une description du dispositif et les problèmes géométriques. Ensuite nous verrons les besoins et fonctionnalités au chapitre 4, suivi de l'architecture logicielle au chaptire 5 et les technologies et outils au chaptire 6. Enfin nous verrons la conception et l'implémentation et terminerons avec les tests et résultats au chapitre 8 et la conslusion au chapitre 9. -\section{Résumé du travail réalisé, méthodologie et annonce du plan du rapport} -Lors de ce projet, nous avons fait une refonte de la librairie, afin de fournir une librairie utilisateur, qui sera utilisée lors du développement d'applications utilisant le bac de réalité augmentée, ainsi qu'une librairie de calibration permettant la création d'application de calibration du bac. Grâce à cette librairie de calibration, nous avons pu développer une application permettant la configuration du bac, ainsi que la sauvegarde de cette configuration dans un fichier afin qu'elle soit persistante. -Dans ce document, nous allons voir tout d'abord à quoi ressemble le bac de réalité augmentée, puis les problématiques géométriques liées à l'utilisation de l'infrastructure, suivi d'une brève comparaison avec d'autres projets similaires. Puis nous verrons les besoins du projet, l'architecture global de notre solution et les technologies utilisées pour y parvenir. Finalement nous verrons la conception et implémentation détaillés du projet, ainsi que les tests et résultat avant de finir par notre conclusion. diff --git a/memoire/chapters/content/resultats.tex b/memoire/chapters/content/resultats.tex index 4963e5b96a60de55c074bf095805e9b511b8d518..b0a7b92cc13a8baccf1e7d3d21f74e9bd049ce5c 100644 --- a/memoire/chapters/content/resultats.tex +++ b/memoire/chapters/content/resultats.tex @@ -1,29 +1,75 @@ - +% !TeX spellcheck = fr_FR \chapter{Tests et résultats} \section{Optimisation} -La librairie fonctionne, mais elle souffre de mauvaise performances, c’est pourquoi le but est d’entâmer une amélioration de celles-ci. Pour ce faire, nous avons utilisé des outils de profiling, afin de localiser les zones à améliorer. Tout d’abords nous avons commencé à utiliser Valgrind, car son interface permettait de lire les données graphiquement, contrairement à Gprof qui retourne les informations dans la console. Ensuite en analysant les données retournées par Valgrind, nous nous voulions voir si les conclusions tirées d’un outil de profiling s’appliquaient pour tout outils. Nous avons donc testé avec Gperftools, qui est un autre outil graphique de profiling. Nous avons remarqué que les deux nous donnaient différents retours, mais que certaines informations étaient quand même redondantes. Enfin en testant avec Gprof, nous avons aussi remarqué qu’une fonction se démarquaient des autres. Cette fonction permettait de reconstruire l’image lors de que la fonction d’ajustement de l’image projetée resortait, plus précisément à cause du parcours de chaque pixel qu'elle effectue pour ajuster les valeurs de la sortie.\\ -L’idée de paralléliser le traitement de l'image était alors concevable, mais pas raisonnable pour le moment, car il fallait s’assurer que le code était bien optimisé sur CPU, avant de l’adapter sur GPU. Donc nous avons décidée d’améliorer le code existant.\\ -Pour ce faire, nous nous sommes atardés sur la gestion de la mémoire des buffers utilisées lors d’une utilisation standard de la librairie. C’est à dire, récupération d’une image de couleur ou profondeur, puis ajustement de l’image projetée. En ce qui concerne la caméra, nous avons limité les buffers à la capture des images couleurs et profondeurs (avec chacunes leur buffer) et le retour d’une copie de ces buffers lors de la récupération de ces images.\\ +La librairie fonctionne, mais elle souffre de mauvaises performances, c’est pourquoi le but est d’entamer une amélioration de celles-ci. Pour ce faire, nous avons utilisé des outils de profiling, afin de localiser les zones à améliorer. Tout d’abords nous avons commencé à utiliser Valgrind, car son interface permettait de lire les données graphiquement, contrairement à Gprof qui retourne les informations dans la console. Ensuite en analysant les données retournées par Valgrind, nous voulions voir si les conclusions tirées d’un outil de profiling s’appliquaient pour tout outils. Nous avons donc testé avec Gperftools, qui est un autre outil graphique de profiling. Nous avons remarqué que les deux nous donnaient différents retours, mais que certaines informations étaient quand même redondantes. Enfin en testant avec Gprof, nous avons aussi remarqué qu’une fonction se démarquait des autres. Cette fonction permettait de reconstruire l’image lors de que la fonction d’ajustement de l’image projetée ressortait, plus précisément à cause du parcours de chaque pixel qu'elle effectue pour ajuster les valeurs de la sortie.\\ +L’idée de paralléliser le traitement de l'image était alors concevable, mais pas raisonnable pour le moment, car il fallait s’assurer que le code était bien optimisé sur \gls{cpu}, avant de l’adapter sur \gls{gpu}. Donc nous avons décidé d’améliorer le code existant.\\ +Pour ce faire, nous nous sommes attardés sur la gestion de la mémoire des buffers utilisés lors d’une utilisation standard de la librairie. C’est à dire, récupération d’une image de couleur ou profondeur, puis ajustement de l’image projetée. En ce qui concerne la caméra, nous avons limité les buffers à la capture des images couleur et profondeur (avec chacune leur buffer) et le retour d’une copie de ces buffers lors de la récupération de ces images.\\ Puis lors de l’ajustement de l’image, nous gardons en mémoire les buffers utilisés dans la fonction. C’est à dire celui contenant l’image de sortie et les quatres autres utilisés dans la fonction d’ajustement. Ce qui nous fait cinqs zones mémoires de la taille de l’image de sortie. Enfin une copie est faite de l’image de sortie, ce qui nous rajoute un buffer.\\ -Lors de l’analyse avec Gperftools, nous avons eu ce graphique : +Lors de l’analyse avec Gperftools, nous avons obtenu un graphique (disponible en annexe). +Nous sommes mitigés face à ce graphique, car nous avons des informations qui parraissent cohérentes, mais nous avons aussi l’inverse, comme le fait que la fonction "HoughCircle" soit appelé lors d’une redimension d’une matrice. +\begin{figure}[H] + \centering + \includegraphics[scale=0.9]{gperftools_graph_houghcircle.jpg} + \caption{Temps passé dans HoughCircle lors de l'exécution du programme utilisateur} + \label{fig:res_gperftools_graph_houghcircle} +\end{figure} +Alors que cette function ne devrait pas être appelée, le programme a passé quand même 279 "tick" sur les 1875 totaux dans cette fonction. +Toutefois, le fait que le filtre spatial de la librairie realsense prenne une place aussi importante lors de l’exécution est tout à fait envisageable. +\begin{figure}[H] + \centering + \includegraphics[scale=0.8]{gperftools_graph_filter.jpg} + \caption{Temps passée dans spatial filter lors de l'exécution du programme utilisateur} + \label{fig:res_gperftools_graph_filter_spatial} +\end{figure} +On remarque qu'elle a un compteur à 607, soit 26\% du temps d'exécution totale. De plus nous voyons aussi que la méthode "copyPixelsInto" se démarque de la majorité. \begin{figure}[H] \centering - \includegraphics[scale=0.3]{gperftools_grpah.jpg} + \includegraphics[scale=0.9]{gperftools_graph_copypixels.jpg} + \caption{Temps passée dans copyPixelsInto lors de l'exécution du programme utilisateur} + \label{fig:res_gperftools_graph_copypixels} \end{figure} -Nous sommes mitigé face à ce graphique, car nous avons des informations qui parraissent cohérentes, mais nous avons aussi l’inverse, comme le fait que la fonction HoughCircle soit appelé lors d’une redimension d’une matrice. Toute fois, le fait que le filtre spatial de la librairie realsense prenne une place aussi importante lors de l’execution est tout à fait envisageable. De plus nous voyons aussi que la méthode copyPixelsInto prends du temps. Cependant, comme nous avons décidé de simplifier le code, cette méthode n’existe plus et ce graphique est donc moyennement représentatif de l’exécution standard de la librairie. Comme le temps manquait, nous n’avons pu aller plus loin dans l’optimisation. -\section{Tests} -Nous avons testé les points clé de la librairie. Tout d’abord nous avons testé la précision de la librairie en utilisant l’application de courbe de niveau sur un terrain plat et en creusant des trous comme s’il s’agissait d’une grille. Comme la librairie précédente perdait en précision dans les bords, nous avons vérifié que s’il y avait une erreur, qu’elle ne s’accentutait pas avec l’éloignement du centre. Le test était positif et la seul marge d’erreur présente était lié à l’approximation de la position du vidéoprojecteur dans la configuration.\\ -Ensuite, nous avons testé la résolution des images projetées, car auparavant, la résolution de l’image projetée dépendait de la résolution de la caméra. Pour testé nous avons simplement afficher une image de haute résolution et le résultat était positif.\\ -Finalement, nous voulions testé le gain de performance lié à l’optimisation de la mémoire. Pour ce faire, nous avons calculé le temps d’initialisation de nos variables. Malheureusement, l’allocation ne dépassait que rarement 0 milisecondes sans l’optimisation et ne dépassait pas 0 avec. +Enfin, nous voyons que 21\% du temps d'exécution est passé dans la fonction et ses sous-appels de fonction, dont un peu plus de la moitié directement dans "copyPixelsInto". +Cependant, comme nous avons décidé de simplifier le code, cette méthode n’existe plus et ce graphique est donc moyennement représentatif de l’exécution standard de la librairie. Comme le temps manquait, nous n’avons pu aller plus loin dans l’optimisation. + +\section{Tests et résultats} +Nous avons testé les points clé de la librairie. Tout d’abord nous avons testé la précision de la librairie en utilisant l’application de coloration de niveau sur un terrain plat et en creusant des trous comme s’il s’agissait d’une grille. Nous avons vérifié que seule la marge d'erreur notable était liée à l'approximation de la position du vidéoprojecteur dans la configuration.\\ +Ensuite, nous avons vérifié la résolution des images projetées, en s'assurant qu'elle ne dépendait pas de la résolution de la caméra. Pour tester nous avons simplement affiché une image de haute résolution et le résultat était positif.\\ +Puis, nous voulions tester le gain de performance lié à l’optimisation de la mémoire. Pour ce faire, nous avons calculé le temps d’initialisation de nos variables. Malheureusement, l’allocation atteignait que rarement 1 miliseconde sans l’optimisation et jamais avec.\\ +Enfin, nous avons fait une application C++ de tests de performance, calculant le temps passé sur chaque fonctions principales utilisées dans une exécution standard et répétée d'une application. En répétant ces opérations un nombre de fois prédéfini, les temps sont enregsitrés dans un fichier et peuvent être lus par une application python qui indiquera le temps moyen passé dans chacune des fonctions et le nombre d'images par seconde moyen.\\ +Temps moyen en milisecondes : + +\begin{table} +\begin{center} +\begin{tabular}{ |m{5em}|m{5em}|m{5em}|m{5em}|m{5em}|m{5em}| } + \hline + Version & Capture & récupère l'image de profondeur & récupère l'image de couleur & Ajuste l'image à projeter & moyenne d'IPS \\ + \hline + basse qualité et imprécis & 18.37 & 0.06 & 0.05 & 84.61 & 9.7\\ + \hline + moyenne qualité et précis & 15.06 & 0.12 & 0.01 & 57.6 & 13.74\\ + \hline + bonne qualité et précis & 14.76 & 0.31 & 0.11 & 210.25 & 4.44\\ + \hline +\end{tabular} +\end{center} +\caption{Résultats des tests d'exécution de l'application de tests} +\label{tab:res_test_execution_lib} +\end{table} + +Dans ce tableau, nous pouvons voir que la première version avait 9 images par secondes en moyenne, car la correction de la précision et d'autres facteurs ont permis d'accélérer le processus global, notamment celui de l'ajustement de l'image. Mais ce qui est impressionant, c'est l'augmentation du temps de traitement entre la deuxième version et la troisième. Ce changement est dû à l'image de profondeur utilisée afin d'adapter l'image, dans le deuxième version, la résolution de l'image de profondeur est propre à la caméra de profondeur, mais dans la dernière version elle est ajustée à la résolution de l'image à projeter, soit 1400x1050 dans cette série de test. Les moyennes présentes dans ce tableau sont tirés d'un échantillonnage de 200 images projetées. + + \section{Utilisation} -La librairie généré par le Makefile retourne un fichier "libsandbox.so", qu’il va falloir inclure dans les projets C++. Pour ce faire, il faudra indiquer le chemin des en-têtes de fichiers lors de la compilation et indiquer le chemin vers le fichier .so lors du lien entre les librairies.\\ -De plus, pour pouvoir exécuter l’application de calibration, il faudra indiquer à la console où trouver le fichier .so nécessaire à l’exécution de l’application. Pour ce faire, il suffit de sauvegarder le chemin vers le fichier .so dans la variable d’environnement LD-LIBRARY-PATH.\\ +La librairie générée par le Makefile retourne un fichier "libsandbox.so", qu’il va falloir inclure dans les projets C++. Pour ce faire, il faudra indiquer le chemin des en-têtes de fichiers lors de la compilation et indiquer le chemin vers le fichier .so lors du lien entre les librairies.\\ +De plus, pour pouvoir exécuter l’application de calibration, il faudra indiquer à la console où trouver le fichier .so nécessaire à l’exécution de l’application. Pour ce faire, il suffit de sauvegarder le chemin vers le fichier .so dans la variable d’environnement \texttt{LD\_LIBRARY\_PATH}.\\ Une fois la calibration faite, l’application utilisateur devra respecter cette routine, afin de s’assurer du bon fonctionnement de la librairie. \begin{figure}[H] \centering \includegraphics[scale=0.5]{sandbox_activity_diagram.jpg} + \caption{Routine d'exécution d'un programme utilisateur} + \label{fig:res_sandbox_activity_diagram} \end{figure} -Nous avons l’initialisation qui permet de vérifier que les compsants physique soit disponible. Puis le chargement de la configuration. Une fois tout validé, l’application utilisateur pourra s’exécuter. +Nous avons l’initialisation qui permet de vérifier que les composants physiques soient disponibles. Puis le chargement de la configuration. Une fois tout validé, l’application utilisateur pourra s’exécuter. diff --git a/memoire/chapters/content/technologies.tex b/memoire/chapters/content/technologies.tex index 812ac7dd18ccdc4fc05a2886f15a1acb4c83364c..f2d19fe73e01b6c9fad3651f5414292f4e358bd0 100644 --- a/memoire/chapters/content/technologies.tex +++ b/memoire/chapters/content/technologies.tex @@ -1,19 +1,33 @@ \chapter{Technologies et outils} -\begin{itemize} - \item C++ : 11.0 - \item g++ : 7.5.0 - \item OpenCV : 3.2.0 - \item realsense 2 : 2.35.2 - \item yaml-cpp : \url{https://github.com/jbeder/yaml-cpp} - \item Qt : 5.9.5 - \item Profiling - \begin{itemize} - \item Valgrind - \item Gprof - \item Gperftools - \end{itemize} - -\end{itemize} +Le projet est basé le language C++. Ainsi que d'autres librairies et framework. + +\section{OpenCV} +Nous avons utilisé OpenCV (Open Source Computer Vision Library) qui est une librairie "spécialisée dans le traitement d'images en temps réel" \parencite{noauthor_opencv_2020-1}. + +\section{RealSense 2} +La librairie realsense 2 est une librairie multi-plateforme développée par Intel RealSense et permettant l'utilisation des ses caméras de profondeurs. + +\section{yaml-cpp} +"yaml-cpp" est une librairie de lecture et d'écriture de fichier YAML ecrite en C++ par Jesse Beder. + +\section{Qt} +"Qt" est un framework C++ permettant la création d'application graphique principalement, mais offre aussi d'autres éléments liés aux connexions réseaux, multi-threading ou d'accès aux données \parencite{noauthor_qt_2020}. + +\section{XrandR} +"XrandR" est une librairie C permettant de récupérer les informations des sorties vidéos et de les modifier \parencite{noauthor_libxrandr_nodate}. + +\section{Profiling} +Lors du projet, nous avons dû utiliser des outils de profiling afin de détecter les potentiels goulets d'étranglement. Les outils ci-dessous proposeront tous d'indiquer des informations après exécution du programme. Ces informations seront principalement basées sur l'arborescence d'appels de fonctions que créera le programme à son exécution, ainsi que les "coûts" de ces fonctions, qui représente une unité de temps, mais qui peut varier en fonction de l'outil. + +\subsection*{Gprof} +"Gprof" \parencite{noauthor_gprof_2016} un outil de profiling qui permet de récupérer les informations liées au temps d'exécution d'un code dans un fichier et de les afficher dans le terminal. Il suffit d'ajouter \textit{-pg} lors de la compilation des fichiers pour générer un fichier \textit{gmon.out} à l'exécution du programme. + +\subsection*{Valgrind} +"Valgrind" \parencite{valgrind_developpers_valgrind_nodate} un autre outil de profiling, qui permet lui aussi de générer un fichier contenant les informations d'exécution. Il est notamment utilisé avec l'outil graphique Callgrind, qui permettra d'avoir une meilleure compréhension visuelle du cours de l'exécution du programme et de l'arborescence d'appels de fonctions. + +\subsection*{Gperftools} +"Gperftools" \parencite{sanjay_ghemawat_gperftools_2008} l'outil de profiling utilisé par Google. Il permet aussi d'afficher une arborescence d'appels de fonctions, mais celui-ci est complet, contrairement à Callgrind qui n'affiche qu'une partie. + diff --git a/memoire/chapters/figureslist.tex b/memoire/chapters/figureslist.tex index 32c4088ef6986a64dc25de9d39986a9f8d7fd85b..5864a152a8eb27357e52d7ce6dcefc7caaa425a8 100644 --- a/memoire/chapters/figureslist.tex +++ b/memoire/chapters/figureslist.tex @@ -6,8 +6,18 @@ \paragraph{Références des URL} \begin{itemize} -\item URL01 \href{ce-site.ch/bla/bli/blo/blou.html}{ce-site.ch/bla/bli/blo/blou.html} -\item URL03 \href{ce-site.ch/blou/bli/bla.html}{ce-site.ch/blou/bli/bla.html} -\item URL04 \href{https://commons.wikimedia.org/w/index.php?curid=906980}{https://commons.wikimedia.org/w/index.php?curid=906980} -\item URL06 \href{ce-site.ch/monrapportdestage.pdf}{ce-site.ch/monrapportdestage.pdf} -\end{itemize} \ No newline at end of file +\item URL01 \href{https://www.figurasfondo.fr/maquette-darchitecture-en-carton-gris/}{https://www.figurasfondo.fr/maquette-darchitecture-en-carton-gris/} + +\item URL02 \href{https://arsandbox.ucdavis.edu/}{https://arsandbox.ucdavis.edu/} + +\item URL03 \href{https://arsandbox.ucdavis.edu/instructions/hardware-2/}{https://arsandbox.ucdavis.edu/instructions/hardware-2/} + +\item URL04 \href{https://fr.wikipedia.org/wiki/Kinect}{https://fr.wikipedia.org/wiki/Kinect} + +\item URL06 \href{https://isandbox.co.uk/software/}{https://isandbox.co.uk/software/} + +\item URL08 \href{https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/warp_affine/warp_affine.html}{\texttt{https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/warp\_affine/warp\_affine.html}} + +\item URL09 \href{https://docs.opencv.org/2.4/modules/imgproc/doc/geometric_transformations.html?highlight=warpaffine#warpaffine}{\texttt{https://docs.opencv.org/2.4/modules/imgproc/doc/geometric\_transformations.html?highlight=warpaffine\#warpaffine}} + +\end{itemize} diff --git a/memoire/chapters/references.tex b/memoire/chapters/references.tex index cb30ac71e91dfb105ced516dad65bed5c08d6f34..ae6818b3f95c5c3de7f390b4b6bccd0e22f0233e 100644 --- a/memoire/chapters/references.tex +++ b/memoire/chapters/references.tex @@ -1,7 +1,3 @@ % !TeX spellcheck = fr_FR -\chapter*{Références documentaires} -\addcontentsline{toc}{chapter}{Références documentaires} % Adding toc entry - -\noindent\textit{Sites Web consultés – Code repris d’ailleurs – Notices techniques – Articles de presse – Ouvrage imprimés – Ouvrages électroniques – Chapitre dans un ouvrage imprimé – Rapports imprimés – Travaux universitaires – Articles de revues imprimés – Articles de périodiques électroniques – Communication dans un congrès. Pour chacun de ces types de document, les mise en forme sont dans le document « Méthode de citation et de rédaction d’une bibliographie ».}\\ - -\textit{Afin de gagner du temps, pensez à utiliser le logiciel de gestion bibliographique Zotero (et/ou BibTeX si vous utilisez LaTeX) pour la mise en forme et l’édition automatique de vos références à la norme ISO690.} \ No newline at end of file +\nocite{*} +\printbibliography[title={Références documentaires},heading=bibintoc] diff --git a/memoire/chapters/statements.tex b/memoire/chapters/statements.tex index b436868c5e08358159956f680d2aad561fdad06f..c5a04b7e3ba1a74b14b23b0d4005fa2ca96d0b38 100644 --- a/memoire/chapters/statements.tex +++ b/memoire/chapters/statements.tex @@ -4,7 +4,7 @@ \addcontentsline{toc}{chapter}{Énoncé du sujet} % Adding toc entry \thispagestyle{noheader} -\begin{figure}[tbph!] +\begin{figure}[H] \centering \includegraphics[scale=0.7]{fanetti_enonce_dipl_2020.jpg} \end{figure} diff --git a/memoire/chapters/tableslist.tex b/memoire/chapters/tableslist.tex index 1a6182416823ee65577fc633613377a97e206a2b..24a4c949d92366b52820d39a14d81b80030a05ba 100644 --- a/memoire/chapters/tableslist.tex +++ b/memoire/chapters/tableslist.tex @@ -3,15 +3,12 @@ \listoftables \addcontentsline{toc}{chapter}{\listtablename} % Adding toc entry -\vspace*{14.4pt} +\paragraph{Références des URL} -\textit{N.B. Si vous avez peu de tableaux, vous pouvez les intégrer à la table des illustrations.} +\begin{itemize} -\vspace*{14.4pt} +\item URL05 \href{https://www.researchgate.net/figure/Comparative-specifications-of-Microsoft-Kinect-v1-and-v2_tbl1_313333776}{\texttt{https://www.researchgate.net/figure/Comparative-specifications-of-Microsoft-Kinect-v1-and-v2\_tbl1\_313333776}} -\paragraph{Références des URL} +\item URL07 \href{https://www.intelrealsense.com/stereo-depth/}{https://www.intelrealsense.com/stereo-depth/} -\begin{itemize} -\item URL02 \href{ce-site.ch/bli/bla/blo/blou}{ce-site.ch/bli/bla/blo/blou} -\item URL05 \href{ce-site.ch/publications/documents/rapports/rapportsdestage/monrapportdestage.pdf}{ce-site.ch/publications/documents/rapports/rapportsdestage/monrapportdestage.pdf} -\end{itemize} \ No newline at end of file +\end{itemize} diff --git a/memoire/figures/ARSandboxLayout.jpg b/memoire/figures/ARSandboxLayout.jpg index abb2164216ae9005f32c2ec417745147e4d56eff..02a4bb090869c557d510e41391c7e768cd15a4c5 100644 Binary files a/memoire/figures/ARSandboxLayout.jpg and b/memoire/figures/ARSandboxLayout.jpg differ diff --git a/memoire/figures/archi_sandbox_api.jpg b/memoire/figures/archi_sandbox_api.jpg index 7631199f5481815b1e35d9248d7bf53a8a66cf12..f0799d1b55391843b46a5138869d37ba91838fd0 100644 Binary files a/memoire/figures/archi_sandbox_api.jpg and b/memoire/figures/archi_sandbox_api.jpg differ diff --git a/memoire/figures/archi_setup_app.jpg b/memoire/figures/archi_setup_app.jpg deleted file mode 100644 index ebd9e4f84a6ca88076c3b98b642e4f4d777553c3..0000000000000000000000000000000000000000 Binary files a/memoire/figures/archi_setup_app.jpg and /dev/null differ diff --git a/memoire/figures/archi_setup_app_complet.jpg b/memoire/figures/archi_setup_app_complet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5ac891fceed2ae5e8d10e8386ac7f7d1cef32345 Binary files /dev/null and b/memoire/figures/archi_setup_app_complet.jpg differ diff --git a/memoire/figures/archi_setup_app_main.jpg b/memoire/figures/archi_setup_app_main.jpg new file mode 100644 index 0000000000000000000000000000000000000000..dfef32b2674ed621f594fdbe2288f02c824454bc Binary files /dev/null and b/memoire/figures/archi_setup_app_main.jpg differ diff --git a/memoire/figures/camera_zones.jpg b/memoire/figures/camera_zones.jpg index 47316af53878495618217e5a570167f3cce5e142..cbc36f98b7ed4a57685d2e2b26b446da230c98ba 100644 Binary files a/memoire/figures/camera_zones.jpg and b/memoire/figures/camera_zones.jpg differ diff --git a/memoire/figures/dispositif_sandbox.jpg b/memoire/figures/dispositif_sandbox.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1d23e753f1444dd30ef1feb823c4ddf39e7cd4b9 Binary files /dev/null and b/memoire/figures/dispositif_sandbox.jpg differ diff --git a/memoire/figures/exemple_code_display_levels.png b/memoire/figures/exemple_code_display_levels.png new file mode 100644 index 0000000000000000000000000000000000000000..59017e73a110f6f19883e195dbf1c5653efb4400 Binary files /dev/null and b/memoire/figures/exemple_code_display_levels.png differ diff --git a/memoire/figures/exemple_code_main.png b/memoire/figures/exemple_code_main.png new file mode 100644 index 0000000000000000000000000000000000000000..902bc294e4a018e4899284c39b2d919aa9520bf5 Binary files /dev/null and b/memoire/figures/exemple_code_main.png differ diff --git a/memoire/figures/gperftools_grpah.jpg b/memoire/figures/gperftools_graph.jpg similarity index 100% rename from memoire/figures/gperftools_grpah.jpg rename to memoire/figures/gperftools_graph.jpg diff --git a/memoire/figures/gperftools_graph_copypixels.jpg b/memoire/figures/gperftools_graph_copypixels.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b8d11f204dd9e70d13f844cda42067f3828d0eec Binary files /dev/null and b/memoire/figures/gperftools_graph_copypixels.jpg differ diff --git a/memoire/figures/gperftools_graph_filter.jpg b/memoire/figures/gperftools_graph_filter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..26eb3766295a60c341fb9295ab614a6ad7f97e76 Binary files /dev/null and b/memoire/figures/gperftools_graph_filter.jpg differ diff --git a/memoire/figures/gperftools_graph_houghcircle.jpg b/memoire/figures/gperftools_graph_houghcircle.jpg new file mode 100644 index 0000000000000000000000000000000000000000..90fac8c96184e213fc7b16fcef787c748ed58d26 Binary files /dev/null and b/memoire/figures/gperftools_graph_houghcircle.jpg differ diff --git a/memoire/figures/isandbox_ice_age.png b/memoire/figures/isandbox_ice_age.png new file mode 100644 index 0000000000000000000000000000000000000000..c501540cc828db9912a3b66f74ae566b444f300d Binary files /dev/null and b/memoire/figures/isandbox_ice_age.png differ diff --git a/memoire/figures/isandbox_volcan.png b/memoire/figures/isandbox_volcan.png new file mode 100644 index 0000000000000000000000000000000000000000..a490b9ccee7eed84781333a5b44c5db36ca12a64 Binary files /dev/null and b/memoire/figures/isandbox_volcan.png differ diff --git a/memoire/figures/kinect_v1.png b/memoire/figures/kinect_v1.png new file mode 100644 index 0000000000000000000000000000000000000000..e8912366572b2325e55a314837ccdc010abc9c39 Binary files /dev/null and b/memoire/figures/kinect_v1.png differ diff --git a/memoire/figures/resume.jpg b/memoire/figures/resume.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e8f298d6389ef292fd6a299b108da8ad720ec1c9 Binary files /dev/null and b/memoire/figures/resume.jpg differ diff --git a/memoire/figures/rotation.jpg b/memoire/figures/rotation.jpg index e0b29d756567f03b6395951576058f2c64b1a443..2346afaf8199e187e55826da29cf11c38fa3071b 100644 Binary files a/memoire/figures/rotation.jpg and b/memoire/figures/rotation.jpg differ diff --git a/memoire/figures/sandbox_activity_diagram.jpg b/memoire/figures/sandbox_activity_diagram.jpg index 6db8ecccc22c895fe1a976a3c1f69924aa1cf087..0c51dc8f1208528b5048614c81b8ab3df09cf016 100644 Binary files a/memoire/figures/sandbox_activity_diagram.jpg and b/memoire/figures/sandbox_activity_diagram.jpg differ diff --git a/memoire/figures/ucdavis_world.jpg b/memoire/figures/ucdavis_world.jpg new file mode 100644 index 0000000000000000000000000000000000000000..835363699183cb2166680f29a49a8f163b1c790c Binary files /dev/null and b/memoire/figures/ucdavis_world.jpg differ diff --git a/memoire/figures/uclaSandboxLevels.jpg b/memoire/figures/uclaSandboxLevels.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f76de775026d157bda489a82e52ae52948dd2864 Binary files /dev/null and b/memoire/figures/uclaSandboxLevels.jpg differ diff --git a/memoire/figures/valgrind.png b/memoire/figures/valgrind.png new file mode 100644 index 0000000000000000000000000000000000000000..2318088de470a093ed7438f09b27cee36bb0e276 Binary files /dev/null and b/memoire/figures/valgrind.png differ diff --git a/memoire/glossary/acronyms.tex b/memoire/glossary/acronyms.tex index a89563607474c32154284d9358fe28abf5fbaa31..b3cc7fe7ab94cdb74f6ae1714a57b07664ea482d 100644 --- a/memoire/glossary/acronyms.tex +++ b/memoire/glossary/acronyms.tex @@ -1,4 +1,7 @@ % Acronym definitions -\newacronym{utc}{UTC}{Coordinated Universal Time} -\newacronym{adt}{ADT}{Atlantic Daylight Time} -\newacronym{est}{EST}{Eastern Standard Time} \ No newline at end of file +\newacronym{api}{API}{Application Programming Interface} +\newacronym{ucdavis}{UC Davis}{Université de Californie à Davis} +\newacronym{ucla}{UCLA}{Université de Californie à Los Angeles} +\newacronym{gpu}{GPU}{Graphics Processing Unit} +\newacronym{cpu}{CPU}{Central Processing Unit} + diff --git a/memoire/memoire_fanetti_simon.pdf b/memoire/memoire_fanetti_simon.pdf deleted file mode 100644 index 5ea4989643a9445725cfa8e0343fad12c80139ec..0000000000000000000000000000000000000000 Binary files a/memoire/memoire_fanetti_simon.pdf and /dev/null differ