丁庆平,福建医科大学信息门户,数码照相机排行榜
1、添加halcon控件,创建wpf项目
在vs2013中创建一个wpf工程,然后添加halcon的控件和工具包,参见:
hsmartwindowcontrol之安装篇 (visual studio 2013 & halcon 18)
在wpf工程中添加好hsmartwindowcontrolwpf控件后,将其拖入主窗体即可。
2、生成摄像头实时显示的halcon代码
使用image acquisition 连接笔记本自带的摄像头,然后生成实时显示的代码即可:
* image acquisition 01: code generated by image acquisition 01 open_framegrabber ('directshow', 1, 1, 0, 0, 0, 0, 'default', 8, 'rgb', -1, 'false', 'default', '[0] integrated camera', 0, -1, acqhandle) grab_image_start (acqhandle, -1) while (true) grab_image_async (image, acqhandle, -1) * image acquisition 01: do something endwhile
3、导出c#代码
这里主要关注action函数:
// main procedure private void action() { // local iconic variables hobject ho_image=null; // local control variables htuple hv_acqhandle = new htuple(); // initialize local and output iconic variables hoperatorset.genemptyobj(out ho_image); //image acquisition 01: code generated by image acquisition 01 //image acquisition 01: attention: the initialization may fail in case parameters need to //image acquisition 01: be set in a specific order (e.g., image resolution vs. offset). hv_acqhandle.dispose(); hoperatorset.openframegrabber("directshow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] integrated camera", 0, -1, out hv_acqhandle); hoperatorset.grabimagestart(hv_acqhandle, -1); while ((int)(1) != 0) { ho_image.dispose(); hoperatorset.grabimageasync(out ho_image, hv_acqhandle, -1); //image acquisition 01: do something } ho_image.dispose(); hv_acqhandle.dispose(); }
这段代码只是实现了采集图像,没有在界面上显示。
4、向vs项目添加halcon导出的c#代码
向action()的代码中添加在窗口上显示图像的代码,即使用dispobj函数。然后把action添加到按钮响应中执行。
这样点击按钮之后就会进入死循环不停的grabimage和dispobj,但是实际操作时界面会停止响应,而且图像并不会在窗口内刷新。
5、添加实时显示子线程
主线程中运行循环无法实时显示,必须创建子线程。
这里使用了工作者线程,点击按钮后,启动线程并执行一个循环显示采集的图像;再次点击按钮时,跳出循环结束worker线程。然后继续点击按钮又可以进入子线程开启实时显示,实现随意启停。
private void button1_click(object sender, routedeventargs e) { if (iscameraopened == false) { button1.content = "关闭实时显示"; iscameraopened = true; play_thread = new thread(action); play_thread.start(); } else { button1.content = "开启实时显示"; iscameraopened = false; } }
注意调用线程需添加引用:
using system.threading;//多线程
需要注意的是,为了防止在实时显示过程中突然关闭窗体导致程序崩溃,在窗体的un_load事件中加入强行停止子线程的代码。
private void window_unloaded(object sender, routedeventargs e) { if(play_thread.isalive) { play_thread.abort(); } }
6、调整图像尺寸以适应halconwindow窗口
(1)使用hsmartwindowcontrolwpf控件时,无需再添加鼠标滚轮的响应函数便可使用鼠标滚轮控制图像缩放。
(2)显示单张图像时,可以直接向hsmartwindowcontrolwpf控件的hdisplaycurrentobject属性赋hobject类型的图像即可自动调整图像尺寸来适应窗口大小。
hsmartwindowcontrol1.hdisplaycurrentobject = new himage("girl.png");
但是这个方式不能适用于动态捕获的图像,所以动态捕获的图像还需要手动判断来进行缩放。调整的方式比较简单,就是获取窗口尺寸和图像尺寸进行对比,根据图像过宽还是过高来缩放。
7、源代码
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using system.windows; using system.windows.controls; using system.windows.data; using system.windows.documents; using system.windows.input; using system.windows.media; using system.windows.media.imaging; using system.windows.navigation; using system.windows.shapes; using halcondotnet; using system.threading;//多线程 namespace halconwindowwpfdemo { /// <summary> /// interaction logic for mainwindow.xaml /// </summary> public partial class mainwindow : window { #region 全局变量 private static mainwindow mainwindow = new mainwindow(); private static hwindow hwindow; //全局窗口变量 thread play_thread; //实时显示线程 private static bool iscameraopened; //是否正在实时显示 private static double halconwindowheight; //halcon窗口高度 private static double halconwindowwidth; ////halcon窗口宽度 #endregion #region 初始化 public mainwindow() { initializecomponent(); } private void window_loaded(object sender, routedeventargs e) { hwindow = hsmartwindowcontrol1.halconwindow;//初始化窗口变量 iscameraopened = false; //获取halcon窗口大小 halconwindowheight = mainwindow.hsmartwindowcontrol1.windowsize.width; halconwindowwidth = mainwindow.hsmartwindowcontrol1.windowsize.height; } #endregion #region 界面响应 /// <summary> /// 开启和关闭实时显示按钮 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button1_click(object sender, routedeventargs e) { if (iscameraopened == false) { button1.content = "关闭实时显示"; iscameraopened = true; play_thread = new thread(action); play_thread.start(); } else { button1.content = "开启实时显示"; iscameraopened = false; } } /// <summary> /// 显示一张图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_click(object sender, routedeventargs e) { hsmartwindowcontrol1.hdisplaycurrentobject = new himage("girl.png"); } #endregion #region 实时显示用函数 /// <summary> /// 摄像头实时显示 /// </summary> private static void action() { // local iconic variables hobject ho_image = null; // local control variables htuple hv_acqhandle = new htuple(); // initialize local and output iconic variables hoperatorset.genemptyobj(out ho_image); ho_image.dispose(); hv_acqhandle.dispose(); //image acquisition 01: code generated by image acquisition 01 hoperatorset.openframegrabber("directshow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb", -1, "false", "default", "[0] integrated camera", 0, -1, out hv_acqhandle); hoperatorset.grabimagestart(hv_acqhandle, -1); while (iscameraopened) { hoperatorset.grabimageasync(out ho_image, hv_acqhandle, -1); if (!mainwindow.showhalconimage(ho_image)) break; } ho_image.dispose(); hv_acqhandle.dispose(); } /// <summary> /// 显示图像 /// </summary> /// <param name="image"></param> /// <returns></returns> private bool showhalconimage(hobject ho_image) { #region 缩放图像,适应窗口 //获取图像大小及纵横比 htuple hv_width = new htuple(), hv_height = new htuple(); hoperatorset.getimagesize(ho_image, out hv_width, out hv_height); int im_width = int.parse(hv_width.tostring()); int im_height = int.parse(hv_height.tostring()); double im_aspectratio = (double)(im_width) / (double)(im_height); //获取窗口大小及纵横比 double w_aspectratio = halconwindowwidth / halconwindowheight; hoperatorset.setsystem("int_zooming", "false");//图像缩放之前最好将此参数设置为false. htuple para = new htuple("constant"); hobject ho_zoomimage; hoperatorset.genemptyobj(out ho_zoomimage); ho_zoomimage.dispose(); if (halconwindowwidth < im_width && im_aspectratio > w_aspectratio) { //超宽图像 hoperatorset.zoomimagesize(ho_image, out ho_zoomimage, halconwindowwidth, halconwindowwidth / im_aspectratio, "constant"); } else if (halconwindowheight < im_height && im_aspectratio < w_aspectratio) { //超高图像 hoperatorset.zoomimagesize(ho_image, out ho_zoomimage, halconwindowheight * im_aspectratio, halconwindowheight, para); } #endregion #region 显示图像 try { hwindow.setpart(0, 0, -2, -2); hwindow.dispobj(ho_zoomimage); } catch (exception exp) { //messagebox.show(exp.tostring()); return false; } #endregion return true; } #endregion #region 析构函数 /// <summary> /// 关闭窗体时推出子线程,防止崩溃 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void window_unloaded(object sender, routedeventargs e) { if(play_thread.isalive) { play_thread.abort(); } } #endregion } }
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Blazor server side 自家的一些开源的, 实用型项目的进度之 CEF客户端
.NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)
vue+.netcore可支持业务代码扩展的开发框架 VOL.Vue 2.0版本发布
网友评论