一、查找相机设备
/// <summary>
/// 枚举相机
/// </summary>
public List<string> DeviceListAcq()
{
var list = new List<string>();
// ch:创建设备列表 | en:Create Device List
System.GC.Collect();
//cbDeviceList.Items.Clear();
list.Clear();
m_stDeviceList.nDeviceNum = 0;
//MV_CC_EnumDevices_NET 查找设备 枚举了GigE相机的设备信息 CGigECameraInfo 、
//U3V相机的设备信息 CUSBCameraInfo 、Camera Link相机的设备信息 CCamLCameraInfo 。
//查找成功 返回0 没有查找成功--非0 显示ShowErrorMsg
int nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref m_stDeviceList);
if (0 != nRet)
{
throw new ArgumentException("Enum Devices Fail");
//MessageBox.Show("Enum Devices Fail");
}
// ch:在窗体列表中显示设备名 | en:Display device name in the form list
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.chUserDefinedName != "")
{
list.Add("GEV: " + gigeInfo.chUserDefinedName + " (" + gigeInfo.chSerialNumber + ")");
}
else
{
list.Add("GEV: " + gigeInfo.chManufacturerName + " " + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")");
}
}
else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
{
MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)MyCamera.ByteToStruct(device.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO));
if (usbInfo.chUserDefinedName != "")
{
list.Add("U3V: " + usbInfo.chUserDefinedName + " (" + usbInfo.chSerialNumber + ")");
}
else
{
list.Add("U3V: " + usbInfo.chManufacturerName + " " + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")");
}
}
}
// ch:选择第一项 | en:Select the first item
//if (m_stDeviceList.nDeviceNum != 0)
//{
// cbDeviceList.SelectedIndex = 0;
//}
return list;
}
二、打开相机
/// <summary>
/// 获得相机的信息。异常:ArgumentException
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public MyCamera.MV_CC_DEVICE_INFO GetCameraInfo(int index)
{
if (m_stDeviceList.nDeviceNum == 0)// || cbDeviceList.SelectedIndex == -1)
{
throw new ArgumentException("没有可用的相机设备");
}
// ch:获取选择的设备信息 | en:Get selected device information
MyCamera.MV_CC_DEVICE_INFO device =
(MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(m_stDeviceList.pDeviceInfo[index],
typeof(MyCamera.MV_CC_DEVICE_INFO));
return device;
}
/// <summary>
/// 打开相机。异常:ArgumentException
/// </summary>
/// <param name="index"></param>
public void OpenCamera(int index)
{
try
{
//获得相机信息
var camerainfo = GetCameraInfo(index);
//创建相机句柄
int nRet= m_MyCamera.MV_CC_CreateDevice_NET(ref camerainfo);
if (MyCamera.MV_OK != nRet)
{
throw new ArgumentException("创建相机句柄失败!");
}
nRet = m_MyCamera.MV_CC_OpenDevice_NET();
if (MyCamera.MV_OK != nRet)
{
m_MyCamera.MV_CC_DestroyDevice_NET();
throw new ArgumentException(string.Format("打开相机失败!{0}",nRet));
}
// ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
if (camerainfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
{
int nPacketSize = m_MyCamera.MV_CC_GetOptimalPacketSize_NET();
if (nPacketSize > 0)
{
nRet = m_MyCamera.MV_CC_SetIntValueEx_NET("GevSCPSPacketSize", nPacketSize);
if (nRet != MyCamera.MV_OK)
{
throw new ArgumentException(string.Format("Set Packet Size failed!",nRet));
}
}
else
{
throw new ArgumentException(string.Format("Get Packet Size failed!", nPacketSize));
}
}
// ch:设置采集连续模式 | en:Set Continues Aquisition Mode
m_MyCamera.MV_CC_SetEnumValue_NET("AcquisitionMode", (uint)MyCamera.MV_CAM_ACQUISITION_MODE.MV_ACQ_MODE_CONTINUOUS);
m_MyCamera.MV_CC_SetEnumValue_NET("TriggerMode", (uint)MyCamera.MV_CAM_TRIGGER_MODE.MV_TRIGGER_MODE_OFF);
}
catch(ArgumentException ex)
{
throw ex;
}
}
public void CloseCamera()
{
// ch:取流标志位清零 | en:Reset flow flag bit
if (m_bGrabbing == true)
{
m_bGrabbing = false;
m_hReceiveThread.Join();
}
if (m_BufForDriver != IntPtr.Zero)
{
Marshal.Release(m_BufForDriver);
}
// ch:关闭设备 | en:Close Device
m_MyCamera.MV_CC_CloseDevice_NET();
m_MyCamera.MV_CC_DestroyDevice_NET();
}
三、关闭相机
public void CloseCamera()
{
// ch:取流标志位清零 | en:Reset flow flag bit
if (m_bGrabbing == true)
{
m_bGrabbing = false;
m_hReceiveThread.Join();
}
if (m_BufForDriver != IntPtr.Zero)
{
Marshal.Release(m_BufForDriver);
}
// ch:关闭设备 | en:Close Device
m_MyCamera.MV_CC_CloseDevice_NET();
m_MyCamera.MV_CC_DestroyDevice_NET();
}
四、开始采集图像
/// <summary>
/// 线程
/// </summary>
public 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)
{
//ShowErrorMsg("Get PayloadSize failed", nRet);
return;
}
UInt32 nPayloadSize = stParam.nCurValue;
if (nPayloadSize > m_nBufSizeForDriver)
{
if (m_BufForDriver != IntPtr.Zero)
{
Marshal.Release(m_BufForDriver);
}
m_nBufSizeForDriver = nPayloadSize;
m_BufForDriver = Marshal.AllocHGlobal((Int32)m_nBufSizeForDriver);
}
if (m_BufForDriver == IntPtr.Zero)
{
return;
}
MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
//MyCamera.MV_DISPLAY_FRAME_INFO stDisplayInfo = new MyCamera.MV_DISPLAY_FRAME_INFO();
while (m_bGrabbing)
{
lock (BufForDriverLock)
{
nRet = m_MyCamera.MV_CC_GetOneFrameTimeout_NET(m_BufForDriver, nPayloadSize, ref stFrameInfo, 1000);
if (nRet == MyCamera.MV_OK)
{
m_stFrameInfo = stFrameInfo;
}
}
if (nRet == MyCamera.MV_OK)
{
//显示图像
stDisplayInfo.hWnd = winHandle;
stDisplayInfo.pData = m_BufForDriver;
stDisplayInfo.nDataLen = stFrameInfo.nFrameLen;
stDisplayInfo.nWidth = stFrameInfo.nWidth;
stDisplayInfo.nHeight = stFrameInfo.nHeight;
stDisplayInfo.enPixelType = stFrameInfo.enPixelType;
m_MyCamera.MV_CC_DisplayOneFrame_NET(ref stDisplayInfo);
}
//else
//{
// if (bnTriggerMode.Checked)
// {
// Thread.Sleep(5);
// }
//}
}
}
/// <summary>
/// 开始采集。异常:ArgumentException
/// </summary>
public void StartGrab()
{
// ch:标志位置位true | en:Set position bit true
m_bGrabbing = true;
m_hReceiveThread = new Thread(ReceiveThreadProcess);
m_hReceiveThread.Start();
m_stFrameInfo.nFrameLen = 0;//取流之前先清除帧长度
m_stFrameInfo.enPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
// ch:开始采集 | en:Start Grabbing
int nRet = m_MyCamera.MV_CC_StartGrabbing_NET();
if (MyCamera.MV_OK != nRet)
{
m_bGrabbing = false;
m_hReceiveThread.Join();
throw new ArgumentException(string.Format("Start Grabbing Fail!{0}", nRet));
}
}
五、停止采集图像
/// <summary>
/// 停止采集。 异常:ArgumentException
/// </summary>
public void StopGrab()
{
// ch:标志位设为false | en:Set flag bit false
m_bGrabbing = false;
m_hReceiveThread.Join();
// ch:停止采集 | en:Stop Grabbing
//MV_CC_StopGrabbing_NET 停止采集图像。 成功,返回MyCamera.MV_OK(0);失败,返回错误码
int nRet = m_MyCamera.MV_CC_StopGrabbing_NET();
if (nRet != MyCamera.MV_OK)
{
throw new ArgumentException(string.Format("Stop Grabbing Fail!{0}", nRet));
}
}
六、保持采集的图像
/// <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> 成功,返回0;错误,返回-1
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>
///将图片保存为BMP格式 异常:ArgumentException
/// </summary>
/// <param name="fname"></param>
public void ImageSaveBMP(string fname)
{
if (false == m_bGrabbing)
{
throw new ArgumentException(string.Format("没有开始采集不能保存图像!0"));
}
IntPtr pTemp = IntPtr.Zero;
MyCamera.MvGvspPixelType enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Undefined;
//先判断相机类型 是Mono8黑白还是BGR8彩色
if (m_stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8 ||
m_stFrameInfo.enPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed)
{
pTemp = m_BufForDriver;
enDstPixelType = m_stFrameInfo.enPixelType;
}
else
{
UInt32 nSaveImageNeedSize = 0;
MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
lock (BufForDriverLock)
{
if (m_stFrameInfo.nFrameLen == 0)
{
throw new ArgumentException(string.Format("Save Bmp Fail! 0"));
}
//判断是否是黑白数据函数
if (IsMonoData(m_stFrameInfo.enPixelType))
{
enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8;
nSaveImageNeedSize = (uint)m_stFrameInfo.nWidth * m_stFrameInfo.nHeight;
}
else if (IsColorData(m_stFrameInfo.enPixelType))
{
enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_BGR8_Packed;
nSaveImageNeedSize = (uint)m_stFrameInfo.nWidth * m_stFrameInfo.nHeight * 3;
}
else
{
throw new ArgumentException(string.Format("No such pixel type! 0"));
}
if (m_nBufSizeForSaveImage < nSaveImageNeedSize)
{
if (m_BufForSaveImage != IntPtr.Zero)
{
Marshal.Release(m_BufForSaveImage);
}
m_nBufSizeForSaveImage = nSaveImageNeedSize;
m_BufForSaveImage = Marshal.AllocHGlobal((Int32)m_nBufSizeForSaveImage);
}
stConverPixelParam.nWidth = m_stFrameInfo.nWidth;
stConverPixelParam.nHeight = m_stFrameInfo.nHeight;
stConverPixelParam.pSrcData = m_BufForDriver;
stConverPixelParam.nSrcDataLen = m_stFrameInfo.nFrameLen;
stConverPixelParam.enSrcPixelType = m_stFrameInfo.enPixelType;
stConverPixelParam.enDstPixelType = enDstPixelType;
stConverPixelParam.pDstBuffer = m_BufForSaveImage;
stConverPixelParam.nDstBufferSize = m_nBufSizeForSaveImage;
int nRet = m_MyCamera.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
if (MyCamera.MV_OK != nRet)
{
throw new ArgumentException(string.Format("Convert Pixel Type Fail! 0"));
}
pTemp = m_BufForSaveImage;
}
}
lock (BufForDriverLock)
{
if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
{
//************************Mono8 转 Bitmap*******************************
Bitmap bmp = new Bitmap(m_stFrameInfo.nWidth, m_stFrameInfo.nHeight, m_stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pTemp);
ColorPalette cp = bmp.Palette;
// init palette
for (int i = 0; i < 256; i++)
{
cp.Entries[i] = Color.FromArgb(i, i, i);
}
// set palette back
bmp.Palette = cp;
bmp.Save(fname, ImageFormat.Bmp);
}
else
{
//*********************BGR8 转 Bitmap**************************
try
{
Bitmap bmp = new Bitmap(m_stFrameInfo.nWidth, m_stFrameInfo.nHeight, m_stFrameInfo.nWidth * 3, PixelFormat.Format24bppRgb, pTemp);
bmp.Save("image.bmp", ImageFormat.Bmp);
}
catch
{
throw new ArgumentException(string.Format("Write File Fail! 0"));
}
}
}
//throw new ArgumentException(string.Format("Save Succeed! 0"));
}
七、设置相机参数
/// <summary>
/// 设置相机参数。异常:ArgumentException
/// </summary>
/// <param name="date"></param>
public void WriteCCDConfig(Tuple<string, string, string> date)
{
m_MyCamera.MV_CC_SetEnumValue_NET("ExposureAuto", 0);
int nRet = m_MyCamera.MV_CC_SetFloatValue_NET("ExposureTime", float.Parse(date.Item1));
if (nRet != MyCamera.MV_OK)
{
throw new ArgumentException(string.Format("Set Exposure Time Fail! {0}", nRet));
}
m_MyCamera.MV_CC_SetEnumValue_NET("GainAuto", 0);
nRet = m_MyCamera.MV_CC_SetFloatValue_NET("Gain", float.Parse(date.Item2));
if (nRet != MyCamera.MV_OK)
{
throw new ArgumentException(string.Format("Set Gain Fail! {0}", nRet));
}
nRet = m_MyCamera.MV_CC_SetFloatValue_NET("AcquisitionFrameRate", float.Parse(date.Item3));
if (nRet != MyCamera.MV_OK)
{
throw new ArgumentException(string.Format("Set Frame Rate Fail! {0}", nRet));
}
}
八、读取相机参数
/// <summary>
/// 读取参数信息。异常:ArgumentException
/// </summary>
/// <returns></returns>
public Tuple<string,string,string> ReadCCDConfig()
{
MyCamera.MVCC_FLOATVALUE stParam = new MyCamera.MVCC_FLOATVALUE();
int nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ExposureTime", ref stParam);
string s1 = "0", s2 = "0", s3 = "0";
//获得曝光
if (MyCamera.MV_OK == nRet)
{
s1 = stParam.fCurValue.ToString("F1");//F1为一种格式
}
//获得增益
nRet = m_MyCamera.MV_CC_GetFloatValue_NET("Gain", ref stParam);
if (MyCamera.MV_OK == nRet)
{
s2 = stParam.fCurValue.ToString("F1");
}
//获得帧率
nRet = m_MyCamera.MV_CC_GetFloatValue_NET("ResultingFrameRate", ref stParam);
if (MyCamera.MV_OK == nRet)
{
s3= stParam.fCurValue.ToString("F1");
}
return new Tuple<string, string, string>(s1, s2, s3);
}
九、界面设计
界面程序:
namespace HaiKangCameraSDKDemo
{
public partial class Form1 : Form
{
hkccdSDK hkccd = new hkccdSDK();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
hkccd.winHandle = pictureBox1.Handle;
cbxCCDList.Items.Clear();
cbxCCDList.Items.AddRange(hkccd.DeviceListAcq().ToArray());
}
private void btnOpenDevice_Click(object sender, EventArgs e)
{
var index = cbxCCDList.SelectedIndex;
if (index < 0) return;
try
{
hkccd.OpenCamera(index);
MessageBox.Show("设备打开成功");
}
catch(ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnCloseDevice_Click(object sender, EventArgs e)
{
hkccd.CloseCamera();
MessageBox.Show("设备关闭成功");
}
private void btnStartGrab_Click(object sender, EventArgs e)
{
try
{
hkccd.StartGrab();
MessageBox.Show("已经开始采集");
}
catch (ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnStopGrab_Click(object sender, EventArgs e)
{
try
{
hkccd.StopGrab();
}
catch(ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnSaveBMP_Click(object sender, EventArgs e)
{
try
{
hkccd.ImageSaveBMP("D:\\b1.bmp");
}
catch(ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnReadConfig_Click(object sender, EventArgs e)
{
var data= hkccd.ReadCCDConfig();
txtExposure.Text = data.Item1;
txtGain.Text = data.Item2;
txtFrame.Text = data.Item3;
}
private void btnSaveConfig_Click(object sender, EventArgs e)
{
float v1 = 0, v2 = 0,v3 = 0;
if(!float.TryParse(txtExposure.Text, out v1)||
!float.TryParse(txtGain.Text, out v2)||
!float.TryParse(txtFrame.Text, out v3) )
{
MessageBox.Show("参数格式不正确!");
return;
}
try
{
hkccd.WriteCCDConfig(new Tuple<string, string, string>(v1.ToString("F1"), v2.ToString("F1"), v3.ToString("F1")));
MessageBox.Show("参数写入成功");
}
catch (ArgumentException ex)
{
MessageBox.Show(ex.Message);
}
}
}
}