基于MFC 对话框的 PCL、VTK 、OPENCV岩体识别系统构建(1)

最近在忙于点云系统的构建,主要结合点云库PCL、可视化库VTK以及图像处理开源库OpenCV来做结合图像和点云数据协同的岩体分析系统。这里希望跟大家分享一下自己的整体构建流程,不足的地方希望大家能够帮忙指出以便改进。由于还在搭建过程中,所以文章的更新时间不一定,但是有关键性的进展一定会写出来讨论,谢谢大家。

整个系统构建的分析过程包括模块划分,模块之间的耦合,数据库构建,相关类的创建、继承等理论细节不在这里讨论。这篇文章先从系统的界面框架开始:

一、菜单栏

关于系统的菜单由于之前讨论完成,主要分为了相关数据加载、数据编辑、三维可视化、点云处理、图像处理等模块。

在建立完成一个基于Dialog的MFC应用程序之后在资源视图下,右键选择“添加资源”,在弹出的对话框中我们选择新建一个Meun,确定之后就会产生一个新的IDR_MENU1菜单资源,保持默认设置,ID号不变,我们编辑我们的菜单项,如下图所示:

菜单项前的图标等其他细节还未设置,之后会进行补充。

建立完成资源之后,我们需要加载这个资源。打开XXXDlg.h,创建一个成员变量

CMenu m_Menu;

接着在XXXDlg.cpp文件中找到XXXDlg::OnInitDialog(){},在//TODE下编写代码:

m_Menu.LoadMenu(IDR_MENU1);
SetMent(&m_Menu);

这样我们的菜单资源就加载好了;

二、工具栏

有了菜单栏接下来是工具栏,这里只是简单设置了下工具栏,关于工具栏的详细操作可以参考这篇文章

工具栏的创建可以进入资源窗口里进行创建,当然这里并没有使用这一方法。

同样在XXXDlg.h中创建ToolBar的成员变量和CImageList:

CToolBar m_toolbar;
CImageList m_toolbarImg;

接着在XXXDlg.cpp下的OnInitDialog(){}中编写代码:

	if(!m_toolbar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC )
		)
	{
		TRACE0(_T("创建工具条失败\n"));
	}

由于我们需要为我们的工具栏上的按钮设置自定义图片,所以这里要利用CImageList:

	/*指定按钮图标图片*/
	m_toolbarImg.Create(16,16,ILC_COLOR16,3,3);
	m_toolbarImg.Add(AfxGetApp()->LoadIcon(IDI_ICON1));
	m_toolbarImg.Add(AfxGetApp()->LoadIcon(IDI_ICON2));
	m_toolbarImg.Add(AfxGetApp()->LoadIcon(IDI_ICON3));
	m_toolbar.GetToolBarCtrl().SetImageList(&m_toolbarImg);

由于这里使用的图片大小为16*16的,所以需要在Crete方法里加以设置,Create方法最后两个参数可以随便设置。

接下来的三行代码是加载我们的自定义图标,在此之前我们需要将我们需要的图标文件拷贝到工程文件的res文件夹下,然后在资源视图下的Icon文件夹中导入我们想要的图标,这里我暂时先载入了3个图标:

修改ID分别为IDI_ICON1,IDI_ICON2,IDI_ICON3。然后利用CImageList的Add方法,载入三个图标。

最后一行代码是获取CToolBarCtrl变量并进行图标的设置,这里要提一句,SetImageList是默认的显示图片方式,而SetHotImageList是鼠标放上去之后的高亮显示,两者是不一样的。

接下来就可以具体为工具栏上添加button工具按钮了。

	m_toolbar.SetButtons(NULL,3);
	m_toolbar.SetButtonInfo(0,IDI_ICON1,TBSTYLE_BUTTON,0);
	m_toolbar.SetButtonText(0,"功能1");
	m_toolbar.SetButtonInfo(1,IDI_ICON2,TBSTYLE_CHECK,1);
	m_toolbar.SetButtonText(1,"功能2");
	m_toolbar.SetButtonInfo(2,IDI_ICON3,TBSTYLE_BUTTON,2);
	m_toolbar.SetButtonText(2,"功能3");
	m_toolbar.SetSizes(CSize(24,24),CSize(16,16));
	RepositionBars(AFX_IDW_CONTROLBAR_FIRST,AFX_IDW_CONTROLBAR_LAST,0);
        m_ImageList.Detach();

我们暂时添加3个按钮,所以第一行为3,第二行的setButtonInfo表示开始添加工具,里面 有4个参数,第一个参数表示工具按钮的id号,0表示第一个;第二个参数是图标的ID号;第三个参数是工具的样式,这里为按钮所以设置为TBSTYLE_BUTTON,当然也可以设置为TBSTYLE_CHECK表示单选check控件;最后一个为CImageList里对应的图片id号,第一个从0开始。之后设置按钮的鼠标提示文本。

按这样的方式设置好三个按钮之后,我们需要设置按钮大小。利用SetSizes方法,第一个参数是按钮的大小,第二个参数是按钮里图标图片的大小,注意的是图标图片的大小于我们之前加载图片的时候需要 一致,同为16*16。

最后不要忘记最后两行RepositionBars和CImageList的Detach(),前者用来显示工具栏,后者释放图片资源。

三、内容树状图

我们在打开文件的时候,通常软件的左侧会显示出一个内容的树状图,这里要用的是CTreeControl。

我们打开工程的主对话框,在左侧添加一个tree Control,设置好大小与布局之后,修改ID号,通过鼠标右键为其关联成员变量,如下图:

完成之后可以在XXXDlg.h中找到该变量,之后我们可以对该控件进行初始化设置。

我们知道内容树状图的节点前一般可以有图标来美化,所以这里我们同样需要利用CImageList来保存我们节点的图标文件:

	hIcon[0] = theApp.LoadIcon(IDI_ICON1);
	hIcon[1] = theApp.LoadIcon(IDI_ICON2);
	hIcon[2] = theApp.LoadIcon(IDI_ICON3);
	m_ImageList.Create(16,16,ILC_COLOR16,3,3);
	for(int i = 0 ;i < 3;i++)
	{
		m_ImageList.Add(hIcon[i]);
	}
	m_Tree.SetImageList(&m_ImageList,TVSIL_NORMAL);

之后我们建立树状节点:

	/*建立第一个节点树*/
	hRoot = m_Tree.InsertItem(_T("根节点1"),0,0);
	hCataItem = m_Tree.InsertItem(_T("节点1"),1,1,hRoot,TVI_LAST);
	m_Tree.SetItemData(hCataItem,1);
	hArtItem = m_Tree.InsertItem(_T("子节点1"),2,2,hCataItem,TVI_LAST);
	hArtItem = m_Tree.InsertItem(_T("子节点2"),2,2,hCataItem,TVI_LAST);
	*建立第二个节点树*/
	hRoot = m_Tree.InsertItem(_T("根节点2"),0,0);
	hCataItem = m_Tree.InsertItem(_T("节点1"),1,1,hRoot,TVI_LAST);
	m_Tree.SetItemData(hCataItem,1);
	hArtItem = m_Tree.InsertItem(_T("子节点1"),2,2,hCataItem,TVI_LAST);
	hArtItem = m_Tree.InsertItem(_T("子节点2"),2,2,hCataItem,TVI_LAST);

依次建立根节点,节点和子节点,并设置节点对应的父节点以及子节点对应的节点。这样就算初始化了节点树状图了。当然了,在具体的系统当中,我们应该是针对具体数据打开之后再显示内容树状图,那时候节点对应的文本应该是根目录,路径名称以及文件名了,节点的级数也是动态变化的,如根据具体的文件路径来设置。

四、属性表单

由于系统涉及图片影像数据与点云数据,我们需要在系统界面上能够在加载数据的同时显示出有关数据的属性信息,所以在界面右侧设置了属性表单。

如何建立我们自己的属性表单呢?

第一、在资源视图中找到Dialog文件夹,鼠标右键添加资源,在弹出的资源对话框中选择展开Dialog,选择里面的IDD_PROPERTY_LARGE,选择新建。

第二、按住Ctrl依次拖动鼠标,创建2份拷贝,这时候有了3个资源,分别是IDD_PROPERTY_LARGE,IDD_PROPERTY_LARGE1,IDD_PROPERTY_LARGE2。(这里只是暂时创建了3份属性表,可以根据需要自己改变)

第三、在XXXDlg.h文件中添加CPropertyPage成员变量和CPropertySheet成员变量:

	CPropertyPage m_page1;
	CPropertyPage m_page2;
	CPropertyPage m_page3;
	CPropertySheet m_pagesheet;

之后添加主对话框的OnCreate()和OnSize()事件。(之前想在OnInitDialog里设置,可是要么出错要么显示不出来,咋回事?)

在OnCreate中加入代码:

	m_page1.Construct(IDD_PROPPAGE_LARGE);
	m_page2.Construct(IDD_PROPPAGE_LARGE1);
	m_page3.Construct(IDD_PROPPAGE_LARGE2);
	m_pagesheet.Construct("property pages",this);
	m_pagesheet.AddPage(&m_page1);
	m_pagesheet.AddPage(&m_page2);
	m_pagesheet.AddPage(&m_page3);

	m_pagesheet.Create(this,WS_CHILD|WS_VISIBLE);

第四、为了方便布局,我们先在主对话框中放置属性表单的位置添加一个static控件,设置好布局和Visial属性为false,这样我们就可以获取其Rect来布局我们的表单。

第五、在OnSize()中添加变量:

	CRect rc;
	GetDlgItem(IDC_STATIC_PROPERTY)->GetWindowRect(&rc);
	m_pagesheet.SetWindowPos(&wndTop,rc.left-10,rc.top-25,rc.right,rc.bottom,NULL);

这里有个问题,就是我直接获取rc的left和top,为什么不能完全叠加到static控件上,总是会有偏移,所以这里我就自己设置了偏移量好吻合上去,可是这样好麻烦...求解答。

以上我们就设置了表单及布局,具体要在表单上添加什么内容,以后再设计。

第五、主工作区视图

主视图区是系统的主要部分,这里的主视图主要分为两个,由Tab控件用于切换,主要是点云的3D显示区域以及图像显示区域。

第一、我们在预留的主视图区添加一个Tab控件,右键为其关联成员变量m_Tab;

第二、由于我们需要为Tab控件里放2个显示方式,所以我们先在资源视图下的Dialog里添加两个对话框资源,修改其Bord属性为None、Style属性为Child,然后为3D显示的对话框修改ID为IDD_DIALOG_VIEW,图片显示的对话框为IDD_DIALOG_PICTURE。在VIEW对话框中添加了static控件来布局VTK窗口,在PIC对话框中添加Picture控件来显示图片影像,并分别对其生成类CPageView和CPagePic。

第三、在XXXDlg.h中添加成员变量

	CPagePic m_pagepicture;
	CPageView m_pageviewer;

第四、在XXXDlg.cpp文件中的OnInitDialog里添加代码;

	CRect r;
	m_tab.InsertItem(1,_T("可视化"));
	m_tab.InsertItem(2,_T("影像"));
	m_pageviewer.Create(IDD_DIALOG_View,&m_tab);//加载对话框并管理到tab控件
	m_pagepicture.Create(IDD_DIALOG_PICTURE,&m_tab);
	m_tab.GetClientRect(&r);
	m_pageviewer.SetWindowPos(NULL,r.left+1,r.top+1,r.right-1,r.bottom-25,SWP_SHOWWINDOW);//设置显示位置
	m_pagepicture.SetWindowPos(NULL,r.left+1,r.top+1,r.right-1,r.bottom-25,SWP_HIDEWINDOW);

第五、响应Tab控件的OnTcnSelchangeTab1()消息,双击就行。并在其中添加代码:

	CRect rect;
	m_tab.GetClientRect(&rect);
	switch(m_tab.GetCurSel())
	{
	case 0:
		m_pageviewer.SetWindowPos(NULL,rect.left+1,rect.top+1,rect.right-1,rect.bottom-25,SWP_SHOWWINDOW);
		m_pagepicture.SetWindowPos(NULL,rect.left+1,rect.top+1,rect.right-1,rect.bottom-25,SWP_HIDEWINDOW);
		break;
	case 1:
		m_pageviewer.SetWindowPos(NULL,rect.left+1,rect.top+1,rect.right-1,rect.bottom-25,SWP_HIDEWINDOW);
		m_pagepicture.SetWindowPos(NULL,rect.left+1,rect.top+1,rect.right-1,rect.bottom-25,SWP_SHOWWINDOW);
		break;
	}
	*pResult = 0;

第六、设置好了之后如果我们想设置VTK的显示该怎么办呢?我们可以调用VTK的vtkRenderWindow对象的SetParetId方法来设置,获取tab控件下的pageviewer对象,得到其内部的static控件的句柄。

	renwin->SetParentId(m_pageviewer.GetDlgItem(IDC_STATIC_VTK)->m_hWnd);
	CRect rect;
	m_pageviewer.GetDlgItem(IDC_STATIC_VTK)->GetWindowRect(&rect);
	renwin->SetSize(rect.Width(),rect.Height());
	iren->SetRenderWindow(renwin);
	iren->Initialize();
	renwin->Render();
	iren->Start();

第七、请包含所有需要的相关头文件。

全部的布局就这样设置好了,现在我们可以看一下效果了,我事先添加了一部分的PCL文件打开的代码,以txt文本的方式被VTK读取并显示。

时间: 2024-07-28 13:36:00

基于MFC 对话框的 PCL、VTK 、OPENCV岩体识别系统构建(1)的相关文章

基于QT和OpenCV的人脸识别系统

1 系统方案设计 1.1 引言 人脸是一个常见而复杂的视觉模式,人脸所反映的视觉信息在人与人的交流和交往中有着重 要的作用和意义,对人脸进行处理和分析在视频监控.出入口控制.视频会议以及人机交互等领 域都有着广泛的应用前景,因此是模式识别和计算机视觉领域持续的研究热点. 本系统在 FriendlyARM Tiny6410 开发板基础上,利用 OpenCV 计算机视觉库和 QT 图形库,通 过普通的 USB 摄像头实现了自动人脸识别,准确率较高,方便易用. 1.2 系统总体架构 "人脸识别&quo

基于opencv的车牌识别系统

前言 学习了很长一段时间了,需要沉淀下,而最好的办法就是做一个东西来应用学习的东西,同时也是一个学习的过程. 概述     OpenCV的全称是:Open Source Computer Vision Library.OpenCV是一个基于(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows和Mac OS操作系统上.它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python.Ruby.MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算

python使用opencv实现人脸识别系统

1.首先安装过python环境,在这里就不过说    检测是否安装成功如下,在cmd中输入Python     2.安装numpy 现在开始安装numpy,打开cmd,输入pip install numpy 我的电脑已经安装过了,忘记截屏了.就在网上找了图片 测试是否成功 3.安装opencv 在官网自行下载,这里下载的是opencv2.4.10安装. ### (1)复制cv2.pyd 将"\opencv\build\python\2.7\x64"或"\opencv\buil

MFC技术积累——基于MFC对话框类的那些事儿

1. 创建对话框类 (1)打开VC++6.0环境,点击:文件→新建: (2)在弹出的新建对话框中选择:工程→MFC AppWizard (exe)→输入工程名称(例如:功能调试)→工程保存路径名→确定(其他勾选项一律默认): (3)在弹出的MFC AppWizard- Step1对话框中选择:(你喜爱创建的应用程序类型?)点击基本对话框→(使用语言?)选择中文→点击下一个: (4)在弹出的MFC AppWizard- Step2 of 4对话框中选择:这里基本保持默认选择,比较有用的一项是输入标

MFC技术积累——基于MFC对话框类的那些事儿2

3. 绘图 3.1 对话框资源编辑 首先通过添加控件的方式来创建一个简单的绘图对话框如图所示,创建步骤为: 第一.在VC++6.0软件环境的灰色空白区域右击,选中Controls,然后会弹出一个控件对话框: 第二.点击需要的控件,鼠标箭头类型就会变成十字形,然后在主对话框里通过点击.拖拽绘制出需要的控件,这里也可以通过鼠标调整控件大小直到满意为止. 第三.在主对话框里右击打开属性对话框(一般情况下可以点击属性对话框左上角的形如大头针样式的小按钮来锁定属性对话框,解锁也是点击同样的按钮,只是按钮样

基于MFC对话框程序中添加菜单栏 (CMenu)

vs2013MFC对话框程序中添加菜单栏的过程,我大致分了这五步. 一.将Menu加入Resource视图中 在WorkSpace中的Resource视图下,在任意一个文件夹图标上,右击选择Insert(插入)选项,在弹出的对话框中选择Menu以后,再点击,new按钮,菜单就会添加成功了,但是现在还没有完成,还不能进行编译,因为现在的菜单时空的,在编译的时候会被清除的. 二.用菜单编辑器添加菜单栏及菜单项 菜单添加成功后,菜单编辑器自动打开,可以在其中添加菜单栏及菜单项,比较简单. 三.将菜单加

基于MFC对话框的2048游戏

在之前一篇<简单数字拼板游戏学习>基础上修改,地址:http://www.cnblogs.com/fwst/p/3706483.html 运行效果: (4 X 4) (7 X 7) (1)已完成 2048 游戏基本功能,需要解决的几个关键问题是 a. 首先是数据结构.先定义矩形类,然后定义矩形类对象的二维数组,长度由宏定义,可修改,即可自定义成N*N的游戏.这样游戏就是由N*N个矩形对象组成. b. 然后是游戏逻辑处理,也是最重要的一部分.方向键的响应.键盘上下左右四个方向键的逻辑一样,代码部

MFC技术积累——基于MFC对话框类的那些事儿4

3.3.4 借助兼容DC加载DIB位图 创建一个与设备环境相兼容的DC,通过将位图暂时导入至兼容DC,然后利用CDC::BitBlt 或者CDC::StretchBlt函数将位图绘制到设备环境中. 示例代码如下: void CFDlg::OnLoadbitmap() { // TODO: Add your control notification handler code here HBITMAP hbitmap; BITMAP bitmapinfo; CBitmap cbitmap; RECT

python基于OpenCV的人脸识别系统

想获得所有的代码,请下载(来自我的CSDN): https://download.csdn.net/download/qq_40875849/11292912 主函数: from recognition import recognition from training import training from datasets import datasets from delFile import del_file def main(): facedict = {} cur_path = r'.