OpenCV: prendre une image RVB à 3 canaux, diviser les canaux et regarder une image avec seulement R+G

je voulais seulement regarder les canaux R+G dans une image RVB parce que j'obtiens de meilleurs contrastes pour détecter un objet lorsque le canal bleu est enlevé. J'ai utilisé OpenCV pour séparer les canaux,mais en fusionnant la même chose après avoir réglé le canal bleu à 0, mon code ne se compile pas.

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    if( argc != 2)
    {
     cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
     return -1;
    }

    Mat image,fin_img;
    image = imread(argv[1], CV_LOAD_IMAGE_COLOR);   // Read the file

    if(! image.data )                              // Check for invalid input
    {
        cout <<  "Could not open or find the image" << std::endl ;
        return -1;
    }

   namedWindow( "Display window", CV_WINDOW_AUTOSIZE );// Create a window for display.
                      // Show our image inside it.

    // Create Windows
    namedWindow("Red",1);
    namedWindow("Green",1);
    namedWindow("Blue",1);

    // Create Matrices (make sure there is an image in input!)

    Mat channel[3];
    imshow( "Original Image", image ); 


    // The actual splitting.
    split(image, channel);


   channel[0]=Mat::zeros(Size(image.rows, image.cols), CV_8UC1);//Set blue channel to 0

    //Merging red and green channels

    merge(channel,image);
    imshow("R+G", image);

    waitKey(0);//Wait for a keystroke in the window
    return 0;
}

Pourrais-je avoir des commentaires sur ce que je vais mal? Je pense que c'est en mettant le canal bleu à 0. Y a-t-il un meilleur moyen de le mettre à 0?Est-il possible d'utiliser cvMixChannels() cette?

22
demandé sur Sriharsha 2013-12-03 06:46:05

4 réponses

vous devez changer ces lignes

    channel[0]=Mat::zeros(Size(image.rows, image.cols), CV_8UC1);//Set blue channel to 0

    //Merging red and green channels
    merge(channel,image);

    channel[0]=Mat::zeros(image.rows, image.cols, CV_8UC1);//Set blue channel to 0

    //Merging red and green channels
    merge(channel,3,image);

Modifier

Comme par votre commentaire voici le code complet et le résultat.

#include <iostream>
#include "opencv2/opencv.hpp"
#include <stdio.h>    

using namespace cv;
using namespace std;

int main( int argc, char** argv )
{
    if( argc != 2)
    {
     cout <<" Usage: display_image ImageToLoadAndDisplay" << endl;
     return -1;
    }

    Mat image,fin_img;
    image = imread("bgr.png", CV_LOAD_IMAGE_COLOR);   // Read the file

    if(! image.data )                              // Check for invalid input
    {
        cout <<  "Could not open or find the image" << std::endl ;
        return -1;
    }

   namedWindow( "Display window", CV_WINDOW_AUTOSIZE );// Create a window for display.
                      // Show our image inside it.

    // Create Windows
    namedWindow("Red",1);
    namedWindow("Green",1);
    namedWindow("Blue",1);

    // Create Matrices (make sure there is an image in input!)

    Mat channel[3];
    imshow( "Original Image", image );


    // The actual splitting.
    split(image, channel);


   channel[0]=Mat::zeros(image.rows, image.cols, CV_8UC1);//Set blue channel to 0

    //Merging red and green channels

    merge(channel,3,image);
    imshow("R+G", image);
    imwrite("dest.jpg",image);

    waitKey(0);//Wait for a keystroke in the window
    return 0;
}

image Source

enter image description here

résultat sans composant bleu

enter image description here

32
répondu Haris 2013-12-04 06:02:50

Bon, j'ai eu à travailler à l'aide de mixChannels():j'ai joint un plus à l'extrait de code ci-dessus:

Mat gr( image.rows, image.cols, CV_8UC3);

// forming an array of matrices is a quite efficient operation,
// because the matrix data is not copied, only the headers
   Mat out[] = {gr};
// bgr[1] -> gr[1],
// bgr[2] -> gr[2], 
int from_to[] = {1,1, 2,2 };
mixChannels( &image, 1, out, 2, from_to, 2 );

imshow("R+G",gr);

Merci Harsha

6
répondu Sriharsha 2013-12-04 02:17:16

la façon la plus efficace de faire ceci est sans aucune division et fusion. Cela permet d'économiser du temps et de la mémoire.

juste bitwise-et votre image avec cv::Scalar(0,255,255) et ceci permettra de définir votre canal bleu à zéro.

Comme dans: imshow("R+G", src & cv::Scalar(0,255,255));.

6
répondu Adi Shavit 2016-03-20 15:17:26

une autre façon est soustrayant Scalar(255,0,0) à partir de la source de l'image

#include <opencv2/opencv.hpp>
using namespace cv;

int main(int argc, char **argv)
{
    Mat src = imread(argv[1], CV_LOAD_IMAGE_COLOR);
    imshow("src", src );
    src -= Scalar(255,0,0);
    imshow("Green and Red channels", src );
    waitKey();
    return 0;
}
4
répondu sturkmen 2016-03-20 10:46:35