Unity控制佳能单反拍照及数据获取 | 您所在的位置:网站首页 › 佳能单反相机开关键 › Unity控制佳能单反拍照及数据获取 |
市面比较常用佳能单反,其他单反是否也提供SDK没有搜过。 佳能单反一般选用EOS500D,550D,600D,650D,750D这些都是被EDSDK所支持的。 截止2019年年初,佳能官方EDSDK需要在官网申请,不对中国提供。 我是使用的EDSDK的版本是3.5/3.6.1 单反侧面翻盖打开后,一般会看到两个接口,一个是micro usb,一个是mini hdmi。前者是本文章主要介绍的方式所使用的,即通过micro usb 转 usb线连接单反与主机 单反开机,把拨盘拨到M挡 如果觉得原配的usb线太短,可以加一根usb延长线,根据距离考虑是否要自带放大器的 EDSDK的dll和c#脚本导入之后如下 我们主要需要关注的是SDKHander.cs。它定义了变量、事件、连接设备方法和摄像机命令。 STAThread是一个线程管理脚本。 数值对应表: 光圈 快门 这个纯粹就是准备好一个RawImage组件,准备播放。 tt = new Texture2D(1920, 1080,TextureFormat.RGB24,true); moviePlane.texture = tt; 5 控制与输出 private bool isLiveOn = false; private byte[] tempBytes; // Update is called once per frame void Update () { if (Input.GetKeyDown(KeyCode.S)) { //拍照 CameraHandler.TakePhoto(); } if (Input.GetKeyDown(KeyCode.D)) { //开直播 CameraHandler.StartLiveView(); isLiveOn = true; } if (Input.GetKeyDown(KeyCode.F)) { //退出直播间~~ CameraHandler.StopLiveView(); isLiveOn = false; } if (isLiveOn) { //如果直播在开着,就一帧帧load显示。这里才是有坑的地方。 tempBytes = CameraHandler.GetImageByte(); tt.LoadImage(tempBytes); } } 6 录像视频流的API改造佳能的EDSDK提供的cs脚本并没有针对Unity,Unity C#的开发和.net framework的开发最突出的问题就是:C#里面的Bitmap在Unity里面没有,怎么把Bitmap转换成Texture呢? 在SDKHandler.cs里面需要做一些改动 1 新增函数和变量 public byte[] TextureBytes;//byte数组,外部获取 public byte[] GetImageByte() { if (TextureBytes != null && TextureBytes.Length != 0) return TextureBytes; return null; } public Bitmap TextureBitmap;//Bitmap中转变量 private MemoryStream ms;//转换中的关键变量2 找到DownloadEvf函数,在函数体内做如下修改 //run live view while (IsLiveViewOn) { //download current live view image err = EDSDKLib.EDSDK.EdsCreateEvfImageRef(stream, out EvfImageRef); if (err == EDSDKLib.EDSDK.EDS_ERR_OK) err = EDSDKLib.EDSDK.EdsDownloadEvfImage(MainCamera.Ref, EvfImageRef); if (err == EDSDKLib.EDSDK.EDS_ERR_OBJECT_NOTREADY) { Thread.Sleep(4); continue; } else Error = err; /* lock (STAThread.ExecLock) { //download current live view image err = EDSDKLib.EDSDK.EdsCreateEvfImageRef(stream, out EvfImageRef); if (err == EDSDKLib.EDSDK.EDS_ERR_OK) err = EDSDKLib.EDSDK.EdsDownloadEvfImage(MainCamera.Ref, EvfImageRef); if (err == EDSDKLib.EDSDK.EDS_ERR_OBJECT_NOTREADY) { Thread.Sleep(4); continue; } else Error = err; } */ //get pointer Error = EDSDKLib.EDSDK.EdsGetPointer(stream, out jpgPointer); Error = EDSDKLib.EDSDK.EdsGetLength(stream, out length); //get some live view image metadata if (!IsCoordSystemSet) { Evf_CoordinateSystem = GetEvfCoord(EvfImageRef); IsCoordSystemSet = true; } Evf_ZoomRect = GetEvfZoomRect(EvfImageRef); Evf_ZoomPosition = GetEvfPoints(EDSDKLib.EDSDK.PropID_Evf_ZoomPosition, EvfImageRef); Evf_ImagePosition = GetEvfPoints(EDSDKLib.EDSDK.PropID_Evf_ImagePosition, EvfImageRef); //release current evf image if (EvfImageRef != IntPtr.Zero) { Error = EDSDKLib.EDSDK.EdsRelease(EvfImageRef); } //create stream to image unsafe { ums = new UnmanagedMemoryStream((byte*)jpgPointer.ToPointer(), (long)length, (long)length, FileAccess.Read); } //把unmanageedMemoryStream类型的ums转成Bitmap TextureBitmap = new Bitmap(ums, true); ms = new MemoryStream(); //用System.Drawing.Bitmap的方法将Bitmap转成MemoryStream TextureBitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); //将MemoryStream转成Bytes TextureBytes = ms.GetBuffer(); //fire the LiveViewUpdated event with the live view image stream if (LiveViewUpdated != null) LiveViewUpdated(ums); ums.Close(); }主要注意这一段: 在这个基础上可以实现拍照,照片会产生在StreamingAssets文件夹下,可以开启实时录像视频流,但是视频流观察下来有0.5秒-1秒的延迟。对于互动应用,如果需要实时画面让用户看到效果,不会影响需求实现,但是如果对实时性要求比较高,这个延迟是不行的,市面上我见过直接使用micro usb接口实现的单反拍照应用不延迟,我目前想应该不是通过unity实现的,还有一点,由于用到了STAThread脚本去管理一个线程,这个线程会在打开实时录像时使用,一旦使用,在exe状态下,关闭应用程序会导致卡死,后续我也会继续去研究怎么改进。 其他方案 视频采集卡单反有mini hdmi接口 我们可以用mini hdmi 转hdmi线,连接单反与采集卡 视频采集卡,无理是pcie内置采集卡,还是外置采集卡都可以 如果是PCIE的内置采集卡,Unity可以通过WebCamDevice去获取到这个“摄像”设备 如果是外置采集卡,则用采集卡另一端的USB3.0接口与主机连接,同样,Unity也是通过WebCamDevice去获取。 这样的技术方案,没有延迟。 缺点是连接了mini hdmi 档位需要在摄像档位,此时连接micro usb无法通过程序进行控制。 这个需求从当初研究到现在已经很长时间,如果有些地方写的不对或者不够好,欢迎您的指正。 工程源码参考:Unity控制佳能单反工程 |
CopyRight 2018-2019 实验室设备网 版权所有 |