博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SiftGPU一些细节整理
阅读量:2050 次
发布时间:2019-04-28

本文共 4955 字,大约阅读时间需要 16 分钟。

联合opencv开发

static int  IsSimpleGlFormat(unsigned int gl_format, unsigned int gl_type){	//the formats there is a cpu code to conver rgb and downsample	return (gl_format == GL_LUMINANCE || gl_format == GL_LUMINANCE_ALPHA ||		gl_format == GL_RGB || gl_format == GL_RGBA ||		gl_format == GL_BGR || gl_format == GL_BGRA) &&		(gl_type == GL_UNSIGNED_BYTE || gl_type == GL_FLOAT || gl_type == GL_UNSIGNED_SHORT);}

GL_LUMINANCE - 亮度

GL_LUMINANCE_ALPHA 亮度+透明度

对于图像的长和宽,灰度和彩色不影响,直接用哪个都行

cv::Mat img1 = cv::imread("../../data/img3.ppm", 1);cv::Mat grayImg1;cv::cvtColor(img1, grayImg1, CV_BGR2GRAY);int width1 = grayImg1.cols;int height1 = grayImg1.rows;sift->RunSIFT(width1, height1, img1.data, GL_BGR, GL_UNSIGNED_BYTE);

假如输入图像是灰度图怎么办,接下来应该怎么处理?

sift->RunSIFT(width1, height1, grayImg1.data, GL_LUMINANCE, GL_UNSIGNED_BYTE);

有一些博客写的是:

sift->RunSIFT(width2, height2, grayImg2.data, GL_INTENSITY8, GL_UNSIGNED_BYTE);

这是错误的!!!!!

还有

让SiftGPU不显示输出信息:

这个本来想取消输出log,后来想想也不差这点时间的优化,就算了

 

 

关于SiftGPU,还有一些内存释放的问题:

我加载dll后,使用FreeLibrary无法实现实时的释放,等待很久都无果,参考网上教程,发现SiftGPU有一些内存释放的问题

参考文档:

SiftGPU (Cg/GLSL/CUDA) for Matlab:

SiftGPU不自动释放GL context的bug及其修正方法:


阅读SiftGPU的代码可以发现,SiftGPU的CreateContextGL()函数调用GlobalUtil类的静态方法GlobalUtil::CreateWindowEZ()创建了一个静态的LiteWindow对象实例,供GLSL程序使用。代码在GlobalUtil.cpp内,如下:

int GlobalUtil::CreateWindowEZ(){	static LiteWindow window;    return CreateWindowEZ(&window);}

注意,这个LiteWindow对象不是以指针形式声明的,而且整个程序再没有销毁过该LiteWindow对象,即便SiftGPU被销毁之后,这个对象仍然存在,直到包含SiftGPU的对象被析构或者包含SiftGPU的函数退出——此时LiteWindow对象依然存在,但是其GL上下文已经丢失,相关指针变为野指针

这种机制为后面的程序带来了隐藏的bug:如果我们在主程序结束前都不析构包含SiftGPU的对象,等到主程序结束时再由系统自动销毁,则程序不会出现任何问题。但是如果我们一运行完SiftGPU的功能就把包含SiftGPU的对象析构了,然后再等主程序结束,就会出现LiteWindow对象无法被析构的错误——因为该对象已经在析构包含SiftGPU的对象时产生了野指针,系统再对其回收就会出现问题。

其实wuchangchang的这个代码本意是把GlobalUtil类设计成一个单体(singleton),只创建一个LiteWindow实例。然而由于该对象不是以指针形式声明的,所以导致无法主动销毁。为了修正这个bug,我们需要对GlobalUtil的代码进行一些修改,将其变成一个完全的单体模式。修改方法如下:

1)打开GlobalUtil.h,删除

static int  CreateWindowEZ(LiteWindow* window);

把方法

static int  CreateWindowEZ();

改为

static LiteWindow*  CreateWindowEZ(); 

添加一个保护的静态成员变量

protected:

    static LiteWindow *m_pWindow;  

添加一个销毁实例的方法:

 static void DestroyWindowEZ();

2)打开GlobalUtil.cpp

删除int GlobalUtil::CreateWindowEZ(LiteWindow* window)和int GlobalUtil::CreateWindowEZ()的代码

添加如下代码:

LiteWindow *GlobalUtil::m_pWindow = NULL;
LiteWindow*  GlobalUtil::CreateWindowEZ(){	if (m_pWindow == NULL)	{		m_pWindow = new LiteWindow;	}	if (!m_pWindow->IsValid())	{		m_pWindow->Create(_WindowInitX, _WindowInitY, _WindowDisplay);	}	if (m_pWindow->IsValid())	{		m_pWindow->MakeCurrent();	}	else	{		std::cerr << "Unable to create OpenGL Context!\n";		std::cerr << "For nVidia cards, you can try change to CUDA mode in this case\n";	}	return m_pWindow;}void GlobalUtil::DestroyWindowEZ(){	if (m_pWindow != NULL)	{		delete m_pWindow;		m_pWindow = NULL;	}}

3)在SiftGPU.h中的SiftGPU类和SiftMatchGPU类分别添加:

SIFTGPU_EXPORT virtual void DestroyContextGL();

SiftGPU: 

SiftMatchGPU:

4)在SiftGPU.cpp中添加:

void SiftGPU::DestroyContextGL(){	return GlobalUtil::DestroyWindowEZ();}

在SiftMatchGPU.cpp中添加: 

void SiftMatchGPU::DestroyContextGL(){	GlobalUtil::DestroyWindowEZ();}

5)修改SiftGPU.h中的

SIFTGPU_EXPORT int  CreateLiteWindow(LiteWindow* window); 

改为:

SIFTGPU_EXPORT LiteWindow*  CreateLiteWindow(); 

6)修改GlobalUtil.cpp中的

int CreateLiteWindow(LiteWindow* window)

改为:

LiteWindow*  CreateLiteWindow(){	return GlobalUtil::CreateWindowEZ();}

 

7)在自己的代码中使用完Sift的地方,手动调用析构GL context的函数

假设变量:SiftGPU *pSift;

pSift->DestroyContextGL();

或者:SiftMatchGPU *pSiftMatch;

pSiftMatch->DestroyContextGL();

具体调用哪句,视最后使用哪个对象而定。

效果大家已经看到了,终于可以运行到代码

#ifdef SIFTGPU_DLL_RUNTIME	FREE_MYLIB(hsiftgpu);#endif

 以下的部分,之前因为存在野指针的问题,导致,无法干净的释放,程序一直卡在FreeLibrary

当然这一块也存在一些属于我自己的疑问:

如果调用函数手动释放,还需要使用delete sift 

参考博客:

new和delete运算符用于动态分配和撤销内存的运算符

new用法:

1.开辟单变量地址空间

1)new int;  //开辟一个存放数组的存储空间,返回一个指向该存储空间的地址.int *a = new int 即为将一个int类型的地址赋值给整型指针a. 

2)int *a = new int(5) 作用同上,但是同时将整数赋值为5

2.开辟数组空间

一维: int *a = new int[100];开辟一个大小为100的整型数组空间

二维: int **a = new int[5][6]

三维及其以上:依此类推.

一般用法: new 类型 [初值]

delete用法:

1. int *a = new int;

delete a;   //释放单个int的空间

2.int *a = new int[5];

delete [] a; //释放int数组空间

要访问new所开辟的结构体空间,无法直接通过变量名进行,只能通过赋值的指针进行访问.

用new和delete可以动态开辟,撤销地址空间.在编程序时,若用完一个变量(一般是暂时存储的数组),下次需要再用,但却又想省去重新初始化的功夫,可以在每次开始使用时开辟一个空间,在用完后撤销它.


delete 的作用先调用析构,然后释放空间

最后我仔细看了SiftGPU的改进

void SiftGPU::DestroyContextGL(){    return GlobalUtil::DestroyWindowEZ();}void SiftMatchGPU::DestroyContextGL(){    GlobalUtil::DestroyWindowEZ();}

语句调用了DestroyWindowEZ

void GlobalUtil::DestroyWindowEZ(){	if (m_pWindow != NULL)	{		delete m_pWindow;		m_pWindow = NULL;	}}

只是对

static LiteWindow *m_pWindow;

的释放

我们再看一下

delete sift;

会先调用析构函数:

SiftGPU::~SiftGPU(){	if(_pyramid) delete _pyramid; 	delete _texImage;	delete _list;    delete[] _imgpath;    delete[] _outpath;}

delete matcher;

会先调用析构函数:

SiftMatchGPU::~SiftMatchGPU(){	if(__matcher) delete __matcher;}

之前没用过这种用法,在类中定义类自己的指针 

所以我们最后应该是这样的:

sift->DestroyContextGL();	matcher->DestroyContextGL();	delete sift;	delete matcher;

为了验证我们测试下: 

转载地址:http://hcwlf.baihongyu.com/

你可能感兴趣的文章
剑指offer 57. 删除链表中重复的结点
查看>>
剑指offer 58. 链表中环的入口结点
查看>>
剑指offer 59. 把字符串转换成整数
查看>>
剑指offer 60. 不用加减乘除做加法
查看>>
leetcode 热题 Hot 100-3. 合并两个有序链表
查看>>
leetcode 热题 Hot 100-4. 对称二叉树
查看>>
Leetcode C++《热题 Hot 100-12》226.翻转二叉树
查看>>
Leetcode C++《热题 Hot 100-13》234.回文链表
查看>>
Leetcode C++《热题 Hot 100-14》283.移动零
查看>>
Leetcode C++《热题 Hot 100-15》437.路径总和III
查看>>
Leetcode C++《热题 Hot 100-16》448.找到所有数组中消失的数字
查看>>
Leetcode C++《热题 Hot 100-17》461.汉明距离
查看>>
Leetcode C++《热题 Hot 100-18》538.把二叉搜索树转换为累加树
查看>>
Leetcode C++《热题 Hot 100-19》543.二叉树的直径
查看>>
Leetcode C++《热题 Hot 100-21》581.最短无序连续子数组
查看>>
Leetcode C++《热题 Hot 100-22》2.两数相加
查看>>
Leetcode C++《热题 Hot 100-23》3.无重复字符的最长子串
查看>>
Leetcode C++《热题 Hot 100-24》5.最长回文子串
查看>>
Leetcode C++《热题 Hot 100-26》15.三数之和
查看>>
Leetcode C++《热题 Hot 100-27》17.电话号码的字母组合
查看>>