1,通过某种方法获取图片数据,并且了解数据结构。
2,通过某种数学公式将鱼眼画面处理成全景图。
3,通过CUDA并行运算实现鱼眼转全景图功能。
本篇主要讲述OpenCV获取图片以及指针的使用,与CUDA无关。
OpenCV 下载驿站(百度云盘下载,同步更新)
配置的方法网上很多,可以查找。我用的是 OpenCV环境配置,以下的代码都是依据这样的环境配置做开发,直接copy可能会报错。
我原想把所有功能都集中在一个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_
typedef enum IHC_RESULT
{
IHC_OK,
IHC_ERROR
};
为什么前缀是叫IHC_?o(=•ェ•=)m 我也不清楚是什么简写,公司大牛挺喜欢这么简写,不知道具体定义,不过用起来反而舒服,不会因为过于具体而限制它的使用范围。
IHC_RESULT GetImgData(Mat **outdata);
这里使用了一个双重指针,一个头疼的东西。曾想过使用一重指针解决,但因为没办法使用引用导致数据处理完后传不出来而作罢。
#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;
}
*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。
#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;
}
这里使用的还是之前的代码,所写的功能都是在之前代码基础上的添加,之后的功能也是如此。
opencv_hander opencvhander;
Mat *imgdata = NULL;
opencvhander.GetImgData(&imgdata);
这里需要注意指针需要初始化,在通过GetImgData(&imgdata)的方法将之前获取到的图片信息拷贝到imgdata里。
namedWindow("img3", CV_WINDOW_FREERATIO);
imshow("img3", *imgdata);
waitKey(0);
destroyWindow("img3");
namedWindow()方法是提供控制弹出窗口大小的接口,CV_WINDOW_FREERATIO可以实现窗口的自由缩放。
waitKey()方法目的是为了等待键盘输入,好往下执行。如果不这么做,goto START;这个方法会一直执行,导致图片还来不及显示就卡死。
destroyWindow()方法是为了关闭窗口。
这段测试代码不是很好的解决方案。
可以用引用的方法规避指针带来的麻烦。
头文件添加代码:
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);