使用OpenCV对像素操作,交换两张图片的B通道和G通道

0 背景

双目摄像头输出就是左边和右边两个摄像头的传感器数据,在经过摄像头板载的DSP传输到电脑后,会产生两张图片文件。看到网上有人把两张图片合成,做出了3D电影中的效果。我也想尝试一下。

1 环境

OpenCV3.4.2和OpenCV3.1.0都可以。C++。

2 原理

opencv读取了彩色图片后,获得的Mat文件每个像素都有三个通道的数据,分别是BGR(蓝色绿色红色)。找到了读取像素的例程,在其中修改即可。

3 代码

#include <iostream>
#include <chrono>
using namespace std;

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

int main ( int argc, char** argv )
{
    // 读取argv[1]指定的图像
    cv::Mat image1, image2, imageDst;
    image1 = cv::imread ( "left01.jpg" ); //cv::imread函数读取指定路径下的图像
    image2 = cv::imread ( "right01.jpg" );

    // 判断图像文件是否正确读取
    if (( image1.data == nullptr ) ||  ( image2.data == nullptr ) ) //数据不存在,可能是文件不存在
    {
        cerr<<"文件"<<argv[1]<<"不存在."<<endl;
        return 0;
    }
    
    cout << "CV_VERSION: " << CV_VERSION << endl << endl;
    // 文件顺利读取, 首先输出一些基本信息
    cout<<"图像1宽为"<<image1.cols<<",高为"<<image1.rows<<",通道数为"<<image1.channels()<<endl;
    cout<<"图像2宽为"<<image2.cols<<",高为"<<image2.rows<<",通道数为"<<image2.channels()<<endl;
    cout<<image1.size()<<endl;
    cv::imshow ( "image", image1 );      // 用cv::imshow显示图像
    cv::waitKey ( 0 );                  // 暂停程序,等待一个按键输入
    // 判断image的类型
    if ( image1.type() != CV_8UC1 && image1.type() != CV_8UC3 )
    {
        // 图像类型不符合要求
        cout<<"请输入一张彩色图或灰度图."<<endl;
        return 0;
    }

    imageDst = cv::Mat::zeros(image1.size(), CV_8UC3);
    // 遍历图像, 请注意以下遍历方式亦可使用于随机像素访问
    // 使用 std::chrono 来给算法计时
    chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
    for ( size_t y=0; y<imageDst.rows; y++ )
    {
        for ( size_t x=0; x<imageDst.cols; x++ )
        {
            // 访问位于 x,y 处的像素
            // 用cv::Mat::ptr获得图像的行指针
            unsigned char* row_ptr = imageDst.ptr<unsigned char> ( y );  // row_ptr是第y行的头指针
            unsigned char* data_ptr = &row_ptr[ x*imageDst.channels() ]; // data_ptr 指向待访问的像素数据
        unsigned char* row_ptr1 = image1.ptr<unsigned char> ( y );
            unsigned char* data_ptr1 = &row_ptr1[ x*image1.channels() ];

        unsigned char* row_ptr2 = image2.ptr<unsigned char> ( y );
            unsigned char* data_ptr2 = &row_ptr2[ x*image2.channels() ];

            // 输出该像素的每个通道,如果是灰度图就只有一个通道
            for ( int c = 0; c != imageDst.channels(); c++ )
            {
        if(c==0)               
            data_ptr[c] = data_ptr1[0];        //B
        else if(c==1)               
            data_ptr[c] = data_ptr2[1];       //G
        else if(c==2)               
            data_ptr[c] = data_ptr1[2];    //R
            }
        }
    }
    chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
    chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>( t2-t1 );
    cout<<"遍历图像用时:"<<time_used.count()<<" 秒。"<<endl;

    cv::imshow ( "imageDst", imageDst );      // 用cv::imshow显示图像
    cv::waitKey ( 0 );                  // 暂停程序,等待一个按键输入
    // 对于图像还有很多基本的操作,如剪切,旋转,缩放等,限于篇幅就不一一介绍了,请参看OpenCV官方文档查询每个函数的调用方法.
    cv::destroyAllWindows();
    return 0;
}

4 结果

左边摄像头图像(图片在opencv的samples\data\内):

右边摄像头图像(图片在opencv的source\samples\data\内):

合成后:

5 小结

本文的知识点比较简单。就是像素操作,加上图像合成中使用到的G和B通道交换。这样的输出效果图就可以看到两张图片的大概形状。

参考资料:利用红蓝分色原理制作三维图片与三维视频

猜你喜欢

转载自blog.csdn.net/qq_27158179/article/details/83098914