寫教學的最大目的是教會未來的自己

openCV

OpenCV cvWaitKey(int delay)的使用方法

參考資料http://jackiechensuper.blogspot.tw/2013/02/cvwaitkey.html

 

在openCV 中,如果要顯示圖片、影片常常會用到這個function,其原意是等但使用者按按鈕,且等待多久

主要放在cvShowImage() 之後,可以當作控製播放速度,他的單位是ms

以下面為範例就是等待10ms 如果在這中間有按按鈕,就會繼續下去。

c = cvWaitKey(10);
printf(\”%c,%d\”,c,c)

 

如果是永久等代直到按下按鈕,可以寫成

c = cvWaitKey(0);
printf(\”%c,%d\”,c,c)

Post to Twitter Post to Plurk Post to Facebook Send Gmail

openCV Mat的儲存與讀取

之前已經寫過兩篇 關於openCV 資料的儲存與讀取,今天又找到一個方便的方法

儲存架構同樣式XML

 

參考資料  http://blog.csdn.net/mmjwung/article/details/6913540

 

寫入

Mat mat = Mat::eye(Size(12,12), CV_8UC1);  //這沒差

 FileStorage fs(".\\vocabulary.xml", FileStorage::WRITE);  //檔案名稱用 XML

 fs<<"vocabulary"<<mat;  

 fs.release();  

 

讀取

FileStorage fs(".\\vocabulary.xml", FileStorage::READ);  

 Mat mat_vocabulary;  

 fs["vocabulary"] >> mat_vocabulary;  

 

經過測試,一個檔案可以分別寫入多個MAT 然後讀取。

Post to Twitter Post to Plurk Post to Facebook Send Gmail

openCV 記憶體釋放要注意

引用自http://blog.csdn.net/xiaowei_cqu/article/details/7586847

 

1、內存洩露

內存洩露是說沒有釋放已經不能使用的內存,這裡一般指堆的內存才需要顯示的釋放。比如用malloc,calloc,realloc,new分配的 內存是在堆上的,需要用free,delete顯示的回收。內存洩露最明顯的一是程序很慢,在運行程序時你可以啟動任務管理器,會看到程序佔用的內存一直 「砰砰砰」的往上漲:

最後直接崩潰,或者你關閉程序的時候也會異常退出,出現

Debug Assertion Failed!
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

之類的問題。

除了new的對象我們知道要delete。OpenCV中使用cvCreateImage()新建一個IplImage*,以及使用cvCreateMat()新建一個CvMat*,都需要cvReleaseImage()  cvReleaseMat()顯示的釋放

 

  1. IplImage* subImg=cvCreateImage( cvSize((img->width)*scale,(img->height)*scale), 8, 3 );  
  2. CvMat *tempMat=cvCreateMat((img->width)*scale,(maxFace->height)*scale,CV_MAKETYPE(image->depth,image->nChannels));  
  3. cvReleaseImage(&subImg);  
  4. cvReleaseMat(&tempMat);  

另外一些函數要用到 CvSeq*來存放結果(通常這些都要用cvCreateMemStorage()事先分配一塊內存CvMemStorage*),都要是釋放掉相應的內存,這是很難找的。

 

比如從二值圖像中尋找輪廓的函數cvFindContours():

 

  1. CvMemStorage* m_storage=cvCreateMemStorage(0);  
  2. CvSeq * m_contour=0;  
  3. cvFindContours( img, m_storage, &m_contour, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));  
  4. //釋放內存  
  5. cvReleaseMemStorage(&m_storage);  

以及人臉識別中檢測人臉的函數:

 

 

  1. CvMemStorage* m_storage=cvCreateMemStorage(0);  
  2. CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );  
  3. CvSeq* faces = cvHaarDetectObjects( img, cascade, m_storage,1.1, 2, 0,cvSize(30, 30) );  
  4. //釋放內存  
  5. cvReleaseMemStorage( &faces->storage);  
  6. cvReleaseHaarClassifierCascade( &cascade );  

注意這裡我們可以使用
cvReleaseMemStorage( &faces->storage);
來釋放m_storate,也可以使用:
cvReleaseMemStorage(&m_storage);
釋放內存,這是等效的,但一定不要用兩次!!

 

2、一塊內存多次釋放

對應沒有釋放內存,對應就是一個內存釋放多次,如同上面的 cvReleaseMemStorage用了兩次。可能報錯的地方:

 

  1. __declspec(noinline)  
  2. void __cdecl _CRT_DEBUGGER_HOOK(int _Reserved)  
  3. {  
  4.     /* assign 0 to _debugger_hook_dummy so that the function is not folded in retail */  
  5.     (_Reserved);  
  6.     _debugger_hook_dummy = 0;  
  7. }  

或者: Unhandled exception at XXXXXXXXXX in XXX.exe: XXXXXXXXXXX: 堆已損壞。 

 

除了上述的MemStorge問題,使用cvQueryFrame()取出CvCapture*每幀圖像,只需在最後釋放CvCapture*,不需要釋放IplImage*

 

  1. CvCapture* pCapture = cvCreateCameraCapture(-1);  
  2. IplImage* pFrame=cvQueryFrame( pCapture );  
  3. cvReleaseCapture(&pCapture);  

*這篇是以前寫的,其實還是建議大家用C++接口的OpenCV,內存問題很少了~

Post to Twitter Post to Plurk Post to Facebook Send Gmail

openCV K-means的用法

最近為了去雜訊,測視使用了 k-means的方法減少,效果不錯,有效解決因為少數雜訊影響重心位置

參考資料

http://forum.gamer.com.tw/C.php?bsn=60292&snA=1518

http://www.aishack.in/2010/08/k-means-clustering-in-opencv/

http://rritw.com/a/bianchengyuyan/C__/20121123/258942.html

 

這三篇教學文當中,我使用第一篇的範力十分簡單好懂

第二篇視所有參數的英文說明

第三篇是中文說明

 

本文教學開始

 

    Mat model(Data.size(),2, CV_32F );//sample

//建立一個矩陣 每一筆資料 一個row,cow代表維度,這次我是算點作標 所以是二維

    vector<Point *>::iterator tempPoint; //事先算好的點陣列
    int i=0;

//把資料塞入矩陣中
    for(tempPoint=Data.begin();tempPoint!=Data.end();tempPoint++,i++)
    {
        model.at<float>(i,0)=(*tempPoint)->x;
        model.at<float>(i,1)=(*tempPoint)->y;
    }
    
    int k=2; //要分幾群
    Mat cluster; //會跑出結果,紀錄每個row 最後是分配到哪一個cluster
    int attempts = 2;//應該是執行次數
    Mat centers; //記錄那個cluster的值
    //使用k means分群
    kmeans(model, k, cluster,TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10, 1), attempts,KMEANS_PP_CENTERS,centers );

    //,TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10, 1),  這裡有三個參數,決定k-means何時結束,第二個參數是指迭代最大次數,第三個參數是精確度多少,第一個參數是指依照前兩個參數的哪一個為準,以範例中就是兩者都參照,以 or 的方式決定

 

 

//以下是因為我指是用這方法去雜訊,所以要找出最多點的地方
    int countMAX=0;
    int MAXIndex;
    int *tempSum =new int[k];
    memset(tempSum,0,sizeof(int)*k);
    for(int i=0;i<Data.size();i++)
    {
        tempSum[cluster.at(i,0)]++;
        if(tempSum[cluster.at(i,0)]>countMAX)
        {
            countMAX=tempSum[cluster.at(i,0)];
            MAXIndex=cluster.at<int>(i,0);
        }
    }
    Point result(centers.at<float>(MAXIndex, 0),centers.at<float>(MAXIndex, 1));

 

 

Post to Twitter Post to Plurk Post to Facebook Send Gmail

OpenCV SURF 儲存方式

資料來源http://blog.csdn.net/lovenessless/article/details/8077012

 

 

//objectKeypoints這些都是cvSeq*   即cvSeq指針

 

CvFileStorage *fs;

fs = cvOpenFileStorage("data.xml", storage, CV_STORAGE_WRITE);

//open file cvWrite(fs, "objectKeypoints", objectKeypoints);

cvWrite(fs, "objectDescriptors", objectDescriptors);

cvWrite(fs, "imageKeypoints", imageKeypoints);

cvWrite(fs, "imageDescriptors", imageDescriptors);

cvReleaseFileStorage(&fs);

 

 

讀取:

 

//objectKeypoints這些都是cvSeq*   即cvSeq指針

    

CvFileStorage *fs;

 

    fs = cvOpenFileStorage("data.xml", storage, CV_STORAGE_READ);

    objectKeypoints = (CvSeq*) cvReadByName(fs, 0, "objectKeypoints");

    objectDescriptors = (CvSeq*)cvReadByName(fs, 0, "objectDescriptors",0);

    imageKeypoints = (CvSeq*)cvReadByName(fs, 0, "imageKeypoints",0);

    imageDescriptors = (CvSeq*)cvReadByName(fs, 0, "imageDescriptors",0);

 

    cvReleaseFileStorage(&fs);

 

 

Post to Twitter Post to Plurk Post to Facebook Send Gmail

openCV的IplImage 與 Mat 相互換轉

OpenCV針對這兩種轉換方式是採用記憶體共享,由於因為記憶體共享,所以任何一方作改變 都會改變原始的數值

(1)IplImage to Mat

Ex.
IplImage* pImg = cvLoadImage(“lena.jpg”);
cv::Mat img(pImg,0); //0是不複製影像,也就是pImg與img的data共用同個記憶體位置,header各自有

(2)Mat to IplImage

Ex.
IplImage* pImg = cvLoadImage(“lena.jpg”);
cv::Mat img(pImg,0); //img拿到pImg的data
IplImage qImg;
qImg = IplImage(img); //一樣檔案沒複製,所以qImg.imageData就是指向pImg->imageData

Post to Twitter Post to Plurk Post to Facebook Send Gmail

Copyright © 2024. All Rights Reserved.

歡迎光臨
初音