通用工业视觉软件设计之相机模块类库-ModuleCamera
一 相机的基础类:CameraBase
using HalconDotNet;
using ModulePublicShare;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ModuleCamera
{
/// <summary>
/// 相机的基础类
/// </summary>
[Serializable]
public class CameraBase
{
public static int m_LastDeviceID = 0;//序列号ID
/// <summary>
/// 设备ID
/// </summary>
private string _DeviceID;
public string m_DeviceID
{
get { return _DeviceID; }
set { _DeviceID = value; }
}
/// <summary>
/// 相机品牌
/// </summary>
private DeviceType _DeviceType;
public DeviceType m_DeviceType
{
get { return _DeviceType; }
set { _DeviceType = value; }
}
/// <summary>
/// 标识符
/// </summary>
private string _UniqueLabe;
public string m_UniqueLabe
{
get { return _UniqueLabe; }
set { _UniqueLabe = value; }
}
/// <summary>
/// 设备内部编号
/// </summary>
private string _SerialNO;
public string m_SerialNO
{
set { _SerialNO = value; }
get { return _SerialNO; }
}
/// <summary>
/// SDK版本信息
/// </summary>
private string _ExtInfo;
public string m_ExtInfo
{
get { return _ExtInfo; }
set { _ExtInfo = value; }
}
/// <summary>
/// 曝光
/// </summary>
private int _ExposeTime = 1360;
public int m_ExposeTime
{
get { return _ExposeTime; }
set { _ExposeTime = value; }
}
/// <summary>
/// 增益
/// </summary>
private int _Gain = 1;
public int m_Gain
{
get { return _Gain; }
set { _Gain = value; }
}
/// <summary>
/// 触发模式
/// </summary>
private TRIGGER_MODE _tRIGGER;
public TRIGGER_MODE m_tRIGGER
{
get { return _tRIGGER; }
set { _tRIGGER = value; }
}
/// <summary>
/// 采集的图像
/// </summary>
[NonSerialized]
private HImage _Image = new HImageExt();
public HImage m_Image
{
get { return _Image; }
set { _Image = value; }
}
/// <summary>
/// 图像的宽度
/// </summary>
[NonSerialized]
private int _ImgWidth;
public int m_ImgWidth
{
get { return _ImgWidth; }
set { _ImgWidth = value; }
}
/// <summary>
/// 图像的高度
/// </summary>
[NonSerialized]
private int _ImgHeight;
public int m_ImgHeight
{
get { return _ImgHeight; }
set { _ImgHeight = value; }
}
/// <summary>
/// 设备连接状态
/// </summary>
private bool _bConnected = false;
public bool m_bConnected
{
get { return _bConnected; }
set { _bConnected = value; }
}
/// <summary>
/// 是否开始采集图像
/// </summary>
private bool _isGrabbing = false;
public bool m_isGrabbing
{
get { return _isGrabbing; }
set { _isGrabbing = value; }
}
/// <summary>
/// 是否为触发模式
/// </summary>
private bool _isTriggerMode = false;
public bool m_isTriggerMode
{
get { return _isTriggerMode; }
set { _isTriggerMode = value; }
}
/// <summary>
/// 是不是最新采集的图像
/// </summary>
[NonSerialized]
private bool _IsNewImage;
public bool m_IsNewImage
{
get { return _IsNewImage; }
set { _IsNewImage = value; }
}
/// <summary>
/// X方向像素当量
/// </summary>
private double dScaleX = 1.0;
public double ScaleX
{
get { return dScaleX; }
set { dScaleX = value; }
}
/// <summary>
/// Y方向像素当量
/// </summary>
private double dScaleY = 1.0;
public double ScaleY
{
get { return dScaleY; }
set { dScaleY = value; }
}
/// <summary>
/// 采集信号
/// </summary>
[NonSerialized]
public AutoResetEvent eventWait = new AutoResetEvent(false);
/// <summary>
/// 构造函数1
/// </summary>
public CameraBase()
{
}
/// <summary>
/// 构造函数2
/// </summary>
/// <param name="deviceType">初始化时指定设备类型</param>
public CameraBase(DeviceType deviceType)
{
this._DeviceType = deviceType;
m_LastDeviceID++;
_DeviceID = "Dev" + m_LastDeviceID;
}
/// <summary>
/// 建立设备连接
/// </summary>
public virtual void ConnectDev() { }
/// <summary>
/// 断开设备连接
/// </summary>
public virtual void DisConnectDev() { }
/// <summary>
/// 设置触发模式
/// </summary>
public virtual bool SetTrigger(TRIGGER_MODE tRIGGER_) { return true; }
/// <summary>
/// 设置曝光时间
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual bool SetExposureTime(int value) { return true; }
/// <summary>
/// 设置增益
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public virtual bool SetGain(int value) { return true; }
/// <summary>
/// 获取参数
/// </summary>
public virtual void GetSetting() { }
/// <summary>
/// 设置参数
/// </summary>
public virtual void SetSetting() { }
/// <summary>
/// 取图
/// </summary>
/// <returns></returns>
public virtual bool CaptureImage(bool byHand) { return true; }
[OnDeserializing()]
internal void OnDeSerializingMethod(StreamingContext context)
{
_Image = new HImage();
eventWait = new AutoResetEvent(false);
}
}
}
二 相机类型:CameraType
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModuleCamera
{
/// <summary>
/// 设备类型
/// </summary>
[Serializable]
public enum DeviceType
{
None,
海康相机,
大华相机,
}
/// <summary>
/// 触发模式
/// </summary>
[Serializable]
public enum TRIGGER_MODE
{
软件触发,
连续采集,
硬件触发,
}
}
三 CamInfo:相机信息类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ModuleCamera
{
/// <summary>
/// 相机信息
/// </summary>
public struct CamInfo
{
/// <summary>
/// 相机品牌
/// </summary>
private DeviceType _DeviceType;
public DeviceType m_DeviceType
{
get { return _DeviceType; }
set { _DeviceType = value; }
}
/// <summary>
/// 设备内部编号
/// </summary>
private string _SerialNO;
public string m_SerialNO
{
set { _SerialNO = value; }
get { return _SerialNO; }
}
/// <summary>
/// 版本信息
/// </summary>
private string _ExtInfo;
public string m_ExtInfo
{
get { return _ExtInfo; }
set { _ExtInfo = value; }
}
/// <summary>
/// 连接状态
/// </summary>
private bool _BConnected;
public bool m_BConnected
{
get { return _BConnected; }
set { _BConnected = value; }
}
}
}
四 海康相机实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MvCamCtrl.NET;
using ModuleLog;
using System.Runtime.InteropServices;
using System.IO;
using System.Runtime.Serialization;
using HalconDotNet;
using System.Drawing;
using System.Threading;
using System.Xml.Linq;
using System.Windows.Media.Media3D;
namespace ModuleCamera
{
/// <summary>
/// 委托
/// </summary>
/// <param name="image"></param>
/// <param name="_user"></param>
// 抓取图像委托
public delegate void GrabImage(int width, int height, IntPtr Red, IntPtr Green, IntPtr Blue);
public delegate void GrabGrayImage(int width, int height, IntPtr Gray);
public delegate void DispImageCallback(HImage image, int _user);
/// <summary>
/// 海康威视
/// </summary>
[Serializable]
public class DriveHKVision : CameraBase
{
/// <summary>
/// 线程锁,保证多线程安全
/// </summary>
[NonSerialized]
Mutex m_mutex = new Mutex();
/// <summary>
/// 委托变量
/// </summary>
// 抓取图像事件
public event GrabImage GrabRGBImageEvent;
public event GrabGrayImage GrabGrayImageEvent;
[NonSerialized]
public DispImageCallback dispImgCallback = null;
/// <summary>
/// 设备列表
/// </summary>
static MyCamera.MV_CC_DEVICE_INFO_LIST m_stDeviceList;
/// <summary>
/// 相机对象
/// </summary>
private MyCamera m_MyCamera = null;
/// <summary>
/// 取像线程
/// </summary>
Thread m_hReceiveThread = null;
/// <summary>
/// 帧信息
/// </summary>
MyCamera.MV_FRAME_OUT_INFO_EX m_stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
/// <summary>
/// 用于从驱动获取图像的缓存
/// </summary>
IntPtr m_BufForDriver;
UInt32 m_nBufSizeForDriver = 0;
byte[] m_pDataForRed = null;
byte[] m_pDataForGreen = null;
byte[] m_pDataForBlue = null;
private Object BufForDriverLock = new Object();
private Object BufForImageLock = new Object(); // 读写图像时锁定
[NonSerialized]
Bitmap m_pcBitmap = null;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="_DeviceType"></param>
public DriveHKVision(DeviceType _DeviceType) : base(_DeviceType)
{
}
/// <summary>
/// 查询相机,添加到相机列表中
/// </summary>
/// <param name="m_CamInfoList"></param>
public static void SearchCameras(out List<CamInfo> m_CamInfoList)
{
m_CamInfoList = new List<CamInfo>();
// ch:创建设备列表 | en:Create Device List
// 枚举设备列表
m_stDeviceList.nDeviceNum = 0;
// 核心1:查找GIGE和USB接口的相机
int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
if (0 != nRet)
{
System.Windows.Forms.MessageBox.Show("查找设备失败!");
Log.Error("查找设备失败!");
return;
}
// ch:打印设备信息 en:Print device info
for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
{
CamInfo _camInfo = new CamInfo();
MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
{
MyCamera.MV_USB3_DEVICE_INFO usb3Info = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
_camInfo.m_SerialNO = usb3Info.chSerialNumber;
_camInfo.m_DeviceType = DeviceType.海康相机;
}
else if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
_camInfo.m_SerialNO = gigeInfo.chSerialNumber;
_camInfo.m_DeviceType = DeviceType.海康相机;
}
// 核心2:添加相机信息
m_CamInfoList.Add(_camInfo);
}
}
/// <summary>
/// 获取相机对应的枚举索引
/// </summary>
/// <param name="CameraID"></param>
/// <returns></returns>
private int GetDeviceIndex(string CameraID)
{
for (int i = 0; i < m_stDeviceList.nDeviceNum; i++)
{
MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
if (gigeInfo.chSerialNumber == CameraID)
return i;
}
else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
{
MyCamera.MV_USB3_DEVICE_INFO usb3Info = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
if (usb3Info.chSerialNumber == CameraID)
return i;
}
}
return -1;
}
/// <summary>
/// 枚举所有设备
/// </summary>
public void EnumDevices()
{
// 枚举设备列表
m_stDeviceList.nDeviceNum = 0;
// 核心:
int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
if (0 != nRet)
{
Log.Error("枚举HIK相机设备失败!");
return;
}
}
/// <summary>
/// 连接相机
/// </summary>
public override void ConnectDev()
{
try
{
// 如果设备已经连接先断开
DisConnectDev();
// 枚举并搜索指定ID的相机是否存在
EnumDevices();
// ch:获取选择的设备信息 | en:Get selected device information
//CCameraInfo device = m_ltDeviceList.Find(item => ((CGigECameraInfo)item).chSerialNumber == m_SerialNO);
int camIdx = GetDeviceIndex(m_SerialNO);
if (camIdx == -1)
{
Log.Error("找不到该ID的相机!");
}
MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[camIdx],
typeof(MyCamera.MV_CC_DEVICE_INFO));
// 建立设备对象
if (null == m_MyCamera)
{
m_MyCamera = new MyCamera();
if (null == m_MyCamera)
{
Log.Error("初始化相机对象失败");
}
}
// 创建设备
int nRet = m_MyCamera.MV_CC_CreateDevice_NET(ref device);
if (MyCamera.MV_OK != nRet)
{
Log.Error($"创建设备失败,失败代码:{nRet}");
}
// 尝试打开设备
nRet = m_MyCamera.MV_CC_OpenDevice_NET();
if (MyCamera.MV_OK != nRet)
{
m_MyCamera.MV_CC_DestroyDevice_NET();
Log.Error($"设备打开失败,失败代码:{nRet}");
}
// 探测网络最佳包大小(只对GigE相机有效)
if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
int nPacketSize = m_MyCamera.MV_CC_GetOptimalPacketSize_NET();
if (nPacketSize > 0)
{
nRet = m_MyCamera.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
if (nRet != MyCamera.MV_OK)
{
Log.Warn($"设置包大小失败,失败代码:{nRet}");
}
}
else
{
Log.Warn($"获取包大小失败,返回的包大小为:{nPacketSize}");
}
}
// ch:设置触发模式为off || en:set trigger mode as off
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
//获取相机参数
GetSetting();
//设置相机参数
SetSetting();
// ch:注册回调函数 | en:Register image callback,把图像数据传出去
GrabGrayImageEvent += GrayImageCallbackFunc;
GrabRGBImageEvent += RGBImageCallbackFunc;
// 标志位置位true
m_isGrabbing = true;
// 核心:取图线程
m_hReceiveThread = new Thread(ReceiveThreadProcess);
m_hReceiveThread.Start();
// 取流之前先清除帧长度
m_stFrameInfo.nFrameLen = 0;
m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8;
// 开始采集
nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
m_isGrabbing = false;
m_hReceiveThread.Join();
Log.Error($"连续采集失败,失败代码:{nRet}");
}
m_bConnected = true;
}
catch (Exception ex)
{
m_bConnected = false;
}
}
/// <summary>
/// 断开相机连接
/// </summary>
public override void DisConnectDev()
{
try
{
if (m_MyCamera == null)
{
return;
}
if (m_MyCamera != null)
{
// 关闭设备
m_MyCamera.MV_CC_CloseDevice_NET();
m_MyCamera.MV_CC_DestroyDevice_NET();
}
m_bConnected = false;
}
catch (Exception)
{
throw;
}
}
/// <summary>
/// 设置曝光时间
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override bool SetExposureTime(int value)
{
m_ExposeTime = value;
try
{
if (m_MyCamera != null && m_bConnected)
{
// 关闭自动曝光
m_MyCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("ExposureTime", value);
if (nRet != MyCamera.MV_OK)
{
System.Windows.Forms.MessageBox.Show("Set Exposure Time Fail!");
return false;
}
else
{
return true;
}
}
return false;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 设置增益
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public override bool SetGain(int value)
{
m_Gain = value;
try
{
if (m_MyCamera != null && m_bConnected)
{
m_MyCamera.MV_CC_SetEnumValue_NET("GainAuto", 0);
int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("Gain", (float)value);
if (nRet != MyCamera.MV_OK)
{
System.Windows.Forms.MessageBox.Show("Set Gain Fail!");
return false;
}
else
{
return true;
}
}
return false;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 设置触发模式
/// </summary>
/// <param name="tRIGGER_"></param>
/// <returns></returns>
public override bool SetTrigger(TRIGGER_MODE tRIGGER_)
{
try
{
if (m_MyCamera != null && m_bConnected)
{
switch (tRIGGER_)
{
case TRIGGER_MODE.软件触发:
int nRet = m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_SOFTWARE);
m_isTriggerMode = true;
break;
case TRIGGER_MODE.连续采集:
//m_pMyCamera.SetEnumValue("TriggerMode", (uint)MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
int nRet2 = m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
m_isTriggerMode = false;
break;
case TRIGGER_MODE.硬件触发:
int nRet3 = m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_ON);
// Line0触发
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerSource", (uint)MyCamera.MV_CAM_TRIGGER_SOURCE.MV_TRIGGER_SOURCE_LINE0);
// 采用上升沿触发
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerActivation", 0);
// 线路防抖 250us
m_MyCamera.MV_CC_SetIntValue_NET("LineDebouncerTime", 250);
m_isTriggerMode = true;
break;
default:
break;
}
return true;
}
else
{
return false;
}
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 采集图像
/// </summary>
/// <param name="byHand">是否手动采集图像</param>
/// <returns></returns>
public override bool CaptureImage(bool byHand)
{
try
{
if (m_MyCamera == null)
{
m_bConnected = false;
return false;
}
// ch:触发命令 | en:Trigger command
int nRet = m_MyCamera.MV_CC_SetCommandValue_NET("TriggerSoftware");
if (MyCamera.MV_OK != nRet)
{
System.Windows.Forms.MessageBox.Show("Open camera failed!");
Log.Error("打开相机失败!");
m_bConnected = false;
return false;
}
return true;
}
catch (Exception)
{
return false;
}
}
/// <summary>
/// 设置参数
/// </summary>
public override void SetSetting()
{
if (m_MyCamera == null && !m_bConnected)
return;
//设置曝光
SetExposureTime(m_ExposeTime);
//设置增益
SetGain(m_Gain);
// 设置缓存个数为8(默认值为16)
//m_dev.StreamGrabber.SetBufferCount(8);
//设置触发模式
SetTrigger(m_tRIGGER);
}
/// <summary>
/// 获取参数
/// </summary>
public override void GetSetting()
{
if (m_MyCamera == null && !m_bConnected)
return;
// 获取曝光时间
MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
int nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
if (MyCamera.MV_OK == nRet)
{
m_ExposeTime = Convert.ToInt32(stParam.fCurValue);
}
//获取增益参数
stParam = new MyCamera.MVCC_FLOATVALUE();
nRet = m_MyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);
if (MyCamera.MV_OK == nRet)
{
m_Gain = Convert.ToInt32(stParam.fCurValue);
}
}
/// <summary>
/// 取像线程(核心)
/// </summary>
private void ReceiveThreadProcess()
{
MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
int nRet = m_MyCamera.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
if (MyCamera.MV_OK != nRet)
{
Log.Error($"读取PayloadSize失败,失败代码:{nRet}");
return;
}
UInt32 nPayloadSize = stParam.nCurValue;
// 获取图像高
nRet = m_MyCamera.MV_CC_GetIntValue_NET("Height", ref stParam);
if (MyCamera.MV_OK != nRet)
{
Log.Error($"获取图像高失败,失败代码:{nRet}");
return;
}
uint nHeight = stParam.nCurValue;
// 获取图像宽
nRet = m_MyCamera.MV_CC_GetIntValue_NET("Width", ref stParam);
if (MyCamera.MV_OK != nRet)
{
Log.Error($"获取图像宽失败,失败代码:{nRet}");
return;
}
uint nWidth = stParam.nCurValue;
// 根据图像大小设置图像缓存
m_pDataForRed = new byte[nWidth * nHeight];
m_pDataForGreen = new byte[nWidth * nHeight];
m_pDataForBlue = new byte[nWidth * nHeight];
if (3 * nPayloadSize > m_nBufSizeForDriver)
{
if (m_BufForDriver != IntPtr.Zero)
{
Marshal.Release(m_BufForDriver);
}
m_nBufSizeForDriver = 3 * nPayloadSize;
m_BufForDriver = Marshal.AllocHGlobal((Int32)m_nBufSizeForDriver);
}
if (m_BufForDriver == IntPtr.Zero)
{
return;
}
IntPtr pImageBuffer = Marshal.AllocHGlobal((int)nPayloadSize * 3);
if (pImageBuffer == IntPtr.Zero)
{
Log.Error($"申请图像缓存区失败!");
return;
}
MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
IntPtr RedPtr = IntPtr.Zero;
IntPtr GreenPtr = IntPtr.Zero;
IntPtr BluePtr = IntPtr.Zero;
IntPtr pTemp = IntPtr.Zero;
while (m_isGrabbing)
{
lock (BufForDriverLock)
{
nRet = m_MyCamera.MV_CC_GetOneFrameTimeout_NET(m_BufForDriver, m_nBufSizeForDriver, ref stFrameInfo, 1000);
if (nRet == MyCamera.MV_OK)
{
Log.Debug("相机取图完成,开始处理...");
m_stFrameInfo = stFrameInfo;
}
}
HImage hImage = new HImage();
if (nRet == MyCamera.MV_OK)
{
// 彩色相机
if (IsColorData(stFrameInfo.enPixelType))
{
if (stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed)
{
pTemp = m_BufForDriver;
}
else
{
nRet = ConvertToRGB(m_MyCamera, m_BufForDriver, stFrameInfo.nHeight, stFrameInfo.nWidth, stFrameInfo.enPixelType, pImageBuffer);
if (MyCamera.MV_OK != nRet)
{
return;
}
pTemp = pImageBuffer;
}
//hImage.GenImageInterleaved(pTemp, "rgb", (int)stFrameInfo.nWidth, (int)stFrameInfo.nHeight, 0, "byte", (int)stFrameInfo.nWidth, (int)stFrameInfo.nHeight, 0, 0, -1, 0);
//HOperatorSet.WriteImage(hImage, "jpg", 255, "D://1");
unsafe
{
byte* pBufForSaveImage = (byte*)pTemp;
UInt32 nSupWidth = (stFrameInfo.nWidth + (UInt32)3) & 0xfffffffc;//5120
for (int nRow = 0; nRow < stFrameInfo.nHeight; nRow++)
{
for (int col = 0; col < stFrameInfo.nWidth; col++)
{
m_pDataForRed[nRow * nSupWidth + col] = pBufForSaveImage[nRow * stFrameInfo.nWidth * 3 + (3 * col)];
m_pDataForGreen[nRow * nSupWidth + col] = pBufForSaveImage[nRow * stFrameInfo.nWidth * 3 + (3 * col + 1)];
m_pDataForBlue[nRow * nSupWidth + col] = pBufForSaveImage[nRow * stFrameInfo.nWidth * 3 + (3 * col + 2)];
}
}
}
RedPtr = Marshal.UnsafeAddrOfPinnedArrayElement(m_pDataForRed, 0);
GreenPtr = Marshal.UnsafeAddrOfPinnedArrayElement(m_pDataForGreen, 0);
BluePtr = Marshal.UnsafeAddrOfPinnedArrayElement(m_pDataForBlue, 0);
//try
//{
// HOperatorSet.GenImage3Extern(out HObject Hobj, (HTuple)"byte", stFrameInfo.nWidth, stFrameInfo.nHeight,
// (new HTuple(RedPtr)), (new HTuple(GreenPtr)), (new HTuple(BluePtr)), IntPtr.Zero);
// HOperatorSet.WriteImage(Hobj, "jpg", 255, "D://1");
//}
//catch (System.Exception ex)
//{
// MessageBox.Show(ex.ToString());
//}
lock (BufForImageLock)
{
Log.Debug("相机触发事件...");
if (GrabRGBImageEvent != null)
GrabRGBImageEvent(stFrameInfo.nWidth, stFrameInfo.nHeight, RedPtr, GreenPtr, BluePtr);
}
}
else if (IsMonoData(stFrameInfo.enPixelType)) // 黑白图像
{
if (stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
{
pTemp = m_BufForDriver;
}
else
{
nRet = ConvertToMono8(m_MyCamera, m_BufForDriver, pImageBuffer, stFrameInfo.nHeight, stFrameInfo.nWidth, stFrameInfo.enPixelType);
if (MyCamera.MV_OK != nRet)
{
return;
}
pTemp = pImageBuffer;
}
// 通过事件传递图像数据
lock (BufForImageLock)
{
if (GrabGrayImageEvent != null)
GrabGrayImageEvent(stFrameInfo.nWidth, stFrameInfo.nHeight, pTemp);
}
}
else
{
continue;
}
}
else
{
if (m_isTriggerMode)
{
Thread.Sleep(5);
}
}
}
}
/// <summary>
/// 回传灰色图像
/// </summary>
/// <param name="pData"></param>
/// <param name="pFrameInfo"></param>
/// <param name="pUser"></param>
public void GrayImageCallbackFunc(int width, int height, IntPtr ImageData)
{
try
{
// 获取图像队列最新帧
m_mutex.WaitOne();
m_mutex.ReleaseMutex();
// 灰度图
HImage hImg = new HImage();
hImg.GenImage1("byte", width, height, ImageData);
// 核心:复制父类图像变量,可用于传递图像
m_Image = new HalconDotNet.HImage(hImg);
eventWait.Set();
// 显示图像委托变量
if (dispImgCallback != null)
{
// 核心:传递图像
dispImgCallback(m_Image, 0);
}
}
catch (Exception)
{
eventWait.Set();
}
}
/// <summary>
/// 回传彩色halcon图像
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="Red"></param>
/// <param name="Green"></param>
/// <param name="Blue"></param>
public void RGBImageCallbackFunc(int width, int height, IntPtr Red, IntPtr Green, IntPtr Blue)
{
try
{
// 获取图像队列最新帧
m_mutex.WaitOne();
m_mutex.ReleaseMutex();
HImage hImg = new HImage();
hImg.GenImage3Extern("byte", width, height, Red, Green, Blue, IntPtr.Zero);
// 核心:复制父类图像变量,可用于传递图像
m_Image = new HalconDotNet.HImage(hImg);
eventWait.Set();
// 显示图像委托变量
if (dispImgCallback != null)
{
// 核心:传递图像
dispImgCallback(m_Image, 0);
}
}
catch (Exception)
{
eventWait.Set();
}
}
/// <summary>
/// 判断是否为黑白图像
/// </summary>
/// <param name="enGvspPixelType"></param>
/// <returns></returns>
private Boolean IsMonoData(MyCamera.MvGvspPixelType enGvspPixelType)
{
switch (enGvspPixelType)
{
case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
return true;
default:
return false;
}
}
/// <summary>
/// 判断是否为彩色图像
/// </summary>
/// <param name="enGvspPixelType"></param>
/// <returns></returns>
private Boolean IsColorData(MyCamera.MvGvspPixelType enGvspPixelType)
{
switch (enGvspPixelType)
{
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
case MyCamera.MvGvspPixelType.PixelType_Gvsp_YCBCR411_8_CBYYCRYY:
return true;
default:
return false;
}
}
/// <summary>
/// 转换为RGB格式
/// </summary>
/// <param name="obj"></param>
/// <param name="pSrc"></param>
/// <param name="nHeight"></param>
/// <param name="nWidth"></param>
/// <param name="nPixelType"></param>
/// <param name="pDst"></param>
/// <returns></returns>
private Int32 ConvertToRGB(object obj, IntPtr pSrc, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType, IntPtr pDst)
{
if (IntPtr.Zero == pSrc || IntPtr.Zero == pDst)
{
return MyCamera.MV_E_PARAMETER;
}
int nRet = MyCamera.MV_OK;
MyCamera device = obj as MyCamera;
MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
stPixelConvertParam.pSrcData = pSrc;//源数据
if (IntPtr.Zero == stPixelConvertParam.pSrcData)
{
return -1;
}
stPixelConvertParam.nWidth = nWidth;//图像宽度
stPixelConvertParam.nHeight = nHeight;//图像高度
stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);
stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) >> 16) & 0x00ff) >> 3);
stPixelConvertParam.pDstBuffer = pDst;//转换后的数据
stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed;
stPixelConvertParam.nDstBufferSize = (uint)nWidth * nHeight * 3;
nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
if (MyCamera.MV_OK != nRet)
{
return -1;
}
return MyCamera.MV_OK;
}
/// <summary>
/// 转换为Mono8格式
/// </summary>
/// <param name="obj"></param>
/// <param name="pInData"></param>
/// <param name="pOutData"></param>
/// <param name="nHeight"></param>
/// <param name="nWidth"></param>
/// <param name="nPixelType"></param>
/// <returns></returns>
private Int32 ConvertToMono8(object obj, IntPtr pInData, IntPtr pOutData, ushort nHeight, ushort nWidth, MyCamera.MvGvspPixelType nPixelType)
{
if (IntPtr.Zero == pInData || IntPtr.Zero == pOutData)
{
return MyCamera.MV_E_PARAMETER;
}
int nRet = MyCamera.MV_OK;
MyCamera device = obj as MyCamera;
MyCamera.MV_PIXEL_CONVERT_PARAM stPixelConvertParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
stPixelConvertParam.pSrcData = pInData;//源数据
if (IntPtr.Zero == stPixelConvertParam.pSrcData)
{
return -1;
}
stPixelConvertParam.nWidth = nWidth;//图像宽度
stPixelConvertParam.nHeight = nHeight;//图像高度
stPixelConvertParam.enSrcPixelType = nPixelType;//源数据的格式
stPixelConvertParam.nSrcDataLen = (uint)(nWidth * nHeight * ((((uint)nPixelType) >> 16) & 0x00ff) >> 3);
stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * ((((uint)MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed) >> 16) & 0x00ff) >> 3);
stPixelConvertParam.pDstBuffer = pOutData;//转换后的数据
stPixelConvertParam.enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
stPixelConvertParam.nDstBufferSize = (uint)(nWidth * nHeight * 3);
nRet = device.MV_CC_ConvertPixelType_NET(ref stPixelConvertParam);//格式转换
if (MyCamera.MV_OK != nRet)
{
return -1;
}
return nRet;
}
}
}