久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

在MFC中使用OpenCV

 mscdj 2016-01-14

Image:CVMFC-GUI.png

目錄

[隱藏]

例程下載

例程源代碼下載

OpenCV與MFC

OpenCV是計(jì)算機(jī)視覺(jué)自由軟件的寶庫(kù),。但是,,由于歷史的原因它的軟件主要采用類似DOS操作系統(tǒng)的命令行方式,使用十分不便,,這也影響了它的推廣,。如果能將它應(yīng)用到VC++文檔結(jié)構(gòu)中就好了。OpenCV程序在MFC中實(shí)現(xiàn)的方法通常是采用CvvImage類,,這個(gè)類的成員函數(shù)DrawToHDC可將位圖整體經(jīng)縮放后顯示到視圖窗口中,,解決了位圖的顯示問(wèn)題,也就解決了OpenCV在MFC中的使用問(wèn)題,。但是,,也有兩個(gè)致命的弱點(diǎn),一是顯示方式不合圖像處理使用習(xí)慣,,二是位圖必須采用CvvImage類,。顯示方面,雖然已經(jīng)能夠察看圖像,,但當(dāng)位圖與窗口的長(zhǎng)寬比不一致時(shí)會(huì)造成圖像失真,,這是瀏覽器的顯示習(xí)慣,并不適用于圖像處理應(yīng)用。圖像采集與處理的使用習(xí)慣是顯示比例1:1,,圖像未經(jīng)縮放,,顯示畫(huà)面可按窗口大小進(jìn)行裁剪并可使用滾動(dòng)條選擇顯示部位,。數(shù)據(jù)結(jié)構(gòu)方面,,采用CvvImage類以后程序中所有位圖必須修改成這個(gè)類,這對(duì)于利用大量OpenCV現(xiàn)成軟件來(lái)說(shuō)是十分不方便的,。顯然,,在VC++文檔結(jié)構(gòu)中使用OpenCV,其關(guān)鍵還是在于OpenCV位圖在MFC中的顯示,。因此,,有必要先比較一下兩者的位圖結(jié)構(gòu),然后尋找新的解決方法,。

StretchDIBits 函數(shù)

由于OpenCV位圖結(jié)構(gòu)中的像素?cái)?shù)據(jù)與DIB中的像素具有類似的存儲(chǔ)結(jié)構(gòu),,可以考慮直接用來(lái)在視圖窗口中顯示。知道位圖像素的存放地址直接往視圖窗口顯示的函數(shù)雖然不多,,但還是有Windows API中的StretchDIBits函數(shù)可以利用,,由下面列出的StretchDIBits函數(shù)原型中可知,只要為它構(gòu)造一個(gè)DIB的位圖信息就行了,。

int StretchDIBits(
    HDC hdc,                        //  顯示設(shè)備句柄
    int XDest, YDest, nDestWidth, nDestHeight, //  目標(biāo)矩形區(qū)域參數(shù)
    int XSrc, YSrc, nSrcWidth, nSrcHeight,     //  源矩形區(qū)域參數(shù)
    //  源區(qū)域與目標(biāo)區(qū)域參數(shù)相同時(shí)為 1:1 比例顯示
    CONST VOID *lpBits,             //  位圖的像素存放首地址
    CONST BITMAPINFO *lpBitsInfo,   //  位圖信息存放地址
    UINT iUsage,                    //  位圖中的顏色類型,,RGB模式用DIB_RGB_COLORS
   DWORD dwRop                     //  像素操作碼,簡(jiǎn)單復(fù)制用SRCCOPY
);

為此,,演示程序CCVMFC中增加了3個(gè)函數(shù),,即CtreateMapInfo、imageClone與imageReplace,。其中,,CtreateMapInfo 函數(shù)用于建立OpenCV位圖的位圖信息,其特點(diǎn)是可以為單通道位圖設(shè)置黑白灰階調(diào)色板,。ImageClone函數(shù)使用OpenCV函 數(shù)實(shí)現(xiàn)位圖的復(fù)制,,自動(dòng)釋放老的指針?biāo)赶虻拇鎯?chǔ)單元以防止內(nèi)存泄漏,同時(shí)返回的m_dibFlag標(biāo)志可以用于激發(fā)刷新工 作位圖workImg的位圖信息m_lpBmi (見(jiàn)后面說(shuō)明),。imageReplace與ImageClone相似,,但不建立新位圖,只用輸入位圖替 換輸出位圖,。

LPBITMAPINFO  CtreateMapInfo(IplImage* workImg)    //  建立位圖信息
{                                           
    BITMAPINFOHEADER BIH={40,1,1,1,8,0,0,0,0,0,0};
    LPBITMAPINFO lpBmi;
    int          wid, hei, bits, colors,i;
    RGBQUAD  ColorTab[256];
    wid =workImg->width;     hei =workImg->height;
    bits=workImg->depth*workImg->nChannels;
    if (bits>8) colors=0;
    else colors=1<<bits;
    lpBmi=(LPBITMAPINFO) malloc(40+4*colors);
    BIH.biWidth   =wid;     BIH.biHeight  =hei;
    BIH.biBitCount=(BYTE) bits;
    memcpy(lpBmi,&BIH,40);                   //  復(fù)制位圖信息頭
    if (bits==8) {                           //  256 色位圖
        for (i=0;i<256;i++)  {                //  設(shè)置灰階調(diào)色板
           ColorTab[i].rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE) i;
       }
       memcpy(lpBmi->bmiColors, ColorTab, 1024);
    }
    return(lpBmi);
}
int  imageClone(IplImage* pi, IplImage** ppo)  //  復(fù)制 IplImage 位圖 (OpenCV)
{
   if (*ppo)
       cvReleaseImage(ppo);                    //  釋放原來(lái)位圖
    (*ppo) = cvCloneImage(pi);                  //  復(fù)制新位圖
    return(true);
}

演示程序

演示程序CVMFC采用VC++多文檔帶滾動(dòng)條結(jié)構(gòu),,圖像的存放與處理則采用OpenCV的位圖結(jié)構(gòu)與函數(shù),圖像的顯示通過(guò)建立相應(yīng)的位圖信息m_lpBmi來(lái)實(shí)現(xiàn),,為了便于管理對(duì)m_lpBmi的操作集中在OnDraw程序中,。待顯示位圖結(jié)構(gòu)發(fā)生改變時(shí)用m_dibFlag標(biāo)志激發(fā)m_lpBmi的刷新。除了文件結(jié)構(gòu)與圖像顯示外,其馀部分基本上都是OpenCV程序,。


位圖數(shù)據(jù):

CVMFCDoc中,, pImg (讀入圖像文件所得原始位圖)

CVMFCView中, workImg (工作位圖),、saveImg (備份位圖),、m_lpBmi (工作位圖的位圖信息)

CVDSCap中, m_Frame (視頻采集所得位圖)


視圖的顯示管理集中在OnDraw函數(shù)中:

void CCVMFC0View::OnDraw(CDC* pDC)
{
  ……                             //  其馀部分內(nèi)容
  if (m_dibFlag) {                         //  刷新 DIB位圖信息
     if (m_lpBmi)
           free(m_lpBmi);
     m_lpBmi = CtreateMapInfo(workImg);
     m_dibFlag = 0;
  }
  if (workImg) {                            //  刷新視圖窗口
     StretchDIBits(pDC->m_hDC, 
                  0, 0, workImg->width, workImg->height,
                  0, 0, workImg->width, workImg->height,
                  workImg->imageData, m_lpBmi, DIB_RGB_COLORS, SRCCOPY);
  }
}

像素?cái)?shù)據(jù)類型

圖像處理主要是對(duì)像素?cái)?shù)據(jù)的處理,。需要注意的是,,在OpenCV中像素存放地址imageData為char* 類型。因此,,在圖像處理時(shí)必須轉(zhuǎn)換成BYTE* 類型才可以使用,。下面以識(shí)別圖像類型函數(shù)imageType為例來(lái)作說(shuō)明。

int  imageType(IplImage* p)         //  識(shí)別圖像類型
{
   int     i,j,k,bpl,n,pg[256];
   BYTE *buf;
   k=p->nChannels;                    //  1 與 3 分別表示灰階圖像與彩色圖像
   if ( k==1 ) {                      //  檢查二值圖像
       for ( i = 0; i < 256; i++ ) pg[i] = 0;
      buf = (BYTE*) p->imageData;     //  修改像素?cái)?shù)據(jù)類型
       bpl = p->widthStep;
      for ( i = 0; i < p->height; i++ ) {
          for ( j = 0; j < p->width; j++) pg[buf[j]]++;  //  直方圖統(tǒng)計(jì)
            buf += bpl;
      }
      for ( i = 0, n = 0; i < 256; i++ ) 
         if (pg[i]) n++;               //  統(tǒng)計(jì)使用色階數(shù)
       if (n == 2) k = -1;              //  -1 表示二值圖像
   }
   return(k);
}

圖像鏡像

在位圖的像素方面,,除了imageData的類型問(wèn)題外,,DIB位圖與IplImage結(jié)構(gòu)間還有一個(gè)顯著的不同,那就是坐標(biāo)原點(diǎn)位置的不同,。前者的坐標(biāo)原點(diǎn)在位圖底部左側(cè),,而后者在頂部左側(cè)。因此,,當(dāng)在OpenCV中需要使用MFC的函數(shù)顯示時(shí)位圖應(yīng)作垂直鏡像,,反之亦然。典型的例子是在OpenCV中調(diào)用DirectShow視頻采集程序CameraDS中的獲取當(dāng)前幀函數(shù)QueryFrame,,其程序如下:

IplImage* CCameraDS::QueryFrame()
{
  ……
  m_pSampleGrabber->GetCurrentBuffer(&m_nBufferSize, (long*) m_pFrame->imageData);
  cvFlip(m_pFrame);
  return m_pFrame;
}

演示程序CVMFC的圖像輸入輸出采用OpenCV的cvLoadImage與cvSaveImage函數(shù)實(shí)現(xiàn),,而顯示采用Windows API中的 StretchDIBits函數(shù)。為了能正常工作,,圖像讀入后需作垂直鏡像,,圖像存盤(pán)前也需作垂直鏡像。也就是說(shuō),,內(nèi)存中存放的是 經(jīng)過(guò)垂直鏡像的OpenCV位圖,。同樣,因?yàn)榻Y(jié)構(gòu)相同,,它也是DIB位圖的像素?cái)?shù)據(jù),。

BOOL CCVMFCDoc::Load(IplImage** pp,LPCTSTR csFileName)
{
  IplImage* pImg=NULL;
  pImg = cvLoadImage(csFileName,-1);    //  讀圖像文件
   if (!pImg) return(false);
   cvFlip(pImg);                        //  使與 DIB 像素結(jié)構(gòu)一致
   if (*pp)  
        cvReleaseImage(pp);
   (*pp)=pImg;
   m_Display=0;
   return(true);
}
BOOL CCVMFCDoc::Save(LPCTSTR csFileName,IplImage* pImg)
{
  int   bl;
  cvFlip(pImg);                           //  恢復(fù)原 OpenCV 位圖結(jié)構(gòu)
   bl=cvSaveImage(csFileName,pImg);        //  圖像存盤(pán)
   return(bl);
}

對(duì)于大多數(shù)的圖像處理算法來(lái)說(shuō)位圖的鏡像與否沒(méi)有什么影響。但是,,對(duì)于某些OpenCV函數(shù),,例如涉及旋轉(zhuǎn)方向以及需要往IplImage結(jié)構(gòu)的位圖上繪制圖形、顯示文字時(shí)就會(huì)使位置出錯(cuò),。這時(shí)就需要與存盤(pán)時(shí)一樣先作垂直鏡像,,旋轉(zhuǎn)角度反向,,操作結(jié)束返回Windows視圖顯示處理結(jié)果時(shí)再轉(zhuǎn)換回來(lái)。

驅(qū)動(dòng)模式與人機(jī)交互

眾所周知,,DOS操作系統(tǒng)采用過(guò)程驅(qū)動(dòng)與文本模式,,Windows操作系統(tǒng)采用事件驅(qū)動(dòng)與圖形模式,它們分別使用鍵盤(pán)與鼠標(biāo)器作為主要輸入工具,。OpenCV編程環(huán)境基于DOS操作系統(tǒng),,因此顯示圖像需要調(diào)用cvNamedWindow函數(shù)建立專門(mén)的窗口,然后調(diào)用cvShowImage函數(shù)進(jìn)行顯示,。畫(huà)面的保持則使用cvWaitKey(0)語(yǔ)句,,或使用內(nèi)含cvWaitKey語(yǔ)句的死循環(huán)來(lái)實(shí)現(xiàn),。為了避免出現(xiàn)死機(jī)故障,,出現(xiàn)OpenCV函數(shù)所開(kāi)窗口時(shí),務(wù)必使用ESCAPE鍵關(guān)閉窗口并退出,。注意:菜單中帶 (ESC) 字樣的命令必須使用ESCAPE鍵退出,。

同時(shí),OpenCV編程環(huán)境人機(jī)交互的功能有限,,只有鼠標(biāo),、鍵盤(pán)與滑動(dòng)條。其中,,鼠標(biāo)與滑動(dòng)條屬于事件驅(qū)動(dòng),,而鍵盤(pán)屬于過(guò)程驅(qū)動(dòng)。由于沒(méi)有菜單功能,,只能使用鍵盤(pán)命令控制程序走向并等待鍵盤(pán)輸入選擇不同功能,。

在驅(qū)動(dòng)模式方面為了便于比較,提供了兩個(gè)[點(diǎn)集凸包]命令,,一個(gè)采用過(guò)程驅(qū)動(dòng),,另一個(gè)采用事件驅(qū)動(dòng),不妨比較具體功能及其實(shí)現(xiàn)的程序,。

程序移植例

演示程序CVMFC中待處理圖像與處理結(jié)果都放在工作位圖workImg中,。同時(shí),工作位圖workImg也是窗口畫(huà)面顯示的內(nèi)容,。所以,,處理程序中僅源圖像的獲取與結(jié)果圖像的顯示與OpenCV中的程序有所不同,中間處理部分可以完全相同,,現(xiàn)以《學(xué)習(xí)OpenCV》一書(shū)中的例2-6為例來(lái)作修改說(shuō)明,。

void CCVMFC0View::OnCannyBorddetec()       //  Canny 邊緣檢測(cè)
{                         //  根據(jù)《學(xué)習(xí)OpenCV》例 2-6 改編
 //  定義工作位圖
  IplImage* pImage;
  IplImage* pImg8u = NULL;
  IplImage* pImg8uSmooth = NULL;
  IplImage* pImgCanny = NULL;
  //**  輸入待處理圖像  **                //  修改部分 1
  pImage = workImg;
  //  建立輔助位圖
  pImg8u =cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
  pImg8uSmooth=cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
  pImgCanny =cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
  //  圖像處理
  cvCvtColor(pImage, pImg8u,CV_BGR2GRAY);
  cvSmooth(pImg8u, pImg8uSmooth,CV_GAUSSIAN,3,0,0);
  cvCanny(pImg8uSmooth, pImgCanny,100,200,3);
  //  釋放位圖
  cvReleaseImage(&pImg8u);
  cvReleaseImage(&pImg8uSmooth);
  //**  輸出處理結(jié)果  **                  //  修改部分 2
  m_dibFlag = ImageReplace(pImgCanny, &workImg);
  //**  設(shè)置標(biāo)志及刷新窗口  ** 
  m_ImageType=1;
  Invalidate();
}

形參書(shū)寫(xiě)順序

演示程序CVMFC是Windows API系統(tǒng)與OpenCV兩種體系函數(shù)的混合使用,而它們的函數(shù)參數(shù)的書(shū)寫(xiě)習(xí)慣是不同的,,極容易引起混淆,。這里作一簡(jiǎn)要說(shuō)明,,請(qǐng)看下面例子:

目標(biāo)參數(shù)Dest <-- 源參數(shù)Src

C:
memcpy( pDest, pSrc, size);
Windows API:
BitBlt( hDestDC, 0, 0, wid, hei, hSrcDC, 0, 0, SRCCOPY);
VC++:
pDestDC->BitBlt( 0, 0, p->wid, p->hei, pSrcDC, 0, 0, SRCCOPY);

源參數(shù)Src --> 目標(biāo)參數(shù)Dest

OpenCV:
cvCvtColor( pSrcImg, pDestcImg, CV_BGR2GRAY);
cvSmooth( pSrcImg, pDestcImg, CV_GAUSSIAN, 3, 0, 0);

演示程序中除了OpenCV函數(shù)采用后一書(shū)寫(xiě)形式外,其他函數(shù)都采用前一書(shū)寫(xiě)形式,,千萬(wàn)注意不能混淆,。OpenCV函數(shù)很 容易辨認(rèn),都以前綴cv-開(kāi)頭,,如cvCvtColor,、cvSmooth。新增函數(shù)ImageClone與imageReplace因?yàn)檎{(diào)用OpenCV函數(shù),, 故也采用后一書(shū)寫(xiě)形式,。

CVMFC 1.1版菜單

[文件]:打開(kāi)圖像、恢復(fù)圖像,、關(guān)閉當(dāng)前窗口,、保存當(dāng)前位圖、恢復(fù)原始圖像,、當(dāng)前畫(huà)面存盤(pán),、退出

[點(diǎn)處理]:彩色變灰階、圖像反相,、垂直鏡像,、水平鏡像、180 度旋轉(zhuǎn),、30 度旋轉(zhuǎn),、仿射變換、透視變換,、亮度變換,、灰階圖像直方圖、直方圖均衡化

[鄰域處理]:鄰域平均,、Gauss 濾波,、中值濾波、Sobel 邊緣檢測(cè),、Laplace 邊緣檢測(cè)

[二值化]:選擇閾值,、選擇閾值(原位圖)、自適應(yīng)閾值法,、基本全局閾值法

[二值圖像處理]:點(diǎn)集最小區(qū)域,、外接矩形、最小面積矩形,、多邊形逼近,、點(diǎn)集凸包、點(diǎn)集凸包 (事件驅(qū)動(dòng)),、區(qū)域凸包,、區(qū)域凹差,、輪廓跟蹤、距離變換

[形態(tài)學(xué)處理]:腐蝕,、膨脹,、開(kāi)運(yùn)算、閉運(yùn)算,、形態(tài)學(xué)梯度,、頂帽變換、波谷檢測(cè)

[彩色圖像處理]:RGB 分量,、HSV 分量,、Lab 分量、RGB 分量 (C),、XYZ 分量,、YCrCb 分量、Luv 分量,、二維直方圖,、鄰域平均,、Gauss 濾波,、中值濾波、Sobel 邊緣檢測(cè),、Laplace 邊緣檢測(cè)

[綜合處理例]:圖像縮小,、徑向梯度、Canny 算法,、Hough 變換 (直線),、"Hough 變換 (圓)、平行四邊形檢測(cè),、連通區(qū)域填充,、金字塔法圖像分割、橢圓曲線擬合,、Snake 原理,、分水嶺原理、角點(diǎn)檢測(cè),、點(diǎn)集聚類,、分割二維點(diǎn)集、旋轉(zhuǎn)點(diǎn)跟蹤,、人臉檢測(cè)

[動(dòng)態(tài)檢測(cè)]:動(dòng)態(tài)邊緣檢測(cè),、L_K 算法光流跟蹤、背景建模檢測(cè),、運(yùn)動(dòng)目標(biāo)檢測(cè),、彩色目標(biāo)跟蹤,、人臉檢測(cè)二

[視頻采集播放]:?jiǎn)?dòng)攝像頭、打開(kāi) AVI 文件,、視頻解凍,、視頻凍結(jié)、多圖像平均,、關(guān)閉視頻,、選擇采樣分辨率

[圖形及其他]:繪制圖形、繪制 Delaunay 圖形,、極坐標(biāo)變換,、DFT 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多