【C#】运行mindvision工业相机

1 运行demo

假设我们手上有了一款相机,可以按照如下流程进行测试

1.1 安装相机驱动

登录
http://www.mindvision.com.cn/
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

正常安装即可,安装完了以后可以在目录中看到如下文件
在这里插入图片描述

1.2 使用VS2010打开demo

在这里插入图片描述

在这里插入图片描述
注意,如果这里报错,提示没有C#环境,建议你新建一个工程,到联网模板里去找,选择C#应用程序,VS2010会自动下载相关的模板
在这里插入图片描述
回到我们的工程,设置FirstStep为启动项目
在这里插入图片描述
运行即可

在这里插入图片描述
效果:
在这里插入图片描述

2 学习代码

然后我们可以新建一个工程,模仿这个demo去实现上面这个功能,实现对C#的学习

2.1 新建项目

在这里插入图片描述
选择C#窗体程序,如果你没有C#环境,可以选择左下角的联机模板,创建C#,会自动下载。
在这里插入图片描述
确定即可。

2.2 添加引用(相机SDK)

在项目“引用”上右键
在这里插入图片描述
找到迈德威视工业相机的驱动安装位置
在这里插入图片描述

进入相机驱动的安装目录

在这里插入图片描述
选择dll
在这里插入图片描述
确定即可。
在这里插入图片描述

(这里直接引用他们的demo里的dll,其实也可以自己写一个项目,模仿MDSDK项目,然后项目属性的输出类似改为类库,再引用即可。建议熟悉后再尝试,现在继续往下看)

2.3 添加四个按钮

右键cs文件
在这里插入图片描述
可以看到下面的InitializeComponent函数,这个函数里面设定了控件(如按钮,文字等)的属性,包括名称、位置、尺寸等等,还有相关的调用方案,一般是自动生成,不用我们修改。
在这里插入图片描述

先添加四个按钮,点击设计界面,如果你没有这个标签页,双击cs文件能打开这个标签。
在这里插入图片描述
我们打开工具箱,从中拖几个按钮过去
在这里插入图片描述
找到公共控件的Button
在这里插入图片描述
拖过去即可,然后再移动鼠标到右下角,把我们的窗口拖到合适大小
在这里插入图片描述
再添加4个按钮,如图:
在这里插入图片描述

2.4 按钮事件

双击某一个按钮,进入代码界面
在这里插入图片描述
可以看到自动生成的点击事件函数:
在这里插入图片描述
复制如下内容到这个函数里

if (m_Grabber != IntPtr.Zero)
    MvApi.CameraShowSettingPage(m_hCamera, 1);

CameraShowSettingPage是进入相机设置界面。这里表示当相机指针不为Zero,进入设置界面。m_Grabber 在相机初始化时会被赋值。

可以看到有标红,
在这里插入图片描述

有一些变量和类需要先初始化,在顶部添加如下代码:
在这里插入图片描述

using MVSDK;
using CameraHandle = System.Int32;
protected IntPtr m_Grabber = IntPtr.Zero;		
protected CameraHandle m_hCamera = 0;

IntPtr:表示指针或句柄的平台特定整数类型,这里你可以认为是定义了一个整数类型的相机句柄,后面会用这个m_Grabber 来操作相机,如打开关闭相机等。

按钮1的点击事件完成,为了更容易识别,我们把按钮1设置为中文名称,右键按钮
在这里插入图片描述
将名称“button1”
在这里插入图片描述
改为“设置”
在这里插入图片描述
效果如下:
在这里插入图片描述

再改第二个名称
在这里插入图片描述
四个都改完后的效果
在这里插入图片描述
然后我们分别给各个按钮添加点击事件
双击第二个“播放”按钮,添加代码:
在这里插入图片描述
添加一个方法即可。

if (m_Grabber != IntPtr.Zero)
	MvApi.CameraGrabber_StartLive(m_Grabber);

表示启动相机。

再双击停止按钮,添加代码
在这里插入图片描述

if (m_Grabber != IntPtr.Zero)
    MvApi.CameraGrabber_StopLive(m_Grabber);

可以看到,由于迈德威视的相机SDK封装的比较完善,我们只需要一个方法就可以实现很多调用了。

但是最后一个抓图(截图)方法会比较复杂一些,因为涉及到一些关于文件保存的问题。双击抓图按钮,添加代码:
在这里插入图片描述
其实主要还是SaveImage和SaveAsBmp方法,然后将文件保存到指定路径中

if (m_Grabber != IntPtr.Zero)
{
    IntPtr Image;
    if (MvApi.CameraGrabber_SaveImage(m_Grabber, out Image, 2000) ==
        CameraSdkStatus.CAMERA_STATUS_SUCCESS)
    {
        string filename = System.IO.Path.Combine(
        AppDomain.CurrentDomain.BaseDirectory.ToString(), 
        string.Format("{0}.bmp", System.Environment.TickCount));

        MvApi.CameraImage_SaveAsBmp(Image, filename);

        MvApi.CameraImage_Destroy(Image);

        MessageBox.Show(filename);
    }
    else
    {
        MessageBox.Show("Snap failed");
    }
}

System.IO.Path.Combine:将路径与文件名合并起来,如C:\ABC.BMP
{0}:占位符,代表后面的第一个变量,类似于打印时的%d

四个按钮的事件写完了。

2.5 定时器控件

定时器控件用于底部状态栏数据的更新,这一块不是很重要,了解一下即可。
在这里插入图片描述
拖过去
在这里插入图片描述

双击上面那个闹钟,进入代码界面,写定时器事件

if (m_Grabber != IntPtr.Zero)
{
    tSdkGrabberStat stat;
    MvApi.CameraGrabber_GetStat(m_Grabber, out stat);
    
    string info = String.Format(
        "| Resolution:{0}*{1} | DispFPS:{2} | CapFPS:{3} |", 
        stat.Width, stat.Height, stat.DispFps, stat.CapFps);
        
    StateLabel.Text = info;
}

状态栏的信息用于获取相机采集到的画面的宽高和帧率等信息。
可以发现有一个地方标红了,
在这里插入图片描述
是标签控件,相当于状态栏的地方,说明标签没有添加,这时候我们可以把标签添加过去。

在这里插入图片描述

在这里插入图片描述
右击属性
在这里插入图片描述

将(Name)的值改为StateLabel
在这里插入图片描述

回来即可发现不再标红
在这里插入图片描述

2.6 相机的回调事件

相机的回调用于不断的刷新图像,我们在窗口设定了一个Image,然后不断的更新这个Image。

我们先在这里调用这个方法
在这里插入图片描述

protected pfnCameraGrabberFrameCallback m_FrameCallback;
m_FrameCallback = new pfnCameraGrabberFrameCallback(CameraGrabberFrameCallback);

然后我们再定义CameraGrabberFrameCallback

在这里插入图片描述
注意这里的第二个和第三个参数,pFrameBuffer是得到的帧缓存,在获取image时需要传入该参数;pFrameHead是图像帧头信息,用于获取图像格式。

private void CameraGrabberFrameCallback(
    IntPtr Grabber,
    IntPtr pFrameBuffer,
    ref tSdkFrameHead pFrameHead,
    IntPtr Context)
{

}

我们在函数体中添加如下代码:

GC.Collect();//强制进行即时垃圾回收,防止内存溢出

int w = pFrameHead.iWidth;
int h = pFrameHead.iHeight;

Boolean gray = (pFrameHead.uiMediaType ==
    (uint)MVSDK.emImageFormat.CAMERA_MEDIA_TYPE_MONO8);
    
Bitmap Image = new Bitmap(w, h,
    gray ? w : w * 3,
    gray ? PixelFormat.Format8bppIndexed : PixelFormat.Format24bppRgb,
    pFrameBuffer);

if (gray)
{
    Image.Palette = m_GrayPal;
}

this.Invoke((EventHandler)delegate
{
    DispWnd.Image = Image;
    DispWnd.Refresh();
});

在这里对image进行绘制,首先要判断相机的类型(彩色or黑白),然后进行Bitmap绘制,最后输出到DispWnd中。
可以看到有一些标红的地方,
在这里插入图片描述
首先pixel format是像素格式,它需要System.Drawing.Imaging的引用。
然后是m_GrayPal,该参数类型是定义组成调色板的颜色的数组,在初始化相机时会被赋值,当确定相机是黑白相机(gray为真)时,对image的图像调色板palette属性进行赋值。
我们添加System.Drawing.Imaging引用和m_GrayPal初始化即可。
在这里插入图片描述

using System.Drawing.Imaging;
protected ColorPalette m_GrayPal;

回来即可发现前两个不再标红
在这里插入图片描述

然后DispWnd,这个是一个PictureBox,顾名思义——图片盒子,就是用来显示我们图像的控件名称,我们回到设计窗口,将PictureBox拖过去。
在这里插入图片描述

在这里插入图片描述
然后右键这个控件,设置它的名称。
在这里插入图片描述

在这里插入图片描述
回到代码,即可发现不再标红。
在这里插入图片描述

2.7 相机的初始化

我们在窗口构造函数处添加相机的初始化代码
在这里插入图片描述
代码很好理解,创建相机的状态参数status,设备列表数组DevList,并获取已连接相机的数量,如果数组不为空则返回数组的长度,否则返回0。

private void InitCamera()
{
    CameraSdkStatus status = 0;

    tSdkCameraDevInfo[] DevList;
    MvApi.CameraEnumerateDevice(out DevList);
    int NumDev = (DevList != null ? DevList.Length : 0);
}

然后添加,获取相机设备的数量
在这里插入图片描述

if (NumDev < 1)
{
    MessageBox.Show("未扫描到相机”);
    return;
}
else if (NumDev == 1)
{
    status = MvApi.CameraGrabber_Create(out m_Grabber, ref DevList[0]);
}
else
{
    status = MvApi.CameraGrabber_CreateFromDevicePage(out m_Grabber);
}

判断当前的相机数量
在这里插入图片描述

if (status == 0)
{
    MvApi.CameraGrabber_GetCameraDevInfo(m_Grabber, out m_DevInfo);
    MvApi.CameraGrabber_GetCameraHandle(m_Grabber, out m_hCamera);
    MvApi.CameraCreateSettingPage(m_hCamera, this.Handle, m_DevInfo.acFriendlyName, null, (IntPtr)0, 0);

    MvApi.CameraGrabber_SetRGBCallback(m_Grabber, m_FrameCallback, IntPtr.Zero);
    tSdkCameraCapbility cap;
    MvApi.CameraGetCapability(m_hCamera, out cap);
    if (cap.sIspCapacity.bMonoSensor != 0)
    {
        MvApi.CameraSetIspOutFormat(m_hCamera, (uint)MVSDK.emImageFormat.CAMERA_MEDIA_TYPE_MONO8);
                     
        Bitmap Image = new Bitmap(1, 1, PixelFormat.Format8bppIndexed);
        m_GrayPal = Image.Palette;
        for (int Y = 0; Y < m_GrayPal.Entries.Length; Y++)
            m_GrayPal.Entries[Y] = Color.FromArgb(255, Y, Y, Y);
    }               
}

上图是有一个相机的时候执行的操作,其中标红的地方是因为m_DevInfo
没有定义,添加后即可
在这里插入图片描述

protected tSdkCameraDevInfo m_DevInfo;

不标红了
在这里插入图片描述

设置完成后我们需要添加启动的操作
在这里插入图片描述

MvApi.CameraSetMirror(m_hCamera, 1, 1);
MvApi.CameraGrabber_StartLive(m_Grabber);

如果if (status == 0)不通过,说明相机打开失败,我们需要进行提醒
在这里插入图片描述

else
{
    MessageBox.Show(String.Format("打开相机失败,原因:{0}", status));
}

相机的初始化也已经完成,最后一步是设置窗口的关闭事件,需要将相机的活动销毁

右键窗口空白处
在这里插入图片描述
在这里插入图片描述
双击右侧空白处,即可自动添加代码,然后写销毁事件即可
在这里插入图片描述
点击运行
在这里插入图片描述

在这里插入图片描述

运行后可以发现,图像不清晰,询问技术得知,是PictureBox缩放显示的问题
在这里插入图片描述
在这里插入图片描述

再次运行即可显示
在这里插入图片描述

  • 27
    点赞
  • 121
    收藏
    觉得还不错? 一键收藏
  • 21
    评论
在Ubuntu系统下使用Flir Blackfly S工业相机,可以按照以下步骤进行操作。首先,安装Spinnaker SDK相机驱动,并增加USB3.0的带宽限制。然后,进行硬件连接并修改相机ID号。最后,启动驱动并使用rviz查看图像。\[1\] 对于PointGrey相机,可以在Flir官网直接搜索型号并找到相应的驱动。此外,也可以在roswiki上找到安装方法。\[2\] 对于Mindvision相机,可以通过以下步骤进行安装:首先,使用sudo su命令获取管理员权限;然后,按照readme文件中的说明打开相机;最后,使用qt编译qt的demo并运行main即可。\[2\] 对于偏振相机SDK的安装,可以按照polar中的readme文件进行操作。安装完成后,关闭防火墙即可。然后,运行spinview来检查相机是否连接成功。\[2\] 如果在安装好相机驱动后,相机显示没有连接上,可以尝试以下步骤:首先,关闭防火墙(可以使用sudo ufw disable命令或sudo su ufw disable命令);然后,重启设备;最后,检查连接线是否正常。\[2\] 如果以上方法仍然无法解决问题,可以尝试保存并重启设备。如果仍然失败,可以使用以下命令进行检测:sudo sh -c 'echo 1000 > /sys/module/usbcore/parameters/usbfs_memory_mb'。\[3\] #### 引用[.reference_title] - *1* *3* [ubuntu20.04 ROS 环境下使用 Flir Blackfly S 工业相机](https://blog.csdn.net/qq_32761549/article/details/126488889)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [安装pointgray灰度相机mindvison,pointgray偏振相机的ubuntu驱动](https://blog.csdn.net/wenzhou_zhou/article/details/107013220)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值