C++ OpenCV:获取 3 通道 RGB 图像,拆分通道并仅使用 R+G 查看图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20341910/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 23:04:10  来源:igfitidea点击:

OpenCV: Taking a 3 channel RGB image, splitting channels and viewing an image with only R+G

c++opencv

提问by Sriharsha

I wanted to look at only the R+G channels in an RGB image because I get better contrasts to detect an object when the Blue channel is removed. I used OpenCV to split the channels,but while merging the same after setting the blue channel to 0, my code doesn't compile.

我只想查看 RGB 图像中的 R+G 通道,因为当蓝色通道被移除时,我可以获得更好的对比度来检测对象。我使用 OpenCV 来拆分通道,但是在将蓝色通道设置为 0 后合并相同的通道时,我的代码无法编译。

#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;
}

Could I have any feedback on where I'm going wrong? I suspect it is with setting the blue channel to 0. Is there any better way to set it to 0?Is there a way to use cvMixChannels() to do this?

我可以对我出错的地方有任何反馈吗?我怀疑是将蓝色通道设置为 0。有没有更好的方法将其设置为 0?有没有办法使用 cvMixChannels() 来做到这一点?

回答by Haris

You need to change these lines

您需要更改这些行

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

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

to

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

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

Edit

编辑

As per your comment here is the full code and result.

根据您的评论,这里是完整的代码和结果。

#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;
}

Source image

源图像

enter image description here

在此处输入图片说明

Result without blue component

结果不含蓝色成分

enter image description here

在此处输入图片说明

回答by Adi Shavit

The most efficient way to do this is without any splits and merges. This saves both time and memory.

最有效的方法是不进行任何拆分和合并。这样既节省时间又节省内存。

Just bitwise-AND your image with cv::Scalar(0,255,255)and this will set your blue channel to zero.

只需按位与您的图像与cv::Scalar(0,255,255),这会将您的蓝色通道设置为零。

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

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

回答by Sriharsha

Alright, I got to work using mixChannels():I have attached an addition to the code snippet above:

好的,我开始使用 mixChannels():我在上面的代码片段中附加了一个附加内容:

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);

Thanks Harsha

谢谢哈沙

回答by sturkmen

another way is subtracting Scalar(255,0,0)from source image

另一种方法是Scalar(255,0,0)从源图像中减去

#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;
}