66 votes

Convertir RVB en noir et blanc dans OpenCV

Je voudrais savoir comment convertir une image RVB en une image noir et blanc (binaire).

Après la conversion, comment puis-je enregistrer l'image modifiée sur le disque ?

144voto

Jacob Points 22306

A priori, vous devez le convertir en niveaux de gris, puis le seuiller en binaire.

1. Lire l'image comme une image en niveaux de gris Si vous lisez l'image RVB à partir du disque, vous pouvez la lire directement comme une image en niveaux de gris, comme ceci :

// C
IplImage* im_gray = cvLoadImage("image.jpg",CV_LOAD_IMAGE_GRAYSCALE);

// C++ (OpenCV 2.0)
Mat im_gray = imread("image.jpg",CV_LOAD_IMAGE_GRAYSCALE);

2. Convertir une image RVB im_rgb en une image en niveaux de gris : Sinon, vous devrez convertir l'image RVB obtenue précédemment en une image en niveaux de gris.

// C
IplImage *im_rgb  = cvLoadImage("image.jpg");
IplImage *im_gray = cvCreateImage(cvGetSize(im_rgb),IPL_DEPTH_8U,1);
cvCvtColor(im_rgb,im_gray,CV_RGB2GRAY);

// C++
Mat im_rgb  = imread("image.jpg");
Mat im_gray;
cvtColor(im_rgb,im_gray,CV_RGB2GRAY);

3. Convertir en binaire Vous pouvez utiliser seuillage adaptatif o seuils à niveau fixe pour convertir votre image en niveaux de gris en une image binaire.

Par exemple, en C, vous pouvez faire ce qui suit (vous pouvez également faire la même chose en C++ avec Mat et les fonctions correspondantes) :

// C
IplImage* im_bw = cvCreateImage(cvGetSize(im_gray),IPL_DEPTH_8U,1);
cvThreshold(im_gray, im_bw, 128, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

// C++
Mat img_bw = im_gray > 128;

Dans l'exemple ci-dessus, 128 est le seuil.

4. Sauvegarder sur le disque

// C
cvSaveImage("image_bw.jpg",img_bw);

// C++
imwrite("image_bw.jpg", img_bw);

0 votes

En fonction de l'application, il peut être préférable d'effectuer un tramage plutôt qu'un simple seuil.

0 votes

Dans la fonction CvtColor, devons-nous utiliser CV_RGB2GRAY ou CV_BGR2GRAY ? J'ai lu qu'Opencv est basé sur le format BGR et que nous devons l'utiliser, mais dans l'image grise ou binaire, je ne vois pas de différence en utilisant l'un ou l'autre.

3voto

nikithashr Points 55

Cela semble avoir fonctionné pour moi !

Mat a_image = imread(argv[1]);

cvtColor(a_image, a_image, CV_BGR2GRAY);
GaussianBlur(a_image, a_image, Size(7,7), 1.5, 1.5);
threshold(a_image, a_image, 100, 255, CV_THRESH_BINARY);

1voto

AndyUK Points 1493

Je fais quelque chose de similaire dans une de mes articles de blog . Un exemple simple en C++ est présenté.

L'objectif était d'utiliser le logiciel libre cvBlobsLib bibliothèque pour la détection d'échantillons ponctuels imprimés sur des lames de microarray, mais les images doivent être converties de la couleur -> échelle de gris -> noir et blanc comme vous l'avez mentionné, afin d'y parvenir.

0 votes

J'aimerais voir votre travail : les images doivent être converties de couleur -> échelle de gris -> noir et blanc comme vous l'avez mentionné, Merci.

0 votes

Le lien mentionné ci-dessus ne fonctionne pas, celui-ci fonctionne : lien

1voto

alwar Points 404

Une façon simple de "binariser" une image est de la comparer à un seuil : Par exemple, vous pouvez comparer tous les éléments d'une matrice à une valeur avec opencv en c++.

cv::Mat img = cv::imread("image.jpg", CV_LOAD_IMAGE_GRAYSCALE); 
cv::Mat bw = img > 128;

De cette façon, tous les pixels de la matrice supérieurs à 128 sont maintenant blancs, et ceux inférieurs à 128 ou égaux seront noirs.

En option, et pour moi, cela a donné de bons résultats, on peut appliquer le flou.

cv::blur( bw, bw, cv::Size(3,3) );

Plus tard, vous pouvez l'enregistrer comme indiqué précédemment avec :

cv::imwrite("image_bw.jpg", bw);

0 votes

Je ne sais pas... Je pense que cela dépend du type d'image que vous sauvegardez. Pour les photos (je travaillais avec des photos) je pense que c'est le bon format.

1 votes

Le problème du JPEG est qu'il introduit des artefacts et dégrade quelque peu la qualité de votre image. J'utiliserais plutôt le PNG ou, pour les très petits fichiers, le TIFF avec une compression CCITT Fax 4.

0 votes

@user1741137, Comment enregistrer un Mat en tant que TIFF avec une compression CCITT Fax 4 avec OpenCV ? En utilisant Highgui.imwrite("sample.tiff", binaryImage) ; j'obtiens toujours un TIFF avec une compression LZW et une profondeur de couleur de 8 bits - voir ma question ici .

1voto

MD. Nazmul Kibria Points 896

Une simple méthode de seuil binaire est suffisante.

inclure

#include <string>
#include "opencv/highgui.h"
#include "opencv2/imgproc/imgproc.hpp"

using namespace std;
using namespace cv;

int main()
{
    Mat img = imread("./img.jpg",0);//loading gray scale image
    threshold(img, img, 128, 255, CV_THRESH_BINARY);//threshold binary, you can change threshold 128 to your convenient threshold
    imwrite("./black-white.jpg",img);
    return 0;
}

Vous pouvez utiliser GaussianBlur pour obtenir une image noire et blanche lisse.

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