您的位置:首页 > 运维架构

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

2017-12-13 13:25 483 查看


思路

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 <conio.h>

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()方法是为了关闭窗口。

这段测试代码不是很好的解决方案。



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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: