CUDA入门3.1——使用CUDA实现鱼眼转全景图(OpenCV环节)

CUDA入门3.1——使用CUDA实现鱼眼转全景图(OpenCV环节)_第1张图片

思路

1,通过某种方法获取图片数据,并且了解数据结构。
2,通过某种数学公式将鱼眼画面处理成全景图。
3,通过CUDA并行运算实现鱼眼转全景图功能。
本篇主要讲述OpenCV获取图片以及指针的使用,与CUDA无关。

获取图片数据

OpenCV环境配置

1 下载OpenCV

OpenCV 下载驿站(百度云盘下载,同步更新)

2 配置OpenCV开发环境

配置的方法网上很多,可以查找。我用的是 OpenCV环境配置,以下的代码都是依据这样的环境配置做开发,直接copy可能会报错。

3 编写头文件

我原想把所有功能都集中在一个CUDA文件中,但因为IDE在CUDA环境下写代码时很不方便,另外以后维护的话也不方便。所以还是一步步来做吧。

#ifndef _OPENCV_H_
#define _OPENCV_H_

#include "include_openCV/opencv2/opencv.hpp"

#pragma comment(lib, "opencv_world320.lib")

using namespace cv;
using namespace std;

typedef enum IHC_RESULT
{
    IHC_OK,
    IHC_ERROR
};
class opencv_hander
{
public:
    IHC_RESULT GetImgData(Mat **outdata);
protected:
private:
};
#endif // !_OPENCV_H_

3.1 定义状态枚举

typedef enum IHC_RESULT
{
    IHC_OK,
    IHC_ERROR
};

为什么前缀是叫IHC_?o(=•ェ•=)m 我也不清楚是什么简写,公司大牛挺喜欢这么简写,不知道具体定义,不过用起来反而舒服,不会因为过于具体而限制它的使用范围。

3.2 定义一个接口

IHC_RESULT GetImgData(Mat **outdata);

这里使用了一个双重指针,一个头疼的东西。曾想过使用一重指针解决,但因为没办法使用引用导致数据处理完后传不出来而作罢。

4 创建C++文件

#include "OpenCVHeader.h"

IHC_RESULT opencv_hander::GetImgData(Mat **outdata) {

    Mat img = imread("fish2sphere180.jpg");

    if (img.empty()) {
        return IHC_ERROR;
    }

    int width = img.cols, height = img.rows;

    *outdata =new Mat();
    **outdata = Mat(height, width, CV_8UC3);

    memcpy((**outdata).data, img.data, width * height * 3);

    return IHC_OK;
}

4.1 关于指针

*outdata =new Mat();
**outdata = Mat(height, width, CV_8UC3);
memcpy((**outdata).data, img.data, width * height * 3);

指针头疼很久,画了几张纸才略微明白是怎么使用的。推荐阅读C 语言指针怎么理解?和 指针究竟有什么用?。
*outdata =new Mat();做的事情是定义了**outdata的类型。而**outdata = Mat(height, width, CV_8UC3);做的事情是分配了一段空间用来存储数据。CV_8UC3是OpenCV里对图片格式的定义(8位色深三通道),这里我读取的图和期望使用的图都是RGB格式,因此使用CV_8UC3,当然还有其他格式,比如YUV422 BGRA等等,他们都有各自的数据格式。memcpy的目的就是将img.data的数据拷贝给**outdata。

5 添加程序入口

#include "Cuda.cuh"
#include "OpenCVHeader.h"
#include 

void printf_usage()
{
    printf("\n**********************************************\n");
    printf("q: quit\n");
    printf("**********************************************\n");
}

int main() {
    input_engine cudainput;
    cudainput.initCUDA();
    printf_usage();
    opencv_hander opencvhander;
    Mat *imgdata = NULL;
    opencvhander.GetImgData(&imgdata);
    namedWindow("img3", CV_WINDOW_FREERATIO);
    imshow("img3", *imgdata);
    waitKey(0);
    destroyWindow("img3");

START:
    if ('q' != _getch()) {
        goto START;
    }
    return 0;
}

5.1 添加头文件OpenCVHeader.h

这里使用的还是之前的代码,所写的功能都是在之前代码基础上的添加,之后的功能也是如此。

5.2 拷贝数据

opencv_hander opencvhander;
Mat *imgdata = NULL;
opencvhander.GetImgData(&imgdata);

这里需要注意指针需要初始化,在通过GetImgData(&imgdata)的方法将之前获取到的图片信息拷贝到imgdata里。

5.3 测试

namedWindow("img3", CV_WINDOW_FREERATIO);
imshow("img3", *imgdata);
waitKey(0);
destroyWindow("img3");

namedWindow()方法是提供控制弹出窗口大小的接口,CV_WINDOW_FREERATIO可以实现窗口的自由缩放。
waitKey()方法目的是为了等待键盘输入,好往下执行。如果不这么做,goto START;这个方法会一直执行,导致图片还来不及显示就卡死。
destroyWindow()方法是为了关闭窗口。
这段测试代码不是很好的解决方案。
CUDA入门3.1——使用CUDA实现鱼眼转全景图(OpenCV环节)_第2张图片


12.15更新

可以用引用的方法规避指针带来的麻烦。
头文件添加代码:

IHC_RESULT GetImgData(Mat &outdata);    //直接对引用进行处理

具体实现:

IHC_RESULT opencv_hander::GetImgData(Mat &outdata) {
    Mat img = imread("fish2sphere180.jpg"); 
    if (img.empty()) {
        return IHC_ERROR;
    }

    img.copyTo(outdata);

    return IHC_OK;
}

入口的修改:

    //方法一
    /*Mat *imgdata = NULL;
    opencvhander.GetImgData(&imgdata);
    Mat outImg = Mat::zeros(imgdata->rows, imgdata->cols, CV_8UC3);*/
    //方法二
    Mat imgdata;
    opencvhander.GetImgData(imgdata);

你可能感兴趣的:(CUDA,&,OpenCV,cuda,opencv)