Je voulais regarder uniquement les canaux R + G dans une image RVB car j'obtiens de meilleurs contrastes pour détecter un objet lorsque le canal bleu est supprimé. J'ai utilisé OpenCV pour diviser les canaux, mais en fusionnant le même après avoir défini le canal bleu sur 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;
}
Puis-je avoir des commentaires sur les erreurs que j'ai commises? Je suppose que c'est en mettant le canal bleu à 0. Y a-t-il une meilleure façon de le mettre à 0? Y a-t-il un moyen d'utiliser cvMixChannels () pour ce faire?
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
Selon 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
Résultat sans composante bleue
D'accord, j'ai commencé à travailler avec mixChannels (): j'ai joint un ajout à 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
La façon la plus efficace de le faire est sans fractionner ni fusionner. Cela économise du temps et de la mémoire.
Juste au niveau du bit ET votre image avec cv::Scalar(0,255,255)
et cela mettra votre canal bleu à zéro.
Comme dans: imshow("R+G", src & cv::Scalar(0,255,255));
.
une autre façon consiste à soustraire Scalar(255,0,0)
de l'image source
#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;
}