看了大神博客东城青年halcon第十三讲:halcon联合vc实时人脸跟踪,自己就根据这个思路联合C#做了一遍,其halcon算法可见转载链接,这里就不说明了。直奔主题:
界面图
代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
namespace renlian
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//全局变量
HObject ho_Image, ho_Rectangle, ho_ImageReduced;
HObject ho_GrayImage, ho_GrayImage1 = null, ho_RegionAffineTrans = null;
// Local control variables
HTuple hv_AcqHandle = new HTuple(), hv_Width = new HTuple();
HTuple hv_Height = new HTuple(), hv_WindowHandle = new HTuple();
HTuple hv_Row1 = new HTuple(), hv_Column1 = new HTuple();
HTuple hv_Row2 = new HTuple(), hv_Column2 = new HTuple();
HTuple hv_Area = new HTuple(), hv_Row = new HTuple(), hv_Column = new HTuple();
HTuple hv_Phi = new HTuple(), hv_ModelID = new HTuple();
HTuple hv_Row3 = new HTuple(), hv_Column3 = new HTuple();
HTuple hv_Angle = new HTuple(), hv_Score = new HTuple();
HTuple hv_HomMat2D = new HTuple();
//定义显示函数
public void disp_message(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem,
HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
{
// Local iconic variables
// Local control variables
HTuple hv_GenParamName = new HTuple(), hv_GenParamValue = new HTuple();
HTuple hv_Color_COPY_INP_TMP = new HTuple(hv_Color);
HTuple hv_Column_COPY_INP_TMP = new HTuple(hv_Column);
HTuple hv_CoordSystem_COPY_INP_TMP = new HTuple(hv_CoordSystem);
HTuple hv_Row_COPY_INP_TMP = new HTuple(hv_Row);
//Convert the parameters for disp_text.
if ((int)((new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(new HTuple())))) != 0)
{
hv_Color_COPY_INP_TMP.Dispose();
hv_Column_COPY_INP_TMP.Dispose();
hv_CoordSystem_COPY_INP_TMP.Dispose();
hv_Row_COPY_INP_TMP.Dispose();
hv_GenParamName.Dispose();
hv_GenParamValue.Dispose();
return;
}
if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0)
{
hv_Row_COPY_INP_TMP.Dispose();
hv_Row_COPY_INP_TMP = 12;
}
if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0)
{
hv_Column_COPY_INP_TMP.Dispose();
hv_Column_COPY_INP_TMP = 12;
}
//
//Convert the parameter Box to generic parameters.
hv_GenParamName.Dispose();
hv_GenParamName = new HTuple();
hv_GenParamValue.Dispose();
hv_GenParamValue = new HTuple();
if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(0))) != 0)
{
if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleEqual("false"))) != 0)
{
//Display no box
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
"box");
hv_GenParamName.Dispose();
hv_GenParamName = ExpTmpLocalVar_GenParamName;
}
}
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
"false");
hv_GenParamValue.Dispose();
hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
}
}
}
else if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleNotEqual("true"))) != 0)
{
//Set a color other than the default.
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
"box_color");
hv_GenParamName.Dispose();
hv_GenParamName = ExpTmpLocalVar_GenParamName;
}
}
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
hv_Box.TupleSelect(0));
hv_GenParamValue.Dispose();
hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
}
}
}
}
if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(1))) != 0)
{
if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleEqual("false"))) != 0)
{
//Display no shadow.
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
"shadow");
hv_GenParamName.Dispose();
hv_GenParamName = ExpTmpLocalVar_GenParamName;
}
}
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
"false");
hv_GenParamValue.Dispose();
hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
}
}
}
else if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleNotEqual("true"))) != 0)
{
//Set a shadow color other than the default.
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamName = hv_GenParamName.TupleConcat(
"shadow_color");
hv_GenParamName.Dispose();
hv_GenParamName = ExpTmpLocalVar_GenParamName;
}
}
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
{
HTuple
ExpTmpLocalVar_GenParamValue = hv_GenParamValue.TupleConcat(
hv_Box.TupleSelect(1));
hv_GenParamValue.Dispose();
hv_GenParamValue = ExpTmpLocalVar_GenParamValue;
}
}
}
}
//Restore default CoordSystem behavior.
if ((int)(new HTuple(hv_CoordSystem_COPY_INP_TMP.TupleNotEqual("window"))) != 0)
{
hv_CoordSystem_COPY_INP_TMP.Dispose();
hv_CoordSystem_COPY_INP_TMP = "image";
}
//
if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(""))) != 0)
{
//disp_text does not accept an empty string for Color.
hv_Color_COPY_INP_TMP.Dispose();
hv_Color_COPY_INP_TMP = new HTuple();
}
//
HOperatorSet.DispText(hv_WindowHandle, hv_String, hv_CoordSystem_COPY_INP_TMP,
hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP, hv_Color_COPY_INP_TMP, hv_GenParamName,
hv_GenParamValue);
hv_Color_COPY_INP_TMP.Dispose();
hv_Column_COPY_INP_TMP.Dispose();
hv_CoordSystem_COPY_INP_TMP.Dispose();
hv_Row_COPY_INP_TMP.Dispose();
hv_GenParamName.Dispose();
hv_GenParamValue.Dispose();
return;
}
//采集人脸按钮的方法
private void button1_Click(object sender, EventArgs e)
{
// Initialize local and output iconic variables
HOperatorSet.GenEmptyObj(out ho_Image);
HOperatorSet.GenEmptyObj(out ho_Rectangle);
HOperatorSet.GenEmptyObj(out ho_ImageReduced);
HOperatorSet.GenEmptyObj(out ho_GrayImage);
HOperatorSet.GenEmptyObj(out ho_GrayImage1);
HOperatorSet.GenEmptyObj(out ho_RegionAffineTrans);
//基于相关性的实时人脸跟踪(优点:基本不受线性关照的影响)
hv_AcqHandle.Dispose();
HOperatorSet.OpenFramegrabber("DirectShow", 1, 1, 0, 0, 0, 0, "default", 8, "rgb",
-1, "false", "default", "[0] ", 0, -1, out hv_AcqHandle);
HOperatorSet.GrabImageStart(hv_AcqHandle, -1);
ho_Image.Dispose();
HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);
hv_Width.Dispose(); hv_Height.Dispose();
HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
if (HDevWindowStack.IsOpen())
{
HOperatorSet.SetPart(HDevWindowStack.GetActive(), 0, 0, hv_Height, hv_Width);
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.CloseWindow(HDevWindowStack.Pop());
}
HOperatorSet.SetWindowAttr("background_color", "black");
HOperatorSet.OpenWindow(0, 0, hWindowControl1.Width, hWindowControl1.Height, hWindowControl1.HalconWindow, "visible", "", out hv_WindowHandle);
HDevWindowStack.Push(hv_WindowHandle);
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
}
//创建模板
disp_message(hv_WindowHandle, "请创建模板并以鼠标右击结束", "window", -1, -1,
"white", "false");
hv_Row1.Dispose(); hv_Column1.Dispose(); hv_Row2.Dispose(); hv_Column2.Dispose();
HOperatorSet.DrawRectangle1(hv_WindowHandle, out hv_Row1, out hv_Column1, out hv_Row2,
out hv_Column2);
ho_Rectangle.Dispose();
HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row1, hv_Column1, hv_Row2, hv_Column2);
hv_Area.Dispose(); hv_Row.Dispose(); hv_Column.Dispose();
HOperatorSet.AreaCenter(ho_Rectangle, out hv_Area, out hv_Row, out hv_Column);
hv_Phi.Dispose();
HOperatorSet.OrientationRegion(ho_Rectangle, out hv_Phi);
ho_ImageReduced.Dispose();
HOperatorSet.ReduceDomain(ho_Image, ho_Rectangle, out ho_ImageReduced);
ho_GrayImage.Dispose();
HOperatorSet.Rgb1ToGray(ho_ImageReduced, out ho_GrayImage);
hv_ModelID.Dispose();
HOperatorSet.CreateNccModel(ho_GrayImage, "auto", -0.39, 0.79, "auto", "use_polarity",
out hv_ModelID);
if (HDevWindowStack.IsOpen())
{
HOperatorSet.SetDraw(HDevWindowStack.GetActive(), "margin");
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.SetLineWidth(HDevWindowStack.GetActive(), 4);
}
}
//定时器响应函数
private void timer1_Tick(object sender, EventArgs e)
{
ho_Image.Dispose();
HOperatorSet.GrabImageAsync(out ho_Image, hv_AcqHandle, -1);
//寻找模板
ho_GrayImage1.Dispose();
HOperatorSet.Rgb1ToGray(ho_Image, out ho_GrayImage1);
hv_Row3.Dispose(); hv_Column3.Dispose(); hv_Angle.Dispose(); hv_Score.Dispose();
HOperatorSet.FindNccModel(ho_GrayImage1, hv_ModelID, -0.39, 0.78, 0.4, 1, 0.5,
"true", 0, out hv_Row3, out hv_Column3, out hv_Angle, out hv_Score);
hv_HomMat2D.Dispose();
HOperatorSet.VectorAngleToRigid(hv_Row, hv_Column, hv_Phi, hv_Row3, hv_Column3,
hv_Angle, out hv_HomMat2D);
ho_RegionAffineTrans.Dispose();
HOperatorSet.AffineTransRegion(ho_Rectangle, out ho_RegionAffineTrans, hv_HomMat2D,
"nearest_neighbor");
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_Image, HDevWindowStack.GetActive());
}
if (HDevWindowStack.IsOpen())
{
HOperatorSet.DispObj(ho_RegionAffineTrans, HDevWindowStack.GetActive());
}
}
//人脸跟踪按钮的方法
private void button2_Click(object sender, EventArgs e)
{
timer1.Enabled = true; //启动定时器响应函数
}
//关闭采集按钮的方法
private void button3_Click(object sender, EventArgs e)
{
timer1.Enabled = false; //关闭定时器响应函数
HOperatorSet.CloseFramegrabber(hv_AcqHandle); //关闭相机
}
}
}
总结
一、将显示函数和action里的变量放在消息响应函数的前面当做全局变量
二、将action函数中while前面的代码拷贝到采集人脸按钮的方法里
三、将action函数中while里面的代码拷贝到定时器响应函数里
四、将启动定时器响应函数的代码timer1.Enabled = true;放到人脸跟踪按钮的方法里
五、将关闭定时器响应函数的代码timer1.Enabled = false; 和关闭相机的代码HOperatorSet.CloseFramegrabber(hv_AcqHandle);放到关闭采集按钮的方法里
注意:如果重复人脸跟踪操作后无反应,说明是电脑问题,休息一下在运行程序就好了。