Diagramme de couleurs 24 bits et diagramme en niveaux de gris 8 bits
Tout d'abord, présentons une image couleur 24 bits. Dans une image couleur 24 bits, chaque pixel est représenté par trois octets, généralement exprimés en RVB. Généralement, de nombreuses images couleur 24 bits sont stockées sous forme d'images 32 bits, et les octets en excès par pixel sont stockés en valeur alpha , montrant des informations d'influence spéciales [1].
Dans le modèle RVB, si r = g = b, la couleur représente une couleur en niveaux de gris, où la valeur de r = g = b est appelée valeur en niveaux de gris. Par conséquent, chaque pixel de l'image en niveaux de gris ne nécessite qu'un seul octet pour stocker la valeur en niveaux de gris (également connue sous le nom de valeur d'intensité et de valeur de luminosité), et la plage de niveaux de gris est de 0 à 255 [2]. Cela vous donne une image en niveaux de gris de l'image.
Plusieurs méthodes de niveaux de gris
1. Méthode des composants: Utilisez l'un des trois composants RVB comme valeur en niveaux de gris de la carte en niveaux de gris.
2. Méthode de la plupart des valeurs: utilisez la valeur maximale ou minimale des trois composants RVB comme valeur en niveaux de gris de la carte de grédite.
3. Méthode moyenne: utilisez la valeur moyenne des trois composants RVB comme valeur en niveaux de gris du graphique en niveaux de gris.
4. Méthode de pondération: En raison de la sensibilité des couleurs différentes des yeux humains, la moyenne pondérée des trois composants RVB peut obtenir une image en niveaux de gris plus raisonnable. La situation générale est la suivante: y = 0,30r + 0,59 g + 0,11b.
[Remarque] La méthode de pondération prend en fait la valeur de luminosité d'une image comme valeur de niveaux de gris pour calculer et utilise le modèle YUV. Dans [3], vous constaterez que l'auteur a utilisé y = 0,21 * r + 0,71 * g + 0,07 * b pour calculer la valeur en niveaux de gris (évidemment la somme des trois poids ne correspond pas à 1, ce qui peut être l'erreur de l'auteur?). En fait, cette différence doit être liée à la question de savoir si la correction gamma est utilisée [1].
Une méthode pour implémenter les niveaux de gris en Java
Si vous recherchez "Java implémente GraysCale", la plupart d'entre eux sont une méthode (code):
public void grayImage () lève ioException {file file = new File (System.getProperty ("user.dir") + "/ test.jpg"); BufferedImage Image = ImageIo.Read (fichier); int width = image.getWidth (); int height = image.getheight (); BufferedImage GrayImage = new BufferedImage (largeur, hauteur, bufferedImage.type_byte_gray); for (int i = 0; i <width; i ++) {for (int j = 0; j <height; j ++) {int rgb = image.getrgb (i, j); greyImage.setrgb (i, j, rgb); }} File newFile = new File (System.getProperty ("user.dir") + "/ méthode1.jpg"); ImageIo.write (GrayImage, "JPG", newfile); }L'image d'origine de Test.jpg est:
Le diagramme en niveaux de gris obtenue en utilisant la méthode ci-dessus:
Voir cette image en niveaux de gris semble être possible, mais si nous utilisons opencv pour atteindre la niveale des gris ou utiliser PIL (Python), vous constaterez que les effets varient considérablement:
img = cv2.imread ('test.jpg', cv2.imread_color) gris = cv2.cvtcolor (img, cv2.color_bgr2Gray) cv2.imwrite ('pythonMeth.jpg', gris) On peut clairement voir que le graphique en niveaux de gris obtenu en utilisant opencv (il en va de même pour PIL) est bien meilleur que la méthode obtenue par la méthode Java ci-dessus, et de nombreux détails peuvent être vus. Cela montre que cette méthode populaire sur Internet a toujours eu un problème, mais elle a été ignorée.
Comment atteindre la niveale des gris dans OpenCV
Si vous avez lu des livres ou des codes liés à opencv , vous pouvez probablement savoir qu'OpenCV opencv utilise la méthode de pondération. La raison en est que c'est à peu près parce que nous ne savons pas pourquoi les images opencv en niveaux de gris sont si bonnes. Y a-t-il d'autres détails de traitement que nous ignorons?
Vérifier notre supposition est très simple. Vérifiez simplement les modifications avant et après la valeur des pixels. Vous pouvez le tester comme suit:
img = cv2.imread ('test.jpg', cv2.imread_color) h, w = img.shape [: 2] gris = cv2.cvtcolor (img, cv2.color_bgr2gray) pour j dans range (w): pour i dans la gamme (h): print str (i) + ":" + str (j) + "" + str (i) [J] IMG [H-1] [W-1] [0: 3]Il est difficile pour nous de juger autant de pixels ci-dessous, mais nous n'avons qu'à prêter attention au dernier point de pixels et nous pouvons trouver des indices: la valeur RGB du dernier point de pixels dans l'image d'origine est de 44, 67, 89, et la valeur après le grisonnement est de 71. Elle correspond simplement à la valeur de gris calculée par la méthode de pondération. Si vous vérifiez les valeurs de pixels de l'image qui a été grisée en Java auparavant, vous constaterez que non seulement les valeurs de pixel ne répondent pas à cette formule, mais que vous êtes même loin les unes des autres.
À ce stade, nous supposons qu'OpenCV (y compris PIL) est une implémentation en niveaux de gris utilisant la méthode de pondération.
Java implémente la méthode pondérée en niveaux de gris
Si cette méthode populaire sur Internet ne fonctionne pas, comment devrions-nous utiliser Java pour réaliser des niveaux de gris? En fait, [3] a réussi (plusieurs méthodes) en niveaux de gris (les amis étrangers sont toujours très puissants en technologie), et seul le code nécessaire est extrait ici:
private static int colortorgb (int alpha, int rouge, int verte, int blue) {int newpixel = 0; newPixel + = alpha; newPixel = newPixel << 8; newPixel + = rouge; newPixel = newPixel << 8; newPixel + = vert; newPixel = newPixel << 8; newPixel + = bleu; retourner NewPixel; } public static void main (String [] args) lève ioException {bufferedImage BufferedImage = ImageIo.read (nouveau fichier (System.getProperty ("user.dir" + "/test.jpg")); bufferedImage GrayImage = new Buffereddimage (buttereDimage.getTyPeePee; pour (int i = 0; i <BufferedImage.getwidth (); i ++) {pour (int j = 0; j <butteredImage.GetHeight (); (int) (0,3 * r + 0,59 * g + 0,11 * b) ;; "/ok.jpg"); Le code ci-dessus imprimera les valeurs de pixels à l'échelle grisée. Si vous les comparez avec le code Python ci-dessus, vous constaterez que les valeurs de pixels correspondent complètement. La méthode colorToRGB gère le diagramme de couleur exactement 4 octets, dont le paramètre alpha (comme mentionné précédemment). La figure suivante est l'image en niveaux de gris de ce code:
Pour d'autres méthodes, la même chose peut être obtenue à son tour.
Résumer
La raison de cet article est d'utiliser Java pour implémenter plusieurs opérations en niveaux de gris et d'utiliser OpenCV pour vérifier le bon ou le mal de la conversion. Cependant, certains problèmes ont été trouvés dans les tests réels (il existe des différences dans les images converties et comment générer des images en niveaux de gris basées sur les valeurs en niveaux de gris après conversion), et certaines pensées et vérifications ont été faites à ce sujet. Il convient de noter ici que certains articles sur Internet ont plus ou moins fait de réflexion (et beaucoup d'entre eux sont même copiés, en particulier les articles domestiques), et pour ces problèmes pratiques, la mise en œuvre pratique et la vérification est une méthode très importante. J'espère que le contenu de cet article sera utile à tout le monde. Si vous avez des questions, veuillez laisser un message à discuter.