宿舍一個哥們經常問我,openCV和openGL有什麼區別,我很裝逼地回答:openCV是處理映像,openGL是圖形。並反問:你知道映像和映像的區別嗎?看來是我有眼不識泰山了,openCV的強大功能遠在我的狹隘認識之上,尤其是那些矩陣的操作,又讓 我回想起了當時看openGL函數的撓頭,但是學還是要學的,言歸正傳,這次用openCV提供的函數,完成一個畫圖板的功能。
功能要求:完成windows畫圖板的功能。
設計實現:核心函數openCV,介面MFC。
---------------------------------------------------------------------------------------------------------------
工具實現:
紅線標註映像中感興趣地區,後台函數將感興趣地區(ROI)儲存。標註感興趣地區採用滑鼠拖動的方式,滑鼠按下時確定ROI矩形框的一角,滑鼠鬆開時確定矩形框的另一角,此兩點確定矩形的主對角線,從而確定矩形。記錄矩形座標,然後使用openCV函數儲存ROI映像。
ROI矩形的記錄屬於細節問題,
關鍵點<1>:雙緩衝。如果不用雙緩衝技術,映像會閃爍,比如我們的程式,每次滑鼠的移動都要引起重繪,重繪過程中閃爍現象很明顯。此時需要雙緩衝技術,網上關於雙緩衝的文章汗牛充棟,本文末會附上相關的連結。我總結雙緩衝技術是為瞭解決兩個關鍵點:①重繪初始時,”白素幀"的插入導致巨大的視覺發差②直接將資料寫入顯存,複雜的顯示過程與映像顯示同時進行。所以你會看到大部分介紹雙緩衝的文章,都會讓你這樣做:①對重繪訊息響應時,直接返回TRUE,以此避免“白素幀”②在重繪函數中,首先將資料寫入一個相容的裝置中,然後進行記憶體的複製。
下面的代碼說明一下雙緩衝的主要技術
CDC dcMem;//裝置描述符的建立,相當於DC的一個對等體,雙緩衝中所有的畫圖操作都在這個對等體中完成。CBitmap bitmapMem;//建立相容位元影像,並將此位元影像裝入記憶體相容裝置環境dcMem.CreateCompatibleDC(pDC);//聲明,我這個裝置描述符是和真正的裝置描述符是對等體。bitmapMem.CreateCompatibleBitmap(pDC,rect.Width(),rect.Height());//對位元影像做類似的聲明CBitmap *pOldBitmapMem=dcMem.SelectObject(&bitmapMem);
做一個比喻。許多人向A君借錢,到要債的時候了,能一個一個去要嗎?可以,但是A君是大忙人,他可不能把大把的時間花在坐飛機去,敲門,要債,喝茶,出門,坐飛機回這樣的瑣事上,於是他和弟弟B說好了--你替我去要債,都要完後,一併把這些錢給我。這樣,同樣的結果--A拿到了錢,但是花費的成本完全不同,坐享其成可比挨家挨戶地要省力多。A君和B君是對等體,同樣在雙緩衝機制中,顯示器的裝置上下文pDC,和我們在OnPaint或者OnDraw中聲明的與之相容的裝置上下文dcMem也是對等體,我們讓所有的計算過程都在弟弟dcMem上完成,然後由它將做好的位元影像一手交給哥哥pDC顯示。如此一來,可不是能夠降低顯示的複雜度了麼,因為複製過程(通過BitBlt函數完成)可比那些計算過程簡單多了。
關鍵點<2>:顯示紅色ROI框時,不能使用openCV裡的cvRectangle函數,這個函數是破壞性的,會直接將源映像中相應的點變成紅色,無法修複。所以,顯示紅色ROI框,我們選用MFC中裝置上下文的相關函數。
好了,這就是一些主要的問題,剩的都是一些小細節的編程問題,本文最後附上一些實現過程中有用的資料,希望可以協助到網友們。
CArray數組的用法:http://www.cnblogs.com/kingln/archive/2008/08/21/1272962.html
Rectangle用法:http://blog.csdn.net/muzi9_17/article/details/6376922
雙緩衝問題: http://blog.csdn.net/zhoxier/article/details/7542371
http://blog.163.com/yuanlong_zheng@126/blog/static/49846449201033093333394/
http://guohaiyang.blog.163.com/blog/static/3213403720081027104147/ VC對話方塊中如何添加WM_ERASEBKGND(OnEraseBkgnd函數)