C#用SDK打开海康工业相机,callback取图Bitmap格式,并保存

上次写了python版本的,但是python虽好不方便发布,她带着重重的解释器有时候不方便玩耍.于是C#来了哦.

C#图像一般用Bitmap表示,所以完全C#就够,别的格式可以自行想转换.

命令行哦,没界面.

MVCamera.cs从MVS示例里面添加到项目中,using MvCamCtrl.NET; 就可以,不需要添加mvcameracrtlnet.dll引用;

build BMP的部分程序是自动生成  后面我人工调试出来的. 

using System;

using MvCamCtrl.NET;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
using SC = System.Console;

using System.IO;


using System.Threading;
using System.Diagnostics.Eventing.Reader;
using static System.Net.Mime.MediaTypeNames;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Grab_Callback
{

    class Grab_Callback
    {
        public static MyCamera.cbOutputExdelegate ImageCallback;
        public static MyCamera device = new MyCamera();

        public static Bitmap buildBMP(int width, int height, byte[] imgBytes)
        {
            Bitmap bmp;
            bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
            ImageLockMode.WriteOnly, bmp.PixelFormat);
            Marshal.Copy(imgBytes, 0, bmpData.Scan0, imgBytes.Length);
            bmp.UnlockBits(bmpData);
           // EventTask.Run
            return bmp;
        }
        public static byte[] m_BufForDriver1=null;
        public static Bitmap Bbmp = null;
        private static Bitmap bmpNow;

        public static string Getcwd = System.Environment.CurrentDirectory + "\\";
        public static Bitmap buildBMP(int width, int height, byte[] imgBytes, bool isGrayScale)
        {
            Bitmap bmp;

            if (isGrayScale)
            {
                bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
                ColorPalette palette = bmp.Palette;
                for (int i = 0; i < palette.Entries.Length; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                bmp.Palette = palette;
            }
            else
            {
                bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
            }
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
                ImageLockMode.WriteOnly, bmp.PixelFormat);
            Marshal.Copy(imgBytes, 0, bmpData.Scan0, imgBytes.Length);
            bmp.UnlockBits(bmpData);
            return bmp;
        }

        static void ImageCallbackFunc(IntPtr pData, ref MyCamera.MV_FRAME_OUT_INFO_EX pFrameInfo, IntPtr pUser)
        {
            string x = $"{pFrameInfo.nWidth}/" + $"{pFrameInfo.nHeight}:" + $"{pFrameInfo.nFrameNum} ";
            m_BufForDriver1 = new byte[pFrameInfo.nFrameLen];

            Marshal.Copy(pData, m_BufForDriver1, 0, ((int)pFrameInfo.nFrameLen));

            // 检查图像是否为灰度图
         //   bool isGrayScale = pFrameInfo.nPixelFormat == MyCamera.MV_PIXEL_FORMAT.MONO8 ||
         //                      pFrameInfo.nPixelFormat == MyCamera.MV_PIXEL_FORMAT.MONO16; // 根据实际像素格式常量进行调整

            Bbmp = buildBMP(pFrameInfo.nWidth, pFrameInfo.nHeight, m_BufForDriver1, false);
            Bbmp.Save(Getcwd + pFrameInfo.nFrameNum.ToString() + ".bmp", ImageFormat.Bmp);
            SC.WriteLine(x);

        }

        static void Main(string[] args)
        {
            int nRet = MyCamera.MV_OK;
            MyCamera.MV_CC_Initialize_NET();// ch: 初始化 SDK | en: Initialize SDK

            do
            {
                // ch:枚举设备 | en:Enum device
                MyCamera.MV_CC_DEVICE_INFO_LIST stDevList = new MyCamera.MV_CC_DEVICE_INFO_LIST();
                nRet = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref stDevList);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Enum device failed:{0:x8}", nRet);
                    break;
                }
                Console.WriteLine("Enum device count : " + Convert.ToString(stDevList.nDeviceNum));
                if (0 == stDevList.nDeviceNum)
                {
                    break;
                }

                MyCamera.MV_CC_DEVICE_INFO stDevInfo;                            // 通用设备信息

                // ch:打印设备信息 en:Print device info
                for (Int32 i = 0; i < stDevList.nDeviceNum; i++)
                {
                    stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));

                    if (MyCamera.MV_GIGE_DEVICE == stDevInfo.nTLayerType)
                    {
                        MyCamera.MV_GIGE_DEVICE_INFO_EX stGigEDeviceInfo = (MyCamera.MV_GIGE_DEVICE_INFO_EX)MyCamera.ByteToStruct(stDevInfo.SpecialInfo.stGigEInfo, typeof(MyCamera.MV_GIGE_DEVICE_INFO_EX));
                        uint nIp1 = ((stGigEDeviceInfo.nCurrentIp & 0xff000000) >> 24);
                        uint nIp2 = ((stGigEDeviceInfo.nCurrentIp & 0x00ff0000) >> 16);
                        uint nIp3 = ((stGigEDeviceInfo.nCurrentIp & 0x0000ff00) >> 8);
                        uint nIp4 = (stGigEDeviceInfo.nCurrentIp & 0x000000ff);
                        Console.WriteLine("[device " + i.ToString() + "]:");
                        Console.WriteLine("DevIP:" + nIp1 + "." + nIp2 + "." + nIp3 + "." + nIp4);
                        Console.WriteLine("ModelName:" + stGigEDeviceInfo.chModelName + "\n");
                    }
                    else if (MyCamera.MV_USB_DEVICE == stDevInfo.nTLayerType)
                    {
                        MyCamera.MV_USB3_DEVICE_INFO_EX stUsb3DeviceInfo = (MyCamera.MV_USB3_DEVICE_INFO_EX)MyCamera.ByteToStruct(stDevInfo.SpecialInfo.stUsb3VInfo, typeof(MyCamera.MV_USB3_DEVICE_INFO_EX));
                        Console.WriteLine("[device " + i.ToString() + "]:");
                        Console.WriteLine("SerialNumber:" + stUsb3DeviceInfo.chSerialNumber);
                        Console.WriteLine("ModelName:" + stUsb3DeviceInfo.chModelName + "\n");
                    }
                }

                Int32 nDevIndex = 0;
                Console.Write("Please input index(0-{0:d}):", stDevList.nDeviceNum - 1);
                try
                {
                    nDevIndex = Convert.ToInt32(Console.ReadLine());
                }
                catch
                {
                    Console.Write("Invalid Input!\n");
                    break;
                }

                if (nDevIndex > stDevList.nDeviceNum - 1 || nDevIndex < 0)
                {
                    Console.Write("Input Error!\n");
                    break;
                }
                stDevInfo = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(stDevList.pDeviceInfo[nDevIndex], typeof(MyCamera.MV_CC_DEVICE_INFO));

                // ch:创建设备 | en:Create device
                nRet = device.MV_CC_CreateDevice_NET(ref stDevInfo);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Create device failed:{0:x8}", nRet);
                    break;
                }

                // ch:打开设备 | en:Open device
                nRet = device.MV_CC_OpenDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Open device failed:{0:x8}", nRet);
                    break;
                }

                // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                if (stDevInfo.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    int nPacketSize = device.MV_CC_GetOptimalPacketSize_NET();
                    if (nPacketSize > 0)
                    {
                        nRet = device.MV_CC_SetIntValueEx_NET("GevSCPSPacketSize", nPacketSize);
                        if (nRet != MyCamera.MV_OK)
                        {
                            Console.WriteLine("Warning: Set Packet Size failed {0:x8}", nRet);
                        }
                    }
                    else
                    {
                        Console.WriteLine("Warning: Get Packet Size failed {0:x8}", nPacketSize);
                    }
                }

                // ch:设置触发模式为off || en:set trigger mode as off
                nRet = device.MV_CC_SetEnumValue_NET("TriggerMode", 0);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Set TriggerMode failed:{0:x8}", nRet);
                    break;
                }

                // ch:注册回调函数 | en:Register image callback
                ImageCallback = new MyCamera.cbOutputExdelegate(ImageCallbackFunc);
                nRet = device.MV_CC_RegisterImageCallBackEx_NET(ImageCallback, IntPtr.Zero);
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Register image callback failed!");
                    break;
                }

                // ch:开启抓图 || en: start grab image
                nRet = device.MV_CC_StartGrabbing_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Start grabbing failed:{0:x8}", nRet);
                    break;
                }

                Console.WriteLine("Press enter to exit");
                Console.ReadLine();

                // ch:停止抓图 | en:Stop grabbing
                nRet = device.MV_CC_StopGrabbing_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Stop grabbing failed:{0:x8}", nRet);
                    break;
                }

                // ch:关闭设备 | en:Close device
                nRet = device.MV_CC_CloseDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Close device failed:{0:x8}", nRet);
                    break;
                }

                // ch:销毁设备 | en:Destroy device
                nRet = device.MV_CC_DestroyDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Destroy device failed:{0:x8}", nRet);
                    break;
                }
            } while (false);

            if (MyCamera.MV_OK != nRet)
            {
                // ch:销毁设备 | en:Destroy device
                nRet = device.MV_CC_DestroyDevice_NET();
                if (MyCamera.MV_OK != nRet)
                {
                    Console.WriteLine("Destroy device failed:{0:x8}", nRet);
                }
            }
            // ch: 反初始化SDK | en: Finalize SDK
            MyCamera.MV_CC_Finalize_NET();
            Console.WriteLine("Press enter to exit");
            Console.ReadKey();
        }
    }
}

### 实现海康威视工业相机的IO触发拍照保存像 为了实现这一功能,在C#环境中需利用海康威视提供的SDK来设置触发模式为外部硬件触发(即IO触发),通过回调函数获拍摄到的数据,最后将其转换成位格式进行存储[^1]。 #### 配置说明 在开始编码之前,确保已经安装了海康威视官方提供的开发包,按照文档指导完成了必要的环境搭建工作。对于具体的编程部分,则主要依赖于`MvCamCtrl.NET`命名空间下的类库来进行操作[^3]。 #### 关键代码示例 下面给出一段简化版的关键代码片段用于展示如何完成上述需求: ```csharp using System; using MvCamCtrl.NET; public class CameraController { private IntPtr handle; // 设备句柄 public void Initialize() { // 初始化设备... SetTriggerMode(); } /// <summary> /// 设置触发模式为IO触发 /// </summary> private void SetTriggerMode(){ int nRet = MV_CC_SetEnumValue(handle,"TriggerSelector",0); //选择帧启动作为触发源 if (MV_OK != nRet){ Console.WriteLine("Set TriggerSelector fail!"); return ; } nRet = MV_CC_SetEnumValue(handle,"TriggerSource",2); //设置触发源为线路输入(Line2),具体数值可能因型号而异,请参照API手册确认 if (MV_OK != nRet){ Console.WriteLine("Set TriggerSource fail!"); return ; } nRet = MV_CC_SetEnumValue(handle,"TriggerMode",1); //开启触发模式 if (MV_OK != nRet){ Console.WriteLine("Enable trigger mode fail!"); return ; } } /// <summary> /// 开始采集数据,注册回调方法处理接收到的信息 /// </summary> public void StartCapture(Action<byte[],int> callback){ // 注册回调事件处理器... RegisterImageCallback(callback); // 启动连续抓拍... MV_CC_StartGrabbing(handle); } /// <summary> /// 停止采集 /// </summary> public void StopCapture(){ MV_CC_StopGrabbing(handle); UnregisterImageCallback(); } /// <summary> /// 处理接收到的一帧像数据 /// </summary> /// <param name="data">原始字节数组</param> /// <param name="size">像大小</param> private void HandleFrame(byte[] data,int size){ Bitmap bitmap = ConvertToBitmap(data,size); // 转换成位对象 SaveToFile(bitmap); // 存储文件至磁盘 } /// <summary> /// 将二进制流转化为位形式 /// </summary> protected abstract Bitmap ConvertToBitmap(byte[] rawData, int imageSize); /// <summary> /// 把生成好的位保存下来 /// </summary> protected virtual void SaveToFile(Bitmap image){ string path = $"./images/{Guid.NewGuid().ToString()}.bmp"; image.Save(path,System.Drawing.Imaging.ImageFormat.Bmp); } } ``` 这段程序展示了基本框架的设计思路以及核心逻辑的实现方式。实际应用中还需要考虑更多细节问题,比如错误处理机制、性能优化等方面的内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值