必须过来怒写一波博客了,遇到这么狗血和奇葩的问题真是不多见,还好解决了!现在分享解决方案给大家^0^
Opencv+VS2015+MFC出现问题:
(1)报错行数:
xmemory0 Line 100:
expression:"(_Ptr_user&(_BIG_ALLOCATION_ALIGNMENT-1))==0"&&0
(2)报错行数:
debug_heap.cpp Line: 892
expression:is_block_type_valid(header->_block_use)
(3)报错行数:
xmemory0 Line 110:
reinterpret_cast(_Ptr_ptr)[-1] ==_BIG_ALLOCATION_SENTINEL);
三个看似不怎么一致的问题,就恰恰出在了一起!也是很令人醉醉的。
不过这三个问题单独来看的话,是没有一个正常的解决方案的,综合多篇在StackOverflow上类似的回答才可以看出,这其实就是一个典型的leaking memory(内存溢出)问题,而在我对图像处理的代码中,用到的最费内存的结构就是一个又一个的不同类型的vector数组了,咋一看并没有什么不妥,因为是C++编程,这些vector都是以局部变量的形式存在的,而我用到了特征检测算法,由于是dense SIFT算法,检测到的特征点会比较多,代码没有被嵌入MFC之前,是可以运行成功的,可当代码被嵌入到事件处理函数中后,奇怪的事情出现了,函数体整个部分没有任何错误,但是在函数结束时,执行return就会出现上述三种错误中的一种,具体出现哪种依据改动的大小而定,这就很令人恼火了,毕竟是两个都好使的代码,按正常手段放到一起照理不应该啊!
类似的错误StackOverflow上有人提出这样的解决方案,供大家参考:
Because the memory of vector is limited, there are too many keypoints. If the keypoints are about 10000:
keypoints.reserve(10000);
但是这是一个只治标不治本的方法,大家可以尝试,真正的问题还是vector导致的leaking memory,那怎么办呢?我突然向导了一个类似的案例,也就是说,当在main()函数中开不出1000000大小的数组时,往往爱把这个大数组定义为全局变量,于是乎,我本着一试的心态,把所有用到的vector全部定义为的全局变量,并在用完之后就调用.clear()函数,将内存释放掉,结果!问题就这样完美的解决啦!程序无bug还是硬道理!
现在附上我不再报错的代码:
vector buff1;
vector buff2;
vector buff3;
vector keyPoints1;
vector keyPoints2;
vector matches; //定义匹配结果变量
vector goodMatches;
vector obj;
vector scene;
void CToolsV1Dlg::OnBnClickedHandle()
{
// TODO: 在此添加控件通知处理程序代码
/*OpenCV2CXimage o2i;
IplImage *iplImage1;
IplImage *iplImage2;
bool okk1 = o2i.Cximage2IplImage(m_pImage1, &iplImage1); ///从Cximage类转换为IplImage类
bool okk2 = o2i.Cximage2IplImage(m_pImage2, &iplImage2);*/
uint8_t* buf1 = NULL;
int32_t len1 = 0;
CxImage cximage1 = *m_pImage1;
bool okk1 =cximage1.Encode(buf1, len1, CXIMAGE_FORMAT_BMP);
uint8_t* buf2 = NULL;
int32_t len2 = 0;
CxImage cximage2 = *m_pImage2;
bool okk2 = cximage2.Encode(buf2, len2, CXIMAGE_FORMAT_JPG);
if (okk1 && okk2)
{
//1.SIFT特征点提取——detect()方法
///Mat srcImg1 = cvarrToMat(iplImage1); ///从IplImage类转换为Mat类
///Mat srcImg2 = cvarrToMat(iplImage2);
buff1.resize(len1);
memcpy(&buff1[0], buf1, len1);
buff2.resize(len2);
memcpy(&buff2[0], buf2, len2);
Mat srcImg1;
Mat srcImg2;
srcImg1=imdecode(buff1, 1);
srcImg2 = imdecode(buff2, 1);
delete []buf1;
delete []buf2;
buff1.clear();
buff2.clear();
Mat srcImg1_copy = srcImg1;
Mat srcImg2_copy = srcImg2;
Mat dstImg1, dstImg2;
DenseFeatureDetector siftDetector;//SiftFeatureDetector是SIFT类的别名
keyPoints1.clear();
keyPoints1.clear();
//2.特征点描述符(特征向量)提取——compute()方法
SiftDescriptorExtractor descriptor;//SiftDescriptorExtractor是SIFT类的别名
Mat description1;
Mat description2;
int step = 10; // 10 pixels spacing between kp's
for (int i = step; i> matcher;//实例化暴力匹配器
matcher.match(description1, description2, matches);//实现描述符之间的匹配
MessageBox(_T("格式转换正确,正在计算......"));
//4.对匹配结果进行筛选(依据DMatch结构体中的float类型变量distance进行筛选)
float minDistance = 100;
float maxDistance = 0;
for (int i = 0; i < matches.size(); i++)
{
if (matches[i].distance < minDistance)
minDistance = matches[i].distance;
if (matches[i].distance > maxDistance)
maxDistance = matches[i].distance;
}
///cout << "minDistance: " << minDistance << endl;
///cout << "maxDistance: " << maxDistance << endl;
for (int i = 0; i < matches.size(); i++)
{
if (matches[i].distance < 3 * minDistance)
{
goodMatches.push_back(matches[i]);
}
}
//5.绘制匹配结果——drawMatches()
Mat dstImg3;
drawMatches(srcImg1, keyPoints1, srcImg2, keyPoints2, goodMatches, dstImg3);
for (int i = 0; i < goodMatches.size(); i++)
{
obj.push_back(keyPoints1[goodMatches[i].queryIdx].pt);
scene.push_back(keyPoints2[goodMatches[i].trainIdx].pt);
}
Mat H = findHomography(scene, obj, CV_RANSAC);
Mat srcImg3;
//Size size(500, 500);
//原图像变形
warpPerspective(srcImg2_copy, srcImg3, H, srcImg2_copy.size());
///srcImg3是最终结果,将其写到磁盘上
imwrite("pic/test3.jpg", srcImg3);
keyPoints1.clear();
keyPoints2.clear();
matches.clear();
goodMatches.clear();
obj.clear();
scene.clear();
/*
OpenCV2CXimage o2i2;
IplImage *iplImage3 = &IplImage(srcImg3);//从Mat类转换为IplImage类
bool okk3 = o2i2.IplImage2Cximage(iplImage3, m_pImage3); //从IplImage类转换为Cximage类
if(okk3)
{
//绘制图像到相应的图像控件上
m_pWnd3 = this->GetDlgItem(IDC_IMAGEC); ////这里一定要和picture Control控件的ID对应起来
DrawImgOnCtrl(m_pImage3, m_pWnd3);
}
else
{
MessageBox(_T("图像类型转换出现问题!"));
}*/
imencode(".jpg", srcImg3, buff3);
CxImage img3(&buff3[0], buff3.size(), CXIMAGE_FORMAT_JPG);
//判断指针是否为空
if (m_pImage3 != NULL)
{
delete m_pImage3;
m_pImage3 = NULL;
}
//开辟内存
m_pImage3 = new CxImage();
m_pImage3 = &img3;
if (!m_pImage3->IsValid())
{
AfxMessageBox(_T("建立图像指针失败!"));
delete m_pImage3;
m_pImage3 = NULL;
return;
}
MessageBox(_T("就差显示了!"));
m_pWnd3 = this->GetDlgItem(IDC_IMAGEC);
DrawImgOnCtrl(m_pImage3, m_pWnd3);
MessageBox(_T("成功显示了呢!"));
}
else
{
MessageBox(_T("请先输入矫正前的两张图像!"));
}
MessageBox(_T("矫正完事儿啦!开心吗?开心^0^,非常开心!哒哒哒"));
}
总结:ACM真的不是白学的!倔强青铜也不是白倔强的!
-------------------------------------这是一条分割线20180330----------------------------------------
用VS运行别人的代码常遇到的错误及解决方法:
error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
这是一个十分常见的错误,最方便的解决办法就是:在c++预处理器中添加_CRT_SECURE_NO_WARNINGS的定义。
具体操作为:
解决方案下,右键项目-->属性-->c/c++-->预处理器-->预处理定义-->点击下拉菜单
添加_CRT_SECURE_NO_WARNINGS,点击确定,应用即可!