Afficher une image en niveaux de gris seulement avec des pixels noirs et blancs

Dithering

Le problème exposé dans ce sujet a été résolu.

Bonjour à tous,

Connaissez-vous un algorithme qui affiche une image de 256 niveaux de gris, mais seulement en utilisant des pixels soit noirs, soit blancs ?

Cet algorithme devrait utiliser le dithering : mais comment décider du nombre de pixels noirs et blancs constituant un niveau de gris précis ? Et aussi : comment le dithering peut-il permettre dessiner chacun des 256 niveaux de gris ?

Merci d’avance, bonnes fêtes de fin d’année :)

+0 -0

Salut :)

  1. Le gris étant en RVB quelque chose comme (X,X,X).
  2. Tu prends le X, tu le divise par 255.
  3. Tu as le ratio pixel noir / pixel blanc à avoir sur ce pixel.

Après il faut que tu saches en combien de "sous-pixel" tu veux découper ton pixel d’origine Par exemple, en découpant le gros pixel gris (100,100,100) en 51x51 "sous-pixel" j’obtiens ca :

pixel

En dé-zoomant ca rend plutôt bien : pixel blanc petit pixel petit pixel noir petit

+1 -0

Tu as le ratio pixel noir / pixel blanc à avoir sur ce pixel.

Parce que 255 = blanc et 0 = noir ? Donc diviser X par 255 donne le ratio "pixels blancs/ pixels noirs" plutôt non ?

Après il faut que tu saches en combien de "sous-pixel" tu veux découper ton pixel d’origine

Ce nombre de sous-pixels détermine quel gris appliquer (plus ou moins foncé) ?

Comment le déterminer justement ?

Tu as le ratio pixel noir / pixel blanc à avoir sur ce pixel.

Parce que 255 = blanc et 0 = noir ?

Pas exactement, en RVB les couleurs vont de 0 à 255 : 0 étant « pas de cette couleur » et 255 « cette couleur au maximum ». Par exemple : (255,0,255) c’est maximum de rouge et de bleu, donc du violet ; (0,0,0) c’est rien de rouge, vert et bleu, donc du noir ; et (255,255,255) c’est du blanc. :P Quand tu mélanges équitablement du rouge, vert et du bleu, tu as du gris :). D’où le fait que du gris en RVB c’est un triplet (X,X,X).

Donc diviser X par 255 donne le ratio "pixels blancs/ pixels noirs" plutôt non ?

Non. Si tu as 240/255, alors tu as beaucoup plus de blanc que de noir dans ton pixel.

Après il faut que tu saches en combien de "sous-pixel" tu veux découper ton pixel d’origine

Ce nombre de sous-pixels détermine quel gris appliquer (plus ou moins foncé) ?

Non. Le dithering, de ce que j’ai compris, c’est mélanger plusieurs pixel pour avoir l’impression d’en avoir qu’un seul d’une autre couleur (cf. l’image que tu donnes en exemple). Le nombre de sous pixel c’est pour savoir si tu divises ton pixel d’origine en 4, 16, 32, etc. petit carré.

Comment le déterminer justement ?

The-Aloha-Protocol

C’est à toi d’apprécier ca il me semble. Encore une fois dans ton exemple, quand tu prends que 4 carrés, ca fait pas du violet, mais celui en bas à droite ressemble beaucoup plus à du violet.

Cela marcherais peut être encore mieux si les pixels étaient répartis également sur ton image Gwend@l ?

Drulac

Tout à fait d’accord. Ce que j’ai fait c’est : alterner pixel blanc/pixel noir, ca donne un damier, puis changer aléatoirement le des pixels pour trouver la nuance de gris qu’il faut. Y’a certainement plus malin.

+0 -0

Tout à fait d’accord. Ce que j’ai fait c’est : alterner pixel blanc/pixel noir, ca donne un damier, puis changer aléatoirement le des pixels pour trouver la nuance de gris qu’il faut. Y’a certainement plus malin.

Avec un damier avec la bonne proportion de noir/blanc ça n’irait pas ?

La bonne proportion, oui, mais la question est de comment répartir les noirs et les blancs. Si la répartition est régulière, on peut avoir un effet visuel non désiré (par exemple, si on a un carré 16x16, et qu’on a 1 point sur 3 en noir, on va voir des lignes en diagonale).

Généralement, une bonne solution est d’utiliser la fonction Gwend@l, mais on peut l’adapter. Par exemple, sur un carré 16x16 (donc 256 pixels), on a déterminé qu’il faudrait idéalement 90 pixels noirs, la solution ’basique’ est :

1
2
3
pour i = 1 a 16
  pour j = 1 a 16
     si random(256) <= 90 alors noir sinon blanc 

Une solution améliorée est :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cases_restantes = 256
cases_noires_restantes = 90
pour i = 1 a 16
  pour j = 1 a 16
     si random(cases_restantes) <= cases_noires_restantes alors 
        noir
        cases_noires_restantes -- 
     sinon 
        blanc 
     cases_restantes --

À débattre, j’en sais rien, mais il me semble que visuellement l’illusion marche mieux si c’est (proche d’) un damier. J’avais essayé purement aléatoire pour voir, mais on dirait un flash code ^^

En matlab/octave c’est assez simple en plus !

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
gris           = 100; % la valeur de gris que tu veux, entre 0 et 255
ratioNoirBlanc = gris/255;
ligne          = 16;
colonne        = 16;

pixel          = rand(ligne,colone);
pixel(pixel >  ratioNoirBlanc) = 0;
pixel(pixel <= ratioNoirBlanc) = 1;

imshow(pixel)

La bonne proportion, oui, mais la question est de comment répartir les noirs et les blancs. Si la répartition est régulière, on peut avoir un effet visuel non désiré (par exemple, si on a un carré 16x16, et qu’on a 1 point sur 3 en noir, on va voir des lignes en diagonale).

Dans ce cas là il faut augmenter le nombre de case jusqu’à ce que cela ne soit plus visible ?

La bonne proportion, oui, mais la question est de comment répartir les noirs et les blancs. Si la répartition est régulière, on peut avoir un effet visuel non désiré (par exemple, si on a un carré 16x16, et qu’on a 1 point sur 3 en noir, on va voir des lignes en diagonale).

Dans ce cas là il faut augmenter le nombre de case jusqu’à ce que cela ne soit plus visible ?

Drulac

En théorie, oui. En pratique, pas forcément. Ca dépend de la taille initiale de ton pixel (s’il fait 1cm² oui, faut le découper en petit morceau sinon ca va se voir…). Mais garde aussi à l’esprit que ca fait une image plus lourde à l’arrivée ! Tu remplaces 1 pixel par 4, 16, etc. pixels !

En théorie, oui. En pratique, pas forcément. Ca dépend de la taille initiale de ton pixel (s’il fait 1cm² oui, faut le découper en petit morceau sinon ca va se voir…). Mais garde aussi à l’esprit que ca fait une image plus lourde à l’arrivée ! Tu remplaces 1 pixel par 4, 16, etc. pixels !

Gwend@l

Tu négliges la profondeur d’un pixel dans cette remarque. Un pixel sur 256 niveaux de gris s’encode comme un octet. Si tes pixels ne contiennent que du noir ou du blanc tu peux en encoder 8 par octet.

+1 -0

Merci à tous pour votre participation.

Si on regarde attentivement la page Wikipédia, on peut lire ceci à propos d’un algorithme dit du "dithering" :

le tramage aléatoire ou tremblotement (dithering) […] compare la valeur de chaque pixel à un seuil aléatoire. Bien que cette méthode ne génère pas d’artefacts répétitifs, le bruit tend à déborder sur les détails de l’image.

Ainsi permet-il d’obtenir une image comme celle-ci : ici

(à partir de cet original).

L’algorithme qui suit vous semble-t-il donc correct ? Il ressemble un peu à celui de Gwend@l :

1
2
3
4
pour chaque pixel
    var new_pixel = if (current_pixel.moyenneRGB() > random()) BLACK else WHITE
    setPixel(new_pixel)
fin pour
+0 -0

Ok. Alors visiblement on ne parle pas de la même chose. Dans mon premier post j’explique comment approximer un pixel en nuance de gris par un ensemble de sous pixel noir et blanc.

Ici, ce que tu cherches toi à faire ce n’est pas exactement ca. Tu cherches à remplacer un pixel gris par un pixel noir ou blanc. Ce n’est pas la même chose. Du coup, pour ce que tu cherches à faire ton algorithme semble correct.

Je suppose que le PO connait déjà cette page, sinon ça vaut la peine de jeter un oeil : https://fr.wikipedia.org/wiki/Tramage_(informatique).

D’après mes souvenirs, Floyd-Steinberg fonctionne relativement bien et est très simple a implémenter.

EDIT: si l’image de départ est en RGB, pour faire du tramage en noir et blanc il faudra tout d’abord convertir les valeurs RGB en un scalaire d’une façon ou d’une autre (voir ici par exemple).

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte