web-dev-qa-db-fra.com

Accès à chaque canal séparé dans OpenCV

J'ai une image avec 3 canaux (img) et une autre avec un seul canal (ch1).

    Mat img(5,5,CV_64FC3);
    Mat ch1 (5,5,CV_64FC1);

Existe-t-il un moyen efficace (sans utiliser de boucle) de copier le premier canal de img vers ch1?

21
iampat

Il existe une fonction appelée cvMixChannels . Vous aurez besoin de voir l'implémentation dans le code source, mais je parie qu'elle est bien optimisée.

12
Jacek

En fait, si vous voulez simplement copier l'un des canaux ou diviser l'image couleur en 3 canaux différents, CvSplit() est plus approprié (je veux dire simple à utiliser).

Mat img(5,5,CV_64FC3);
Mat ch1, ch2, ch3;
// "channels" is a vector of 3 Mat arrays:
vector<Mat> channels(3);
// split img:
split(img, channels);
// get the channels (dont forget they follow BGR order in OpenCV)
ch1 = channels[0];
ch2 = channels[1];
ch3 = channels[2];
49
orielfrigo

Vous pouvez utiliser la fonction de partage, puis mettre des zéros sur les canaux que vous souhaitez ignorer. Il en résultera la diffusion d'un canal sur trois. Voir ci-dessous..

Par exemple:

Mat img,chans[3]; 
img = imread(.....);  //make sure its loaded with an image

//split the channels in order to manipulate them
split(img,channel);

//by default opencv put channels in BGR order , so in your situation you want to copy the first channel which is blue. Set green and red channels elements to zero.
chans[1]=Mat::zeros(img.rows, img.cols, CV_8UC1); // green channel is set to 0
chans[2]=Mat::zeros(img.rows, img.cols, CV_8UC1);// red channel is set to 0

//then merge them back
merge(chans,3,img);

//display 
imshow("BLUE CHAN",img);
cvWaitKey();
10
techguy18985

Un plus simple si vous avez un RVB à 3 canaux est cvSplit () si je ne me trompe pas, vous avez moins à configurer ... (et je pense qu'il est également bien optimisé).

J'utiliserais cvMixChannel () pour des tâches "plus dures" ...: p (je sais que je suis paresseux).

voici la documentation de cvSplit ()

2
jmartel

Vous pouvez accéder à un canal spécifique, cela fonctionne plus rapidement que l'opération split

Mat img(5,5,CV_64FC3);
Mat ch1;
int channelIdx = 0;
extractChannel(img, ch1, channelIdx); // extract specific channel

// or extract them all
vector<Mat> channels(3);
split(img, channels);
cout << channels[0].size() << endl;
0
Gralex