Opencv2.4.9+VS2015+MFC出現問題:expression:"(_Ptr_user&(_BIG_ALLOCATION_ALIGNMENT-1))==0"&&0解決方案
必須過來怒寫一波部落格了,遇到這麼狗血和奇葩的問題真是不多見,還好解決了!現在分享解決方案給大家^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<uintptr_t *>(_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()函式,將記憶體釋放掉,
現在附上我不再報錯的程式碼:
vector<uchar> buff1;
vector<uchar> buff2;
vector<uchar> buff3;
vector<KeyPoint> keyPoints1;
vector<KeyPoint> keyPoints2;
vector<DMatch> matches; //定義匹配結果變數
vector<DMatch> goodMatches;
vector<Point2f> obj;
vector<Point2f> 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<srcImg1.rows - step; i += step)
{
for (int j = step; j<srcImg1.cols - step; j += step)
{
// x,y,radius
keyPoints1.push_back(KeyPoint(float(j), float(i), float(step)));
}
}
for (int i = step; i<srcImg2.rows - step; i += step)
{
for (int j = step; j<srcImg2.cols - step; j += step)
{
// x,y,radius
keyPoints2.push_back(KeyPoint(float(j), float(i), float(step)));
}
}
descriptor.compute(srcImg1, keyPoints1, description1);//注意原圖和特徵點要對應,不要寫錯
descriptor.compute(srcImg2, keyPoints2, description2);
///imshow("description1", description1);
///imshow("description2", description2);
//3.使用暴力匹配器進行暴力匹配——BruteForceMatcher類的match()方法
BruteForceMatcher<L2<float>> 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); //<span style = "white-space:pre"></span>//這裡一定要和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,點選確定,應用即可!