MFC动态绘图+OpenCV画图

本程序运用到了OpenCv库,采用2.47版本。、

本程序中也充分运用到了MFC框架下的两个坐标系:屏幕坐标系和客户区坐标系。

本程序利用MFC画图技术+OpenCv技术实现功能:

1、通过文件对话框,利用OpenCv将图片加载并刷新到MFC Picture控件上。

根据OpenCv载入图片数据得到MFC BitMapInfo 位图信息。

LPBITMAPINFO CDrawAndOpenCVDlg::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->origin == 0) ? -workImg->height:workImg->height; 
    bits=workImg->depth*workImg->nChannels;
    if (bits>8) colors=0;
    else colors = 1<<bits;

    int nsize = sizeof(BITMAPINFO);
    lpBmi=(LPBITMAPINFO) malloc(40+4*colors);
    BIH.biWidth   =wid;     BIH.biHeight  =hei;
    BIH.biBitCount=(BYTE) bits;
    memcpy(&lpBmi->bmiHeader, &BIH, 40);    //  复制位图信息头 
    if (bits==8) {                          //  256 色位图
        for (i=0;i<256;i++)  {              //  设置灰阶调色板
            ColorTab[i].rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE) i;
        }
        memcpy(lpBmi->bmiColors, ColorTab, 1024);
    }
    return(lpBmi);
}

利用OpenCv载入图片并将其显示到Picture控件上,其中img为IplImage*,已经载入。

BOOL CDrawAndOpenCVDlg::displayImage()
{
    CDC* pDC = mPictureStatic.GetDC();
    CRect rect;
    mPictureStatic.GetClientRect(rect);
    HDC hDC = pDC->GetSafeHdc();
    LPBITMAPINFO bitmap = CtreateMapInfo(img);
    ::SetStretchBltMode (hDC, STRETCH_DELETESCANS);
    ::StretchDIBits(hDC , rect.left , rect.top ,  rect.Width() , rect.Height(),
        0 , 0 , img->width , img->height,  img->imageData , 
        bitmap,DIB_RGB_COLORS,SRCCOPY);
    ReleaseDC(pDC);
    pDC = NULL;
    delete bitmap;
    bitmap = NULL;
    return TRUE;
}

2、实现对Picture控件进行动态画图,本实时加载到图片数据上进行显示。
动态绘图主要处理三个鼠标消息响应:

afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);

在OnMouseMove中主要处理:

CPoint p1 = mPoint1;
            CPoint p2 = mPoint2;
            CDC *pDC = mPictureStatic.GetDC();
            pDC->SetROP2(R2_XORPEN); //这是关键,先去反色
            pDC->SelectObject(mMFCPen);
            CBrush *newBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
            pDC->SelectObject(newBrush);
            switch(drawType) {
            case 1:  //画线
                {               
                    pDC->MoveTo(p1);
                    pDC->LineTo(p2); //将上次画的线反色再画
                    p2 = mPoint2 = point;
                    pDC->MoveTo(p1);
                    pDC->LineTo(p2); //画本次线
                    ReleaseDC(pDC);
                    break;
                }
            case 2:
                {           
                    CRect rect(p1, p2);
                    pDC->Rectangle(rect);
                    p2 = mPoint2 = point;
                    if(p1.x > p2.x){
                        long x = p1.x;
                        p1.x = p2.x;
                        p2.x = x;
                    }
                    if(p1.y > p2.y){
                        long y = p1.y;
                        p1.y = p2.y;
                        p2.y = y;
                    }
                    rect.SetRect(p1, p2);
                    pDC->Rectangle(rect);
                    break;
                }

            }
            newBrush->DeleteObject();
            ReleaseDC(pDC);

OpenCv绘图主要有两个函数:

void CDrawAndOpenCVDlg::drawLineToImage()
{
    CRect rect;
    mPictureStatic.GetClientRect(rect);
    CvPoint cvPo1, cvPo2;
    cvPo1.x = mPoint1.x * img->width / rect.Width();
    cvPo1.y = mPoint1.y * img->height / rect.Height();
    cvPo2.x = mPoint2.x * img->width / rect.Width();
    cvPo2.y = mPoint2.y * img->height / rect.Height();
    int tempWidth = lineWidth * img->width / rect.Width();
    cvLine(img, cvPo1, cvPo2, mCvScaler, tempWidth);
    displayImage();
}
void CDrawAndOpenCVDlg::drawRectToImage()
{
    if(mPoint1.x > mPoint2.x){
        long x = mPoint1.x;
        mPoint1.x = mPoint2.x;
        mPoint2.x = x;
    }
    if(mPoint1.y > mPoint2.y){
        long y = mPoint1.y;
        mPoint1.y = mPoint2.y;
        mPoint2.y = y;
    }
    CRect rectPicStatic;
    CvPoint cvPo1, cvPo2;
    mPictureStatic.GetClientRect(rectPicStatic);
    cvPo1.x = mPoint1.x * img->width / rectPicStatic.Width();
    cvPo1.y = mPoint1.y * img->height / rectPicStatic.Height();
    cvPo2.x = mPoint2.x * img->width / rectPicStatic.Width();
    cvPo2.y = mPoint2.y * img->height / rectPicStatic.Height();
    int tempWidth = lineWidth * img->width / rectPicStatic.Width();
    cvRectangle(img, cvPo1, cvPo2, mCvScaler, tempWidth);
    displayImage();
}

3、可实现对画图颜色和线宽的选择,画图方式有矩形和线。颜色选择主要在void OnLButtonDown(UINT nFlags, CPoint point);中处理:

    ClientToScreen(&point); //将对话框客户区坐标point转换为屏幕坐标
    CRect rect;
    mColourStatic.GetWindowRect(rect); //得到屏幕坐标系下的mColourStatic矩形坐标
    if(rect.PtInRect(point)){
        CColorDialog m_setClrDlg;
        // CC_RGBINIT可以让上次选择的颜色作为初始颜色显示出来
        m_setClrDlg.m_cc.Flags |= CC_FULLOPEN|CC_RGBINIT;   
        m_setClrDlg.m_cc.rgbResult = mMFCColor; //记录上次选择的颜色
        if(IDOK ==m_setClrDlg.DoModal())
            mMFCColor = m_setClrDlg.m_cc.rgbResult; // 保存用户选择的颜色    
        fillColourStatic();
        mMFCPen.DeleteObject();
        mCvScaler.val[0] = GetBValue(mMFCColor);
        mCvScaler.val[1] = GetGValue(mMFCColor);
        mCvScaler.val[2] = GetRValue(mMFCColor);
        lineWidth = mLineWidthBox.GetCurLineWidth();
        mMFCPen.CreatePen(PS_SOLID, lineWidth, 
            RGB(GetRValue(mMFCColor), GetGValue(mMFCColor), GetBValue(mMFCColor)));
    }

4、可将最终画的图片进行本地保存,在画图过程还可以进行还原,全部删除前面所画图形。
下载地址:http://download.csdn.net/detail/qq_20828983/9609281
程序效果:

这里写图片描述
这里写图片描述

这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值