Compare commits

..

7 Commits

Author SHA1 Message Date
tth
711e54fe43 histocomputing boilerplate [done] 2020-09-03 02:00:32 +02:00
tth
951dc4450f working on histogram computation 2020-09-03 01:37:53 +02:00
tth
4b2d2c264f need proff reading 2020-09-03 01:35:54 +02:00
tth
a5cd02a261 ignore .tiff in v4l2/ 2020-09-02 12:45:41 +02:00
tth
fe22b0561e enhanced verbosity message 2020-08-31 17:51:12 +02:00
tth
3279d0dde8 oups... 2020-08-24 11:40:49 +02:00
tth
30347903ca half-fixed a memory leak 2020-08-23 23:55:36 +02:00
8 changed files with 177 additions and 26 deletions

1
.gitignore vendored
View File

@ -42,6 +42,7 @@ v4l2/*.o
v4l2/*.ppm v4l2/*.ppm
v4l2/*.png v4l2/*.png
v4l2/*.fits v4l2/*.fits
v4l2/*.tiff
v4l2/video-infos v4l2/video-infos
v4l2/nc-camcontrol v4l2/nc-camcontrol

View File

@ -26,7 +26,7 @@
\usepackage{xspace} \usepackage{xspace}
\usepackage[verbose]{layout} \usepackage[verbose]{layout}
\setlength \parskip {0.333em} \setlength \parskip {0.35em}
\makeatletter \makeatletter
% exlpication de ce truc ? % exlpication de ce truc ?
@ -204,19 +204,22 @@ lesquels sont décrits en page \pageref{outils}.
% ------------------------------------------------------------------- % -------------------------------------------------------------------
\section{Installation} \section{Installation}
Sauf indications contraires, ces instructions se réfèrent à
une distribution Debian\index{Debian} récente.
\textit{Attention, ça devient un peu gore. Myrys, punk, toussa\dots} \textit{Attention, ça devient un peu gore. Myrys, punk, toussa\dots}
\subsection{Prérequis} \subsection{Prérequis}
Vous devez, en dehors des outils classiques (bash, gcc, make\dots), Vous devez, en dehors des outils classiques (bash, gcc, make\dots),
avoir quelques bibliothèques installées\footnote{Les \texttt{-dev} avoir quelques bibliothèques installées\footnote{Les \texttt{-dev}
pour Debian et dérivées}~: en plus pour Debian et dérivées}~:
\textsf{ \textsf{
libv4l2, libpnglite, libtiff, libv4l2, libpnglite, libtiff,
libnetpbm\footnote{package libnetpbm10-dev}, libnetpbm\footnote{package libnetpbm10-dev},
libz\footnote{package zlib1g-dev}, libcurses, libz\footnote{package zlib1g-dev}, libcurses,
libcfitsio-dev libcfitsio-dev
} % en of textsf } % end of textsf
éventuellement avec le \textsf{-dev} correspondant, éventuellement avec le \textsf{-dev} correspondant,
et probablement d'autres choses. et probablement d'autres choses.
@ -293,7 +296,8 @@ typedef struct {
\end{lstlisting}\index{FloatImg} \end{lstlisting}\index{FloatImg}
Les deux premiers champs sont \textsl{obvious}. Les deux premiers champs sont \textsl{obvious}.
Le troisième est le type d'image : pour le moment, il y en a trois Le troisième est le type d'image : pour le moment, il y en a % trois
un certain nombre
qui sont définis\footnote{et plus ou moins bien gérés\dots} : qui sont définis\footnote{et plus ou moins bien gérés\dots} :
gris, rgb et rgba\index{rgba}. gris, rgb et rgba\index{rgba}.
Les constantes adéquates sont dans \texttt{floatimg.h} Les constantes adéquates sont dans \texttt{floatimg.h}
@ -317,7 +321,8 @@ Les deux champs suivants (fval et count) sont à la disposition du
\textsl{yuser} \textsl{yuser}
qui peut jouer avec à loisir pour faire, par exemple, ce genre de qui peut jouer avec à loisir pour faire, par exemple, ce genre de
chose : imaginons un périphérique de capture qui nous fournisse des 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} images en gris sur 4 bits (et linéaire).
Et que nous voulions cumuler\index{cumul}
quelques images... quelques images...
Le champ \textsl{count} sera mis à 0 et Le champ \textsl{count} sera mis à 0 et
@ -436,15 +441,17 @@ Là aussi, il n'y a aucun contrôle sur la validité des valeurs
$x$ et $y$ de la demande. $x$ et $y$ de la demande.
Quand au canal \textsl{alpha}\index{alpha}, il est pour le moment Quand au canal \textsl{alpha}\index{alpha}, il est pour le moment
superbement ignoré. superbement ignoré. Ceci dit, on vient de me faire remarquer qu'il
peut être utilisable aussi pour faire du
\textsl{z-buffer}\index{z-buffer} \dots
% ---------------------------------- % ----------------------------------
\subsection{Contraste}\index{contraste}\label{contraste} \subsection{Contraste}\index{contraste}\label{contraste}
Certaines opérations d'ajustement du contraste d'une image Certaines opérations d'ajustement du contraste d'une image
semblent cohérents avec la notion d'image flottante. semblent cohérentes avec la notion d'image flottante.
Certains d'entre eux, les plus simples, sont disponibles. Certaines d'entre elles, les plus simples, sont disponibles.
Les autres sont à imaginer. Les autres sont à imaginer.
\begin{figure}[h] \begin{figure}[h]
@ -453,8 +460,9 @@ Les autres sont à imaginer.
\end{figure} \end{figure}
Ils prennent chacun trois paramètres, d'abord les images Ils prennent chacun trois paramètres, d'abord les images
source et destination (\texttt{* FloatImg}), et le troisième source et destination (\texttt{* FloatImg}),
est un nombre en double précision donnant la valeur ensuite le troisième
qui est un nombre en double précision donnant la valeur
maximale \textsl{supposée} de l'image source, maximale \textsl{supposée} de l'image source,
valeur qui peut être déterminée de plusieurs manières. valeur qui peut être déterminée de plusieurs manières.
@ -469,6 +477,7 @@ int fimg_cos_010(FloatImg *s, FloatImg *d, double maxval);
Si vous souhaitez rajouter votre propre méthode de modification Si vous souhaitez rajouter votre propre méthode de modification
de contraste, il y a quelques explication en page \pageref{exemplefunc}. de contraste, il y a quelques explication en page \pageref{exemplefunc}.
Mais rien ne vous oblige à le faire.
\begin{figure}[h] \begin{figure}[h]
@ -606,7 +615,8 @@ Les autres bits ne sont pas utilisés et doivent être à zéro.
\subsubsection{Vers PNG}\index{PNG} \subsubsection{Vers PNG}\index{PNG}
Actuellement, on peut enregistrer uniquement en mode RGB, 8 bits par composante, Actuellement, on peut enregistrer uniquement en mode RGB,
8 bits par composante,
mais on a quand même une bonne compression, ça compense. mais on a quand même une bonne compression, ça compense.
J'utilise \textsl{libpnglite} avec qui j'ai un peu de mal à suivre. J'utilise \textsl{libpnglite} avec qui j'ai un peu de mal à suivre.
Mais je me soigne. Le mode 16 bits va bientôt arriver. Mais je me soigne. Le mode 16 bits va bientôt arriver.
@ -618,13 +628,18 @@ int fimg_save_as_png(FloatImg *src, char *outname, int flags);
Tous les flags doivent être à zéro. Sinon, ça foire parfois. Tous les flags doivent être à zéro. Sinon, ça foire parfois.
\subsubsection{Vers/depuis TIFF}\index{TIFF} \subsubsection{Vers TIFF}\index{TIFF}
Le format canonique de la PAO\index{PAO} du siècle dernier. Il permet Le format canonique de la PAO\index{PAO} du siècle dernier. Il permet
de gérer une foultitude de formats numériques. C'est aussi un format de gérer une foultitude de formats numériques. C'est aussi un format
classique proposé par les gros scanners corporates. classique proposé par les gros scanners corporates.
To be done\index{XXX} \begin{lstlisting}
int fimg_write_as_png(FloatImg *src, char *outname, int flags);
\end{lstlisting}
Tous les flags doivent être à zéro.
\subsubsection{Vers FITS}\index{FITS} \subsubsection{Vers FITS}\index{FITS}
@ -769,10 +784,10 @@ return 0;
\end{lstlisting} \end{lstlisting}
Je vous laisse imaginer les dégats que peut faire cette Je vous laisse imaginer les dégats que peut faire cette
fontion en utilisation réelle. Mieux, je vous propose fonction en utilisation réelle. Mieux, je vous propose
d'essayer par vous-même. d'essayer par vous-même.
En particulier tout le reste du code qui suppose qu'un pixel En particulier tout le reste du code qui suppose qu'un pixel
ne peut \textbf{pas} être négatif. ne peut \textbf{pas} être négatif va peut-être exploser de rire.
Vous pouvez aussi remarquer qu'il n'y a pas de controle Vous pouvez aussi remarquer qu'il n'y a pas de controle
de cohérence sur les dimensions des deux images, malgré l'existence de cohérence sur les dimensions des deux images, malgré l'existence
de fonctions prévues à cet effet.. de fonctions prévues à cet effet..
@ -1129,7 +1144,7 @@ done
\end{verbatim} \end{verbatim}
Et en fin de boucle, nous convertissons le résultat de nos Et en fin de boucle, nous convertissons le résultat de nos
savants au format PNG, et écrivons le fichier dans le répertoire savants calculs au format PNG, et écrivons le fichier dans le répertoire
de destination fixé au début. de destination fixé au début.
C'est le moment de passer la main à ffmpeg\index{ffmpeg}. C'est le moment de passer la main à ffmpeg\index{ffmpeg}.
@ -1180,8 +1195,10 @@ La plupart de ces options ont un usage quasi-évident.
L'option \texttt{-s} doit correspondre à une des L'option \texttt{-s} doit correspondre à une des
résolutions possibles de votre capteur. Le type du résolutions possibles de votre capteur. Le type du
fichier en sortie (option \texttt{-o}) est déterminé par fichier en sortie (option \texttt{-o}) est déterminé par
l'extension, actuellement l'extension du nom.
seulement \texttt{.fimg}, \texttt{.pnm} et \texttt{.png} Actuellement
seulement \texttt{.fimg}, \texttt{.pnm}, \texttt{.fits},
\texttt{.tiff} et \texttt{.png}
sont reconnus. sont reconnus.
La conversion en gris (option \texttt{-g}) mérite un La conversion en gris (option \texttt{-g}) mérite un
@ -1256,9 +1273,25 @@ de \textsl{Brunus} pour avancer...
\subsection{Gimp}\index{Gimp} \subsection{Gimp}\index{Gimp}
Mmmmm... Ça semble un peu plus compliqué. D'un autre coté, il Mmmmm... Ça semble un peu plus compliqué.
La documentation à ce sujet me semble ésotérique.
D'un autre coté, il
faut faire ça en \textbf{C}, ce qui ne peut être négatif. faut faire ça en \textbf{C}, ce qui ne peut être négatif.
\subsection{ffmpeg}\index{ffmpeg}
Un petit aide-mémoire pour encoder vos superbes
timelapses\index{timelapse} :
\begin{lstlisting}
ffmpeg -nostdin \
-y -r 30 -f image2 -i stereo/S%04d.png \
-c:v libx264 \
-pix_fmt yuv420p \
-tune film \
stereo.mp4
\end{lstlisting}
\subsection{Et encore ?}\index{krita}\index{geeqie} \subsection{Et encore ?}\index{krita}\index{geeqie}
Il y a d'autres logiciels pour lesquels écrire une fonction d'importation Il y a d'autres logiciels pour lesquels écrire une fonction d'importation

View File

@ -4,7 +4,7 @@ COPT = -Wall -fpic -g -no-pie -DDEBUG_LEVEL=0
DEPS = ../floatimg.h Makefile DEPS = ../floatimg.h Makefile
OBJS = fimg-png.o fimg-tiff.o misc-plots.o filtrage.o utils.o \ OBJS = fimg-png.o fimg-tiff.o misc-plots.o filtrage.o utils.o \
fimg-libpnm.o rampes.o sfx0.o geometry.o rotate.o \ fimg-libpnm.o rampes.o sfx0.o geometry.o rotate.o \
equalize.o fimg-fits.o saturation.o equalize.o fimg-fits.o saturation.o histogram.o
#--------------------------------------------------------------- #---------------------------------------------------------------
@ -45,6 +45,9 @@ rotate.o: rotate.c $(DEPS)
saturation.o: saturation.c $(DEPS) saturation.o: saturation.c $(DEPS)
gcc $(COPT) -c $< gcc $(COPT) -c $<
histogram.o: histogram.c $(DEPS)
gcc $(COPT) -c $<
equalize.o: equalize.c $(DEPS) equalize.o: equalize.c $(DEPS)
gcc $(COPT) -c $< gcc $(COPT) -c $<

76
funcs/histogram.c Normal file
View File

@ -0,0 +1,76 @@
/*
* FLOATIMG
* calculer un histogramme et l'afficher
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../floatimg.h"
extern int verbosity;
/* --------------------------------------------------------------------- */
int fimg_calcul_histo(FloatImg *src, long *ghist, int sz)
{
float maxval;
int x, y, idx;
float rgb[3], moy;
fprintf(stderr, ">>> %s ( %p %p %d )\n", __func__, src, ghist, sz);
maxval = fimg_get_maxvalue(src);
fprintf(stderr, "maximum is %f\n", maxval);
for (y=0; y<src->height; y++) {
for(x=0; x<src->width; x++) {
fimg_get_rgb(src, x, y, rgb);
moy = (rgb[0]+rgb[1]+rgb[2]) / 3.0;
/* ok, here the had math part ... */
idx = (int)( (moy*sz) / maxval);
/* sanity check */
if (idx<0 || idx>=sz) {
fprintf(stderr, "idx = %d, error\n", idx);
abort();
}
ghist[idx]++;
}
}
return -66;
}
/* --------------------------------------------------------------------- */
#define NSLICES 999
int fimg_essai_histo(FloatImg *src, char *outpic, int k)
{
long histo[NSLICES];
int foo;
FILE *pipe;
fprintf(stderr, ">>> %s ( %p '%s' %d )\n", __func__, src, outpic, k);
memset(histo, 0, NSLICES*sizeof(long));
foo = fimg_calcul_histo(src, histo, NSLICES);
for (foo=0; foo<NSLICES; foo++) {
printf("%7d %ld\n", foo, histo[foo]);
}
pipe = popen("gnuplot", "w");
fprintf(pipe, "set term png size 1000,400\n");
fprintf(pipe, "set output \"histo.png\"\n");
fprintf(pipe, "plot 'toto' with lines\n");
fclose(pipe);
return -1;
}
/* --------------------------------------------------------------------- */

View File

@ -401,7 +401,36 @@ fprintf(stderr, "save as png -> %d\n", foo);
return 0; return 0;
} }
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
enum nCmd { Equalize=1, Rotate, Sfx0, F3x3, MIRE, Wfits, Wpng, Wtiff };
/* func in histogram.c */
int fimg_essai_histo(FloatImg *src, char *outpic, int k);
int essai_histogramme(char *fname, int k)
{
FloatImg fimg;
int foo;
fprintf(stderr, ">>> %s ( '%s' %d )\n", __func__, fname, k);
foo = fimg_create_from_dump(fname, &fimg);
if (foo) {
fprintf(stderr, "%s: err load '%s'\n", __func__, fname);
return foo;
}
foo = fimg_essai_histo(&fimg, "out.png", k);
if (foo) {
fprintf(stderr, "essai_histo -> %d\n", foo);
return foo;
}
fprintf(stderr, "\\o/ end of %s\n", __func__);
return -1;
}
/* --------------------------------------------------------------------- */
enum nCmd { Equalize=1, Rotate, Sfx0, F3x3, MIRE, Wfits, Wpng, Wtiff,
Histo };
typedef struct { typedef struct {
char *name; char *name;
int Cmd; int Cmd;
@ -416,6 +445,7 @@ Command commands[] = {
{ "wfits", Wfits }, { "wfits", Wfits },
{ "wpng", Wpng }, { "wpng", Wpng },
{ "wtiff", Wtiff }, { "wtiff", Wtiff },
{ "histo", Histo },
{ NULL, 0 } { NULL, 0 }
} ; } ;
@ -455,7 +485,7 @@ int main(int argc, char *argv[])
int foo, opt; int foo, opt;
char *filename, *command; char *filename, *command;
puts("++++++++ test des fonctions +++++++"); fprintf(stderr, "++++++++ test des fonctions pid=%d\n", getpid());
global_fvalue = 1.0; global_fvalue = 1.0;
@ -506,6 +536,9 @@ switch(opt) {
case Wtiff: case Wtiff:
foo = essai_ecriture_tiff(filename); foo = essai_ecriture_tiff(filename);
break; break;
case Histo:
foo = essai_histogramme(filename, 0);
break;
default: default:
fprintf(stderr, "%s : bad command\n", command); fprintf(stderr, "%s : bad command\n", command);
exit(1); exit(1);

View File

@ -141,6 +141,8 @@ if (foo) {
exit(1); exit(1);
} }
fimg_destroy(&fimg);
return 0; return 0;
} }
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */

View File

@ -240,7 +240,7 @@ else {
} }
fimg_clear(&cumul); fimg_clear(&cumul);
cumul.fval = 255.0; cumul.fval = 255.0; /* must be read from camera XXX */
cumul.count = 0; cumul.count = 0;
to_save = &cumul; to_save = &cumul;
@ -347,6 +347,8 @@ if (verbosity) fprintf(stderr, "saving cumul to '%s'\n", outfile);
maxvalue = cumul.fval * cumul.count; maxvalue = cumul.fval * cumul.count;
if (verbosity) { if (verbosity) {
fprintf(stderr, "theorical maxvalue = %g\n", maxvalue); fprintf(stderr, "theorical maxvalue = %g\n", maxvalue);
fprintf(stderr, "computed max value = %g\n",
fimg_get_maxvalue(&cumul));
} }
switch (contrast) { switch (contrast) {
case CONTRAST_NONE: case CONTRAST_NONE:
@ -398,6 +400,7 @@ switch (foo) {
break; break;
case FILE_TYPE_TIFF: case FILE_TYPE_TIFF:
foo = fimg_write_as_tiff(to_save, outfile, 0); foo = fimg_write_as_tiff(to_save, outfile, 0);
break;
default: default:
fprintf(stderr, "can't save as %s\n", outfile); fprintf(stderr, "can't save as %s\n", outfile);
break; break;