Image processing with OpenCV MFC sample of the actual collection of small tools to make c ++ MFC program design

Original author: aircraft

Original link: https://www.cnblogs.com/DOMLX/p/12111102.html

 

    Getting people can soon exercise to combat it by opencv opencv of learning outcomes, Baidu cloud link:

Link: https: //pan.baidu.com/s/1jGOD97Zx96ZDAvlkQtaPYQ
extraction code: afip

 

 Operating environment VS2017, you need to configure library: opencv

 

Title: sample collection gadget

 

 

 

demand:

With MFC and opencv complete sample collection gadget.

Interface Features

1, select the directory of the original picture set.

2. Select the current sample is positive or negative samples? And select its directory.

3, through the replacement of a next set of pictures show the original picture.

Click on the picture display area function

1, left-click the picture selected, click the mouse at the center, width W * height H of the region.

2, roll the mouse wheel increases the selected area.

3, the mouse wheel to scroll down narrow the selected area.

4. Right-click the selected area to save the picture in the catalog of the positive samples or negative samples, depending on the currently selected sample positive or negative samples.

 

 

 

 

Complete interface is shown:

 

 

 

 

The first step: MFC interface that controls both drag and good binding opencv good graphic box

Add our binding code in the MFC initialization function:

BOOL CpicroiDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
    //  执行此操作
    SetIcon(m_hIcon, TRUE);            // 设置大图标
    SetIcon(m_hIcon, FALSE);        // 设置小图标




    //InitializeSkin(("Minimized.ssk"));//初始化


    // TODO: 在此添加额外的初始化代码
    namedWindow("ImageShow", CV_WINDOW_KEEPRATIO);          // 用OpenCV创建一个窗口 
    CRect cWindowRect;
    m_PictureControl.GetClientRect(&cWindowRect);           // 获取控件窗口大小
    //int nWindowWidth = cWindowRect.Width();
    //int nWindowHeight = cWindowRect.Height();
    //resizeWindow("ImageShow", 200, 100);
    HWND hPictureWindow = (HWND)cvGetWindowHandle("ImageShow");        //  获取OpenCV窗口的句柄
    HWND hParentWindow = ::GetParent(hPictureWindow);
    ::SetParent(hPictureWindow, GetDlgItem(IDC_PIC)->m_hWnd);   //  关联OpenCV窗口和MFC的控件窗口
    ::ShowWindow(hParentWindow, SW_HIDE);
    GetDlgItem(IDC_PIC)->ShowWindow(0);                        // 开始不显示图片控件

    setMouseCallback("ImageShow", onMouse, 0);

    pcom.InsertString(0, "正样本");
    pcom.InsertString(1, "负样本");
    pcom.SetCurSel(0);

    
    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

 

 

 

第二步:选中原图片集的目录

这样接下来操作的图片都从这个目录顺序读取,并且切换上下张

 

添加好对话框类之后:

双击这个控件,进入相应的编辑函数内部编写事件处理代码:

 

 

 

void CpicroiDlg::OnBnClickedMainFilePath()
{
    // TODO: 在此添加控件通知处理程序代
    
    CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, _T("image files (*.jpeg; *.jpg; *.bmp;*.png)  All Files (*.*) |*.*||"));
    CString m_strPath;
    CString m_folderpath;
    if (IDOK == dlg.DoModal()) {
        m_strPath = dlg.GetPathName();
        m_folderpath = dlg.GetFolderPath();
    }
    string strName = CT2A(m_strPath.GetString());              // CString和string之间的类型转换
    string strPathNames = CT2A(m_folderpath.GetString());
    sourceImage = imread(strName);
    nWindowWidth = sourceImage.cols;
    nWindowHeight = sourceImage.rows;
    resizeWindow("ImageShow", nWindowWidth, nWindowHeight);
    if (strName == "")return;

    tempImage = sourceImage.clone();
    imshow("ImageShow", sourceImage);
    GetDlgItem(IDC_PIC)->ShowWindow(1);


    SetDlgItemText(IDC_MAIN_FILE, m_folderpath);
    UpdateWindow();
    getFiles1(strPathNames, files);
    filesLen = files.size()-1;
    for (auto path : files) {
        index++;
        if (path == strName)break;
    }
}

 

同样的也要选择保存的文件路径:

 

 

 

void CpicroiDlg::OnBnClickedMainFilePath2()
{
    // TODO: 在此添加控件通知处理程序代码
    if (m_dlgMainFile.DoModal() != IDOK)
        return;

    CString cstrFile;                //文件全名
    string strFile;
    cstrFile = m_dlgMainFile.GetFolderPath();
    strFile = CT2A(cstrFile.GetString());
    SetDlgItemText(IDC_MAIN_FILE2, cstrFile);
    UpdateWindow();
    getFiles1(strFile, filesPath2);
    picIndex = filesPath2.size();
    GetDlgItem(IDC_MAIN_FILE2)->GetWindowTextA(cs_pcomValue);
    s_pcomComValue = CT2A(cs_pcomValue.GetString());
}

 

 

void CpicroiDlg::OnBnClickedMainFilePath3()
{
    // TODO: 在此添加控件通知处理程序代码
    if (m_dlgMainFile.DoModal() != IDOK)
        return;

    CString strFile;                //文件全名
    strFile = m_dlgMainFile.GetFolderPath() + "\\";
    SetDlgItemText(IDC_MAIN_FILE3, strFile);
    UpdateWindow();
}

 

这样只要选择好了正负样本点击右键就可以自动保存到相应的选择好的目录了

第三步:鼠标控制图像的裁剪和选定

 这里我们要实现的是鼠标点击出现一个矩形框,然后用鼠标的滚轮去滚动,让矩形框围绕中心点改变大小,然后点击右键则保存图形

void onMouse(int event, int x, int y, int flag, void*) {

    //CDC *pDC = GetDC();
    //CString str; str.Format(TEXT("%d,%d"), x, y);
    //pDC->FillSolidRect(0, 0, 100, 100, GetSysColor(COLOR_WINDOW));
    //pDC->TextOut(1, 0, str);
    switch (event)
    {
    case CV_EVENT_LBUTTONDOWN://左键按下
        flag = true;
        mousFlag = 1;
        moux = x;
        mouy = y;
        if ((x - width / 2) < 0)Lu.x = 0;
        else Lu.x = x - width / 2;
        if ((y - height / 2) < 0)Lu.y = 0;
        else Lu.y = y - height / 2;
        if ((x + width / 2) > nWindowWidth - 1)Rd.x = nWindowWidth - 1;
        else Rd.x = x + width / 2;
        if ((y + height / 2) > nWindowHeight - 1 )Rd.y = nWindowHeight - 1;
        else Rd.y = y + height / 2;
        lastImage = tempImage.clone();
        rectangle(tempImage, Lu, Rd, Scalar(0, 255, 0), 1, 0, 0);
        imshow("ImageShow", tempImage);
        break;
    case CV_EVENT_RBUTTONDOWN://右键按下
        {    Rect rect(Lu.x, Lu.y, Rd.x-Lu.x, Rd.y-Lu.y);
        g_rect = rect;
        }
        if (s_pcomComValue == "")
        {
            MessageBox(AfxGetMainWnd()->m_hWnd, "存放目录未填写","警告", MB_OK);
            break;
        }
        s_save = s_pcomComValue +"\\"+ to_string(picIndex) + ".jpg";
        ROI = sourceImage(g_rect);
        imwrite(s_save, ROI);
        picIndex++;
        break;
    case CV_EVENT_MOUSEWHEEL:
        int mousWhellFlag;
        int value;
        mousWhellFlag = 1;
        value = getMouseWheelDelta(flag);
        if (value > 0) {
            Lu.x = Lu.x > 0 ? Lu.x -= step : Lu.x;
            Lu.y = Lu.y > 0 ? Lu.y -= step : Lu.y;

            Rd.x = Rd.x < (nWindowWidth - 1) ? Rd.x += step : (nWindowWidth - 1);
            Rd.y = Rd.y < (nWindowHeight - 1) ? Rd.y += step : (nWindowHeight - 1);
        }    
        else {
            Lu.x = Lu.x < x ? Lu.x += step : x;
            Lu.y = Lu.y < y ? Lu.y += step : y;

            Rd.x = Rd.x > x ? Rd.x -= step : x;
            Rd.y = Rd.y > y ? Rd.y -= step : y;
        }
        {    Rect rect(Lu.x, Lu.y, Rd.x - Lu.x, Rd.y - Lu.y); g_rect = rect;    }
        tempImage = lastImage.clone();
        rectangle(tempImage, Lu, Rd, Scalar(0, 255, 0), 1, 0, 0);
        imshow("ImageShow", tempImage);
        break;

    default:
        break;
    }
    
}

因为我们裁剪已经画矩形框都不能在原图上画,所以我们复制一份图像显示,所有的操作都是在复制 的临时图像上操作的,然后在根据缓冲刷新,将图像替换就行了

 

最后说一句,这个是直接显示原图的,如果原图过大只能看到部分,这时候在代码里面加个判断,然后用opencv的图像归一化的函数去改变一下图像大小即可。

因为不想写的很详细,(别问为什么,问就是因为最近很懒!!!),所以我给出了项目源码的百度云在文章的开头

 

 

若有兴趣交流分享技术,可关注本人公众号,里面会不定期的分享各种编程教程,和共享源码,诸如研究分享关于c/c++,python,前端,后端,opencv,halcon,opengl,机器学习深度学习之类有关于基础编程,图像处理和机器视觉开发的知识

Guess you like

Origin www.cnblogs.com/DOMLX/p/12111102.html