9 votes

Histogramme du "niveau d'encre noire" d'une image par axe horizontal

J'ai un fichier image (ou pdf) en noir et blanc, et je veux obtenir un histogramme du profil horizontal de l'image. Autrement dit, pour chaque colonne de l'image, je veux la somme des valeurs de gris des pixels de la colonne. Si l'image mesure X par Y pixels, je me retrouverai avec X nombres compris entre 0 (pour une colonne entièrement noire) et 255*Y (pour une colonne entièrement blanche).

Veuillez consulter le deuxième panneau de cette bande dessinée Comic

Je voudrais un histogramme comme celui-ci, mais chaque case représenterait toute l'"encre noire" de l'image à cette coordonnée x (pixel).

En tant que pauvre étudiant diplômé, je suis contraint d'utiliser uniquement la ligne de commande Linux et les programmes FOSS (ImageMagick, gnuplot, Perl, g++, etc.). Quelque chose comme GIMP ne serait utile que si je peux exécuter la commande via un terminal, car je n'ai pas accès à une interface graphique. Un fichier de sortie visuel serait utile pour plus tard, mais n'est pas nécessaire.

Quelqu'un connaît-il un moyen d'extraire cette information ? Les recherches de "profil d'image" ne mènent qu'à des informations sur les profils de couleur.

13voto

andyras Points 6906

Je vais répondre en deux actes, en utilisant deux de mes utilitaires gratuits préférés : python et gnuplot.

En tant qu'étudiant diplômé (en informatique), je pense que si vous voulez faire des choses gratuitement, python est l'un des outils les plus polyvalents que vous pouvez apprendre à utiliser.

Voici un script python qui fait la première partie, en comptant la valeur des niveaux de gris (de 0 pour le blanc à 255 pour le noir) :

#!/usr/bin/python

import Image            # basic image processing/manipulation, just what we want

im = Image.open('img.png')       # open the image file as a python image object
with open('data.dat', 'w') as f: # open the data file to be written
    for i in range(im.size[0]):  # loop over columns
        counter = sum(im.getpixel((i,j)) for j in range(im.size[1]))
        f.write(str(i)+'\t'+str(counter)+'\n')  # write to data file

C'est incroyablement indolore ! Maintenant pour que gnuplot fasse un histogramme* :

#!/usr/bin/gnuplot

set terminal pngcairo size 925,900
set output 'plot.png'
#set terminal pdfcairo
#set output 'plot.pdf'
set multiplot

## first plot
set origin 0,0.025              # this plot will be on the bottom
set size 1,0.75                 # and fill 3/4 of the whole canvas

set title "Black count in XKCD 'Self-Description'"
set xlabel 'Column'
set ylabel "Black\ncount" norotate offset screen 0.0125

set lmargin at screen 0.15      # make plot area correct size
set rmargin at screen 0.95      # width = 740 px = (0.95-0.15)*925 px

set border 0                    # these settings are just to make the data
set grid                        # stand out and not overlap with the tics, etc.
set tics nomirror
set xtics scale 0.5 out 
set ytics scale 0

set xr [0:740]                  # x range such that there is one spike/pixel

## uncomment if gnuplot version >= 4.6.0
## this will autoset the x and y ranges
#stats 'data.dat'
#set xr [STATS_min_x:STATS_max_x+1]
#set yr [STATS_min_y:STATS_may_y]

plot 'data.dat' with impulse notitle lc 'black'

## second plot
set origin 0,0.75               # this plot will be on top
set size 1,0.25                 # and fill 1/4 of the canvas

unset ylabel; unset xlabel      # clean up a bit...
unset border; unset grid; unset tics; unset title

set size ratio -1               # ensures image proper ratio
plot 'img.png' binary filetype=png with rgbimage

unset multiplot         # important to unset multiplot!

Pour exécuter ces scripts, enregistrez-les dans le même répertoire que l'image que vous voulez tracer (dans ce cas, la bande dessinée XKCD, que j'ai enregistrée sous le nom de img.png ). Rendez-les exécutables. En bash, c'est

$ chmod 755 grayscalecount.py plot.plt

Ensuite (si python+image module+gnuplot sont tous installés), vous pouvez exécuter

$ ./grayscalecount.py
$ ./plot.plt

Sur mon ordinateur, qui fonctionne sous Ubuntu 11.10 avec gnuplot 4.4.3, j'obtiens ce graphique sympa à la fin :

enter image description here

**Note complémentaire : il existe de nombreux histogrammes différents que gnuplot peut réaliser. J'ai trouvé que ce style mettait bien en valeur les données, mais vous pouvez chercher à formater vos données pour qu'elles soient plus claires. histogrammes gnuplot .

Il existe de nombreuses façons de faire en sorte que python fasse des graphiques lui-même ou avec gnuplot (matplotlib, pygnuplot, gnuplot-py), mais je ne suis pas aussi facile avec celles-ci. Gnuplot est incroyablement scriptable pour le traçage, et il y a beaucoup de façons de le faire jouer agréablement avec python, bash, C++, etc.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X