MFC3-图像边缘处理

来源:互联网 发布:那个基金软件好 编辑:程序博客网 时间:2024/05/21 20:29

前面的创建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

祝大家一切顺利。