Bibliothèque de traitements d'images en virgule flottante.
http://la.buvette.org/photos/cumul/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
465 lines
15 KiB
465 lines
15 KiB
\documentclass[a4paper,10pt]{article} |
|
|
|
% \listfiles % pour le debug |
|
|
|
\usepackage[french]{babel} |
|
\usepackage[utf8]{inputenc} |
|
\usepackage[T1]{fontenc} |
|
% XXX \usepackage{lipsum} |
|
\usepackage{makeidx} |
|
\usepackage{listings} |
|
\usepackage{babel} |
|
|
|
\usepackage{pifont} % caractères rigolos |
|
\usepackage{enumitem} |
|
\setitemize[1]{label={\ding{82}}} |
|
\frenchbsetup{CompactItemize=false} |
|
|
|
% \usepackage{color} |
|
% \usepackage{url} |
|
\usepackage{xspace} |
|
\usepackage[verbose]{layout} |
|
|
|
\makeindex |
|
% ------------------------------------------------------------------- |
|
\title{Floating images processing} |
|
\author{tTh} |
|
|
|
\begin{document} |
|
\maketitle |
|
|
|
\section{Image flottante ?} |
|
|
|
Mais de quoi parle-t-on exactement ? |
|
\vspace{1em} |
|
|
|
Traditionnellement, les valeurs des pixels dans les images |
|
informatiques sont mémorisées sur 8 bits, un octet\index{octet}, |
|
soit 256 valeurs différentes. |
|
Ceci dit, on trouve parfois des images codées sur 16 bits par |
|
composante, mais c'est loin d'être le cas général. |
|
J'ai donc souhaité aller plus loin, et coder chaque canal de |
|
chaque pixel en virgule flottante sur 32bits, le type |
|
\texttt{float}\index{float} du langage C. |
|
\vspace{1em} |
|
|
|
Attention, tout le code que nous allons voir ensemble est en |
|
perpétuelle évolution\footnote{voir page \pageref{TODO}}, |
|
et sa fiablité reste à démontrer\index{valgrind}. |
|
|
|
% ------------------------------------------------------------------- |
|
|
|
\tableofcontents |
|
\pagebreak |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Premier example}\index{example}\label{example} |
|
|
|
\textsc{FloatImg} a débuté sous la forme de quelques fonctions |
|
basiques en C, gérant la structure des données d'image en mémoire |
|
et sur disque. |
|
Nous allons donc directement rentrer au cœur du problème. |
|
|
|
\vspace{1em} |
|
|
|
Pour commencer par quelques chose de simple, |
|
nous allons créer une image RGB\index{RGB} complètement noire, |
|
puis l'enregistrer dans un fichier \texttt{.fimg}\index{.fimg}, |
|
un format complètement inconnu, puisque je viens de l'inventer |
|
à l'instant même. |
|
|
|
Tout d'abord, nous devons déclarer et garnir quelques variables |
|
pour gérer la machinerie interne. |
|
|
|
\begin{verbatim} |
|
int width = 640, height = 480; |
|
char *fname = "exemple.fimg"; |
|
FloatImg fimg; |
|
\end{verbatim} |
|
|
|
Ensuite, nous enchainerons trois étapes : création de l'image |
|
en mémoire centrale, initialisations des valeurs de pixel à 0.0, |
|
et pour conclure, enregistrement dans un fichier. |
|
|
|
\begin{verbatim} |
|
foo = fimg_create(&fimg, width, height, FIMG_TYPE_RGB); |
|
if (foo) { |
|
fprintf(stderr, "create floatimg -> %d\n", foo); |
|
exit(1); |
|
} |
|
fimg_clear(&fimg); |
|
foo = fimg_dump_to_file(&fimg, fname, 0); |
|
if (foo) { |
|
fprintf(stderr, "dump fimg -> %d\n", foo); |
|
exit(1); |
|
} |
|
\end{verbatim} |
|
|
|
|
|
Une fois ce code enrobé dans un \texttt{main()}, compilé et exécuté, |
|
nous pouvons entrevoir, grâce au logiciel |
|
\texttt{fimgstats} (voir page \pageref{fimgstats}), |
|
le résultat sous forme de chiffres divers, et/ou inutiles~: |
|
|
|
\begin{verbatim} |
|
$ ./fimgstats quux.img |
|
----------- numbers from 'quux.img' : |
|
640 480 3 0x7f3718c4f010 0x7f3718d7b010 0x7f3718ea7010 |
|
surface 307200 |
|
mean values: |
|
R 0.000000 |
|
G 0.000000 |
|
B 0.000000 |
|
A 0.000000 |
|
max value 0.000000 |
|
\end{verbatim} |
|
|
|
Nous avons donc sous la main une mécanique qui ne demande qu'à |
|
faire des trucs futiles et des images qui clignotent. |
|
La suite vers la page \pageref{codaz}. |
|
|
|
\vspace{1em} |
|
|
|
Vous trouverez dans le répertoire \texttt{tools/}\index{tools/} |
|
d'autres exemples de mise en œuvre des fonctions disponibles |
|
sous formes d'outils en ligne de commande, |
|
décrits en page \pageref{outils}. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Installation} |
|
|
|
\subsection{Prérequis} |
|
|
|
Vous devez, en dehors des outils classiques (bash, gcc, make\dots), |
|
avoir quelques bibliothèques installées\footnote{Les \texttt{-dev} |
|
pour Debain et dérivées}~: libv4l2, libpnglite, libtiff, libpnm, |
|
et probablement d'autres choses. |
|
Être familier avec l'utilisation du shell\index{shell} et l'écriture |
|
de Makefile's sera un plus. |
|
|
|
\subsection{Compilation} |
|
|
|
Un script \texttt{build.sh} permet de construire approximativement |
|
le bouzin. Il est loin d'être parfait\footnote{Il doit être possible |
|
de faire un Makefile récursif, mais\dots}. |
|
Dans chacun des |
|
répertoires à traiter, ce script devrait trouver un Makefile et un fichier |
|
\texttt{t.c} source de la cible par défaut du make. |
|
\vspace{1em} |
|
|
|
Pour le moment, la procédure d'installation est un peu rude, |
|
pour ne pas dire clairement sommaire. |
|
Si le résultat vous semble correct, vous pouvez copier |
|
les deux fichiers \texttt{floatimg.h} et \texttt{libfloatimg.a} |
|
dans un emplacement |
|
approprié, par exemple |
|
\texttt{/usr/local/include} et \texttt{/usr/local/lib}. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Utilisation coté codeur}\label{codaz} |
|
|
|
Classiquement, il y a un fichier à inclure, \texttt{floatimg.h}, |
|
contenant un certain nombre de |
|
définition de structures, de macros, |
|
de constantes\footnote{À l'ancienne, via le pré-processur} |
|
et les prototypes des fonctions utilisables. |
|
\vspace{1em} |
|
|
|
Au niveau du code source, ces fonctions sont approximativement |
|
classées en deux catégories : \texttt{lib/} et \texttt{funcs/}. |
|
La première contient les choses qui sont relativement figées, |
|
et la seconde celles qui risquent de bouger. Cette classification |
|
est en fait arbitraire. |
|
|
|
\subsection{Structures, macros\dots} |
|
|
|
Les pixels flottants d'une image résidant en mémoire centrale |
|
sont décrits par un ensemble |
|
de données (certains appelent ça des \textsl{metadats}) regroupées |
|
dans une jolie structure que nous allons examiner dès maintenant. |
|
|
|
\begin{verbatim} |
|
/* in memory descriptor */ |
|
typedef struct { |
|
int width; |
|
int height; |
|
int type; |
|
float fval; |
|
int count; |
|
float *R, *G, *B, *A; |
|
int reserved; |
|
} FloatImg; |
|
\end{verbatim}\index{FloatImg} |
|
|
|
Les deux premiers champs sont \textsl{obvious}. |
|
Le troisième est le type d'image : pour le moment, il y en a trois |
|
qui sont définis\footnote{et plus ou moins bien gérés\dots} : |
|
gris, rgb et rgba\index{rgba}. |
|
|
|
\begin{verbatim} |
|
#define FIMG_TYPE_GRAY 1 |
|
#define FIMG_TYPE_RGB 3 |
|
#define FIMG_TYPE_RGBA 4 |
|
\end{verbatim} |
|
|
|
Un peu plus loin, nous avons les pointeurs vers les |
|
différents \textsl{pixmaps} de l'image. En principe l'organisation |
|
interne de ces zones est improbable, puisque qu'elle dérive |
|
d'idées approximatives. |
|
\vspace{1em} |
|
|
|
Les deux champs suivants (fval et count) sont à la disposition du |
|
\textsl{yuser} |
|
qui peut jouer avec à loisir pour faire, par exemple, ce genre de |
|
chose. Imaginons un périphérique de capture qui nous fournisse des |
|
images en gris sur 4 bits. Et que nous voulions cumuler\index{cumul} |
|
quelques images... |
|
\vspace{1em} |
|
|
|
Le champ \textsl{count} sera mis à 0 et |
|
le champ \textsl{fval} sera initialisé à 15.0 |
|
(valeur maximale renvoyée par le capteur). |
|
Ensuite, dans la boucle capture/cumul, \textsl{count} sera |
|
incrémenté à chaque passe, et nous aurons donc, en finale, |
|
toutes les informations nécessaires pour exploiter au mieux la dynamique |
|
de notre image dans les étapes ultérieures. |
|
|
|
|
|
\subsection{lib/}\index{lib/} |
|
|
|
Première chose, la gestion dynamique de la mémoire occupées |
|
par tous ces pixels flottants est faite par ces deux fonctions~: |
|
|
|
\begin{verbatim} |
|
int fimg_create(FloatImg *fimg, int w, int h, int type); |
|
int fimg_destroy(FloatImg *fimg); |
|
\end{verbatim} |
|
|
|
Les types d'images actuellement gérés sont les trois grands |
|
classiques : gray, rgb et rgba. Il y a les constantes adéquates |
|
dans \texttt{floatimg.h}. Les codes d'erreur sont disparates |
|
et non documentés. |
|
\vspace{1em} |
|
|
|
Bon, vous avez une image latente, et vous souhaitez dessiner dessus |
|
(ou dedans ?) avec vos encres flottantes ? |
|
Il y a une fonction pour ça. |
|
|
|
\begin{verbatim} |
|
int fimg_plot_rgb (FloatImg *head, int x, int y, |
|
float r, float g, float b); |
|
\end{verbatim} |
|
|
|
Les paramètres sont explicites, mais leur validité doit être |
|
sévèrement controlée par l'appelant. Il y a une fonction |
|
soeur, \texttt{fimg\_add\_rgb}\index{fimg\_add\_rgb}, |
|
qui ajoute du rgb à un pixel. |
|
|
|
|
|
\subsection{funcs/}\index{funcs/}\label{funcs} |
|
|
|
Une bonne partie de ces fonctions est indéterministe. Ce qui |
|
veut dire, en langage de tous les soirs, que ça risque de ne |
|
pas être la même chose dans l'avenir. |
|
\vspace{1em} |
|
|
|
On y trouve pêle-mêle de l'import/export de fichiers, de l'analyse |
|
de chaines de caractères, du tracé de choses bizarres\dots |
|
Plein de trucs qu'il faudra bien expliquer un jour\footnote{Mais |
|
il fait trop chaud dans le dd2\index{dd2}}. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Les outils}\label{outils} |
|
|
|
\textsl{3615mavie} : sur des projets comme celui-ci, qui travaillent |
|
in-fine sur des objets que l'on peut considérer comme « physiques », |
|
il est important de passer à une utilisation |
|
normale\footnote{Il y a une vie en dehors de git.} et construire |
|
des trucs qui mettent en action le code primitif. |
|
\vspace{1em} |
|
|
|
Ces machins ont en commun deux options bien pratiques~: |
|
\texttt{-h} pour avoir un résumé des options disponibles |
|
et \texttt{-v} qui augmente la puissance de bavardage. |
|
Dans un avenir incertain, il existera des pages de man\index{man}. |
|
|
|
|
|
\subsection{mkfimg}\index{mkfimg}\label{mkfimg} |
|
|
|
Création d'un fichier contenant une image de « teinte » constante |
|
(ou pas). |
|
Cette notion de teinte est assez inconsistante pour le moment, |
|
|
|
\begin{verbatim} |
|
tth@debian:~/Devel/FloatImg/tools$ ./mkfimg -v -h |
|
Usage: mkfimg [options] quux.fimg width height |
|
-k N.N give a float parameter |
|
-t bla howto make the pic |
|
black, drand48... |
|
-v increase verbosity |
|
*** FloatImg library, alpha v73 (Sep 28 2019, 23:34:29) |
|
\end{verbatim} |
|
|
|
|
|
\subsection{png2fimg}\index{png2fimg}\label{png2fimg} |
|
|
|
Grosse panne à réparer. |
|
|
|
\begin{verbatim} |
|
tth@debian:~/TMP/floatimg$ png2fimg A.png foo.fimg |
|
error in 'fimg_create_from_png' : read png -> -1 File error |
|
png2fimg : err -1, abort. |
|
\end{verbatim} |
|
|
|
Il faut envisager le passage à \texttt{libpng}\index{libpng}. |
|
|
|
\subsection{fimgstats}\index{fimgstats}\label{fimgstats} |
|
|
|
Affichage de quelques valeurs calculées à partir du contenu d'un fichier |
|
\texttt{.fimg}\index{.fimg}. |
|
|
|
\begin{verbatim} |
|
usage : fimgstats [options] file.fimg |
|
-c make a machinable csv |
|
-v increase verbosity |
|
\end{verbatim} |
|
|
|
À vrai dire, je ne sais pas encore quelles métriques seront utiles |
|
en première approche, alors commençont par le plus simple, |
|
les valeurs moyennes de chaque composante. |
|
|
|
Puis nous rajouterons le calcul de la variance\index{variance}. |
|
|
|
\subsection{fimgops}\index{fimgops}\label{fimgops} |
|
|
|
Operations diverses sur ou entre des images. |
|
|
|
\begin{verbatim} |
|
usage: |
|
fimgops [options] A.fimg B.fimg operator D.fimg |
|
operators: |
|
add 1 |
|
sub 2 |
|
mix 3 |
|
mul 4 |
|
options: |
|
-g convert output to gray |
|
-k N.N set float value |
|
-v increase verbosity |
|
\end{verbatim} |
|
|
|
Pour des operateurs paramétrable (comme \texttt{mix}), le paramêtre flottant doit |
|
être fourni en utilisant l'option \texttt{-k}. |
|
|
|
\subsection{fimg2png, fimg2pnm, fimg2tiff} |
|
\index{fimg2png}\label{fimg2png} |
|
\index{fimg2pnm}\label{fimg2pnm} |
|
\index{fimg2tiff}\label{fimg2tiff} |
|
|
|
Quelques petits proggies pour exporter notre format\index{.fimg} secret |
|
vers des choses plus directement utilisables. À condition que le |
|
code soit écrit et documenté en page \pageref{funcs}. |
|
|
|
\subsection{fimg2gray}\index{fimg2gray}\label{fimg2gray} |
|
|
|
Nous avons vu dans ce document que chaque image flottante pouvait |
|
avoir plusieurs plans de réalité. Il ne faut en négliger aucun. |
|
\vspace{1em} |
|
|
|
Il faut quand même deviner que pour passer de l'espace RGB\index{RGB} |
|
à une abstraction linéaire mono-dimensionnelle, il existe une foultitude |
|
de méthodes, toutes plus légitimes que les autres. |
|
|
|
% ------------------------------------------------------------------- |
|
\section{TODO}\index{TODO}\label{TODO} |
|
|
|
Il reste plein de choses à faire pour que ce soit vraiment utilisable. |
|
\vspace{1em} |
|
|
|
\begin{itemize} |
|
|
|
\item Import/export au format \textsc{tiff}\index{tiff}. |
|
\item Remplacer le « fait-maison » par \textsc{libnetpnm}\index{pnm}. |
|
\textsl{[en cours]}. |
|
\item Compléter les traitements mathémathiques (eg le gamma\index{gamma}). |
|
\item Formaliser les codes d'erreur. |
|
\ |
|
\end{itemize} |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Exemples pour yusers}\index{example} |
|
|
|
\begin{verbatim} |
|
#!/bin/bash |
|
|
|
ACCU="quux.fimg" |
|
TMPF="tmp.fimg" |
|
DIMS="640 480" |
|
|
|
mkfimg ${ACCU} ${DIMS} |
|
|
|
for i in {0..100} |
|
do |
|
fname=$( printf "f%04d.pnm" $i ) |
|
echo $fname |
|
mkfimg -t drand48 ${TMPF} ${DIMS} |
|
done |
|
\end{verbatim} |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Video for Linux}\index{v4l2} |
|
|
|
Donc, maintenant, nous savons un peu tripoter ces images flottantes. |
|
Et nous devons nous poser une question fondamentale\footnote{primitive ?} |
|
sur la provenance de ces données prétendant être des images. |
|
\vspace{1em} |
|
|
|
En fait, notre désir secret est la découverte des choses cachées du |
|
monde qui nous entoure. Nous voulons des images du \textbf{réel} et |
|
pour cela, l'outil le plus commun, le plus répandu, |
|
est la webcam\index{webcam}. L'universelle webcam. Et l'incontournable |
|
v4l2. |
|
|
|
\subsection{grabvidseq}\index{grabvidseq}\label{grabvidseq} |
|
|
|
Un logiciel en devenir, qui permet déja la capture d'images en |
|
\textsl{longue pose} selon la méthode du cumul\index{cumul}. |
|
|
|
\begin{verbatim} |
|
tth@debian:~/Devel/FloatImg/v4l2$ ./grabvidseq -h |
|
options : |
|
-d /dev/? select video device |
|
-g convert to gray |
|
-n NNN how many frames ? |
|
-O ./ set Output dir |
|
-o bla set output filename |
|
-p NN.N period in seconds |
|
-s WxH size of capture |
|
-u try upscaling... |
|
-v increase verbosity |
|
\end{verbatim} |
|
|
|
\subsection{video-infos}\index{video-infos}\label{video-infos} |
|
|
|
Que contient, que peut faire mon périphérique \textsl{àlc} ? |
|
|
|
% ------------------------------------------------------------------- |
|
\section{Et pour la suite ?} |
|
|
|
En fait, je fait de la photo par la méthode du « cumul »\index{cumul} |
|
depuis plusieurs années. Une webcam\index{webcam}, |
|
un Linux\index{Linux}, et ça \textsl{juste marche}. |
|
Sauf que c'est quand même un peu galère à déplacer, il faut |
|
avoir un shell pour déclencher, c'est pas facile à utiliser |
|
en mode portnawak\dots |
|
\vspace{1em} |
|
|
|
L'idée est donc de construire un appareil autonome, basé sur un Raspi et |
|
une webcam \textsc{usb}\index{USB}, alimenté par batterie et permettant d'aller |
|
faire des images au bord d'un lac. |
|
|
|
% ------------------------------------------------------------------- |
|
|
|
\printindex |
|
|
|
\end{document}
|
|
|