1. 程式人生 > >Opencv2.4.9+VS2015+MFC出現問題:expression:"(_Ptr_user&(_BIG_ALLOCATION_ALIGNMENT-1))==0"&&0解決方案

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()函式,將記憶體釋放掉,

結果!問題就這樣完美的解決啦!程式無bug還是硬道理!

現在附上我不再報錯的程式碼:

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,點選確定,應用即可!