1. 程式人生 > >OpenCV+ MFC 對影象的讀取、顯示、儲存

OpenCV+ MFC 對影象的讀取、顯示、儲存

一、安裝和配置

安裝opencv,vc6.0配置工程目錄
Include目錄:
E:\PROGRAM FILES\OPENCV\OPENCV1.0\CV\INCLUDE
E:\PROGRAM FILES\OPENCV\OPENCV1.0\CVAUX\INCLUDE
E:\PROGRAM FILES\OPENCV\OPENCV1.0\CXCORE\INCLUDE
E:\PROGRAM FILES\OPENCV\OPENCV1.0\ML\INCLUDE
E:\PROGRAM FILES\OPENCV\OPENCV1.0\OTHERLIBS\HIGHGUI
E:\PROGRAM FILES\OPENCV\OPENCV1.0\OTHERLIBS\CVCAM\INCLUDE
Lbirary目錄:
E:\PROGRAM FILES\OPENCV\OPENCV1.0\LIB
Source目錄:
E:\PROGRAM FILES\OPENCV\OPENCV1.0\CV\SRC
E:\PROGRAM FILES\OPENCV\OPENCV1.0\CVAUX\SRC
E:\PROGRAM FILES\OPENCV\OPENCV1.0\CXCORE\SRC
E:\PROGRAM FILES\OPENCV\OPENCV1.0\ML\SRC
E:\PROGRAM FILES\OPENCV\OPENCV1.0\OTHERLIBS\HIGHGUI
E:\PROGRAM FILES\OPENCV\OPENCV1.0\OTHERLIBS\CVCAM\SRC

建立MFC工程
新增連結庫 cv.lib cvaux.lib cxcore.lib ml.lib highgui.lib cvcam.lib
StdAfx.h中新增

#include <cv.h>
#include <highgui.h>
#include "Processing.h" 

注意: 安裝opencv過程中,勾選新增路徑到系統變數。工程建立好之後,若提示缺少dll檔案,就把opencv安裝目錄下的bin資料夾裡面的所有dll複製到系統C盤的windows/ system32 (64位系統為sysWOW64)中去。

二、Doc類操作

1、文件類doc.h

新增成員

IplImage*   pImg;           // 讀入影象檔案的原始點陣圖
int m_Display;              // 影象顯示標記
CString m_filepath;         // 影象路徑

過載開啟文件虛擬函式

virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);

2、文件類doc.cpp

(1) 構造

pImg = NULL; 
m_Display = -1;     // 初始為-1
m_filepath="";

(2) 析構

if (pImg)   cvReleaseImage(&pImg);

(2) 過載開啟文件虛擬函式

在類檢視中,右鍵CxxxDoc名稱,點選“Add VirtuAl Function …”,雙擊左邊列表中“OnOpenDocument”,確定。

BOOL CxxxDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
    if (!CDocument::OnOpenDocument(lpszPathName))
        return FALSE;
    // TODO: Add your specialized creation code here
    m_filepath = lpszPathName; 

    /*  選擇一副臨時影象    */
    IplImage* pTempImg=NULL;
    pTempImg = cvLoadImage(lpszPathName,-1);      
    if (!pTempImg) 
    {
        AfxMessageBox("Load Image Error!");
        return FALSE;
    }                   

    /*  影象儲存在Doc類成員  */
    if (pImg)   
        cvReleaseImage(&pImg);
    pImg=cvCreateImage(cvGetSize(pTempImg),pTempImg->depth,pTempImg->nChannels);    
    cvCopy(pTempImg,pImg);  // 複製影象
    cvReleaseImage(&pTempImg);  // 釋放臨時影象

    //pImg=cvCloneImage(pTempImg);//可代替上面三行 (但易造成記憶體洩漏,推薦用cvCopy)

    m_Display = 0;          // 讀取到影象後為0
    return TRUE;
}

三、View類操作

1、檢視類View.h

新增成員變數

IplImage* saveImg;      // 備份點陣圖
IplImage* workImg;      // 工作點陣圖
// workImg的資訊;
int m_nHeight, m_nWidth, m_nWidthStep, m_nChannels, m_nDepth;

2、檢視類View.cpp

(1) OnDraw()函式處理

void CModificationView::OnDraw(CDC* pDC)
{
    CModificationDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here

    if (pDoc->pImg != NULL)         //  有磁碟輸入影象
    {
        if (pDoc->m_Display == 0)   // 磁碟中有新影象, 未顯示
        {
            // 釋放原影象
            if (workImg) cvReleaseImage(&workImg);
            if (saveImg) cvReleaseImage(&saveImg);

            // 重新分配空間
            CvSize size= cvGetSize(pDoc->pImg);
            int dep = pDoc->pImg->depth;
            int chan = pDoc->pImg->nChannels;

            workImg= cvCreateImage(size,dep,chan);
            saveImg= cvCreateImage(size,dep,chan);

            // 拷貝影象
            cvCopy(pDoc->pImg,workImg);
            cvCopy(pDoc->pImg,saveImg);

            m_ImageType = imageType(workImg);   //影象型別

            pDoc->m_Display = 1;    // 顯示標記,置1
        }
    }

    if (workImg) //  重新整理視窗畫面
    {
        // 影象基本資訊
        m_nWidth    = workImg->width;
        m_nHeight   = workImg->height;
        m_nWidthStep= workImg->widthStep;
        m_nChannels = workImg->nChannels;
        m_nDepth    = workImg->depth;

        // 設定滾動條 -- 需要設定檢視積累為ScrollView,否者刪除下面3行
        CSize  sizeTotal;
        sizeTotal = CSize(workImg->width,workImg->height);
        SetScrollSizes(MM_TEXT,sizeTotal); 

        // 顯示
        RECT rect;      // 使用CvvImage類繪圖函式的必要引數
        rect.top = 0;
        rect.left=0;
        rect.bottom=m_nHeight;
        rect.right=m_nWidth;

        HDC hDC = pDC->GetSafeHdc() ;   //pDC->m_hDC;this->m_hDc  // 獲取輸出物件控制代碼, ::GetDC(m_hWnd)為全域性函式
        CvvImage image;
        image.CopyOf(workImg,workImg->nChannels);
        image.DrawToHDC(hDC, &rect);    //  image.Show(hDC,0,0,m_nWidth,m_nHeight); // 採用cv繪圖方式,原點在左下角。

        image.Destroy();
    }
}

(2) 儲存影象

對按鈕“另存為“(ID_FILE_SAVE_AS)新增訊息響應函式

void CModificationView::OnFileSaveAs() 
{
    // TODO: Add your command handler code here
    if (!workImg)
    {   
        MessageBox("Current View has no image!");
        return;
    }

    CString csBMP="BMP Files(*.BMP)|*.BMP|";
    CString csJPG="JPG Files(*.JPG)|*.JPG|";
    CString csTIF="TIF Files(*.TIF)|*.TIF|";
    CString csPNG="PNG Files(*.PNG)|*.PNG|";
    CString csDIB="DIB Files(*.DIB)|*.DIB|";
    CString csPBM="PBM Files(*.PBM)|*.PBM|";
    CString csPGM="PGM Files(*.PGM)|*.PGM|";
    CString csPPM="PPM Files(*.PPM)|*.PPM|";
    CString csSR ="SR  Files(*.SR) |*.SR|";
    CString csRAS="RAS Files(*.RAS)|*.RAS||";

    CString csFilter=csBMP+csJPG+csTIF+csPNG+csDIB
        +csPBM+csPGM+csPPM+csSR+csRAS;

    CString name[]={"","bmp","jpg","tif","png","dib",
        "pbm","pgm","ppm","sr", "ras",""};

    CString strFileName;
    CString strExtension;

    CFileDialog FileDlg(false,NULL,NULL,OFN_HIDEREADONLY,csFilter);
    //  檔案存檔對話方塊
    if (FileDlg.DoModal()==IDOK ) //  輸入了檔名
    {        
        strFileName = FileDlg.m_ofn.lpstrFile;
        if (FileDlg.m_ofn.nFileExtension == 0) //  無檔案字尾
        {  
            strExtension = name[FileDlg.m_ofn.nFilterIndex];
            strFileName = strFileName + '.' + strExtension;
            //  加檔案字尾
        }

        cvSaveImage(strFileName,workImg);   //  當前畫面存檔  
    }
}