MFC3-圖像邊緣處理

前面的創建MFC工程和頁面的設計,這一篇就不在多聊,以後有時間會把這一步單獨做一個介紹。本篇直接從代碼開始:

因爲實現邊緣檢測,所以先在EdgesProcess.h中把頭文件添加進來。如下圖:


在MFC應用程序中我們經常使用類視圖,在這裏面可以添加函數和變量。如圖:


之後在類視圖中CEdgesProcessDlg右鍵添加變量TheImage,變量類型爲IplImage*,變量類型是可以手動添加和修改的。如圖:


之後還是在類視圖中雙擊OnInitDialog(),在提示:“// TODO: Add extra initialization here”的下面添加 TheImage 的初始化代碼:

    CvSize ImgSize;
    ImgSize.height = IMAGE_HEIGHT;
    ImgSize.width = IMAGE_WIDTH;
    TheImage = cvCreateImage( ImgSize, IPL_DEPTH_8U, IMAGE_CHANNELS );
然後按照相同的方法添加函數void ShowImage( IplImage* img, UINT ID ) 和 void ResizeImage(IplImage* img)

void CEdgesProcessDlg::ResizeImage(IplImage* img)
{
    // 讀取圖片的寬和高
    int w = img->width;
    int h = img->height;

    // 找出寬和高中的較大值者
    int max = (w > h)? w: h;

    // 計算將圖片縮放到TheImage區域所需的比例因子
    float scale = (float) ( (float) max / 256.0f );
    
    // 縮放後圖片的寬和高
    int nw = (int)( w/scale );
    int nh = (int)( h/scale );

    // 爲了將縮放後的圖片存入 TheImage 的正中部位,需計算圖片在 TheImage 左上角的期望座標值
    int tlx = (nw > nh)? 0: (int)(256-nw)/2;
    int tly = (nw > nh)? (int)(256-nh)/2: 0;

    // 設置 TheImage 的 ROI 區域,用來存入圖片 img
    cvSetImageROI( TheImage, cvRect( tlx, tly, nw, nh) );

    // 對圖片 img 進行縮放,並存入到 TheImage 中
    cvResize( img, TheImage );

    // 重置 TheImage 的 ROI 準備讀入下一幅圖片
    cvResetImageROI( TheImage );
}

void CEdgesProcessDlg::ShowImage( IplImage* img, UINT ID )    // ID 是Picture Control控件的ID號
{
    CDC* pDC = GetDlgItem( IDC_ShowImg )->GetDC();        // 獲得顯示控件的 DC
    HDC hDC = pDC ->GetSafeHdc();                // 獲取 HDC(設備句柄) 來進行繪圖操作
	CRect rect;
    GetDlgItem(IDC_ShowImg)->GetClientRect( &rect );

    int rw = rect.right - rect.left;            // 求出圖片控件的寬和高
    int rh = rect.bottom - rect.top;
    int iw = img->width;                        // 讀取圖片的寬和高
    int ih = img->height;
    int tx = (int)(rw - iw)/2;                    // 使圖片的顯示位置正好在控件的正中
    int ty = (int)(rh - ih)/2;
    SetRect( rect, tx, ty, tx+iw, ty+ih );

    CvvImage cimg;
    cimg.CopyOf( img );                            // 複製圖片
    cimg.DrawToHDC( hDC, &rect );                // 將圖片繪製到顯示控件的指定區域內
	
	cvWaitKey(0);
    
    ReleaseDC( pDC );
}

還在類視圖中,雙擊 OnPaint,在 if(IsIconic())…的 else 裏添加以下代碼,用來重繪窗口:

CDialog::OnPaint();                    // 重繪對話框
        CDialog::UpdateWindow();                // 更新windows窗口,如果無這步調用,圖片顯示還會出現問題
        ShowImage( TheImage, IDC_ShowImg );    // 重繪圖片函數
在CEdgesprocessApp下雙擊Initnstance,在兩個“// TODO: Place code here to handle when the dialog is…”下面添加:

cvReleaseImage( &dlg.TheImage );
接下來,要轉到GUI界面了,就是最直觀的圖形界面:添加兩個按鈕的點擊事件:OnBnClickedReadimg和OnBnClickedEdgesDetcet。直接雙擊按鈕就可以了。添加以下代碼:

void CEdgesProcessDlg::OnBnClickedReadimg()
{
	// TODO: 在此添加控件通知處理程序代碼
    IplImage* ipl = cvLoadImage( "E:\\beijing.bmp", 1 );    // 讀取圖片、緩存到一個局部變量 ipl 中
    if( !ipl )                                    // 判斷是否成功載入圖片
        return;
    if( TheImage )                                // 對上一幅顯示的圖片數據清零
        cvZero( TheImage );
    
    ResizeImage( ipl );    // 對讀入的圖片進行縮放,使其寬或高最大值者剛好等於 256,再複製到 TheImage 中
    ShowImage( TheImage, IDC_ShowImg );            // 調用顯示圖片函數    
    cvReleaseImage( &ipl );                        // 釋放 ipl 佔用的內存
}



void CEdgesProcessDlg::OnBnClickedEdgedetect()
{
	// TODO: 在此添加控件通知處理程序代碼
	IplImage *gray = 0, *edge = 0;
    gray = cvCreateImage( cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 1 );
    edge = cvCreateImage( cvSize(IMAGE_WIDTH, IMAGE_HEIGHT), IPL_DEPTH_8U, 1 );
    cvCvtColor( TheImage, gray, CV_BGR2GRAY );
    cvCanny( gray, edge, 30, 100, 3 );
    cvCvtColor( edge, TheImage, CV_GRAY2BGR );    
    ShowImage( TheImage, IDC_ShowImg );            // 調用顯示圖片函數

    cvReleaseImage( &gray );
    cvReleaseImage( &edge );
}
效果圖:




參考:

http://www.laganiere.name/opencv1Tut/index.shtml

http://blog.csdn.net/chenyusiyuan/article/details/4744097

祝大家一切順利。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章