c# 调用basler 相机

目录

一联合halcon:

[二 c# 原生](# 原生)

一联合halcon:

===============环境配置==================

下载安装pylon软件

下载安装halcon

创建 winform项目 test_basler

添加引用

打开pylon可以连接相机

可以看到我的相机id为23970642

=============================


c#联合halcon的基础教程(案例:亮度计算、角度计算和缺陷检测)(含halcon代码)_halcon.dll,halcondotnet.dll 下载-CSDN博客

c#添加几个控件(button、 textbox 和hwindowcontrol)

basler使用

allCameras = CameraFinder.Enumerate();//获取所有相机设备

camera = new Camera(id);//指定的序列号

camera.Open();//打开相机

使用

image.GenImage1("byte", grabResult.Width, grabResult.Height, p);

抓图。

完整代码如下:

cs 复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Basler.Pylon;
using HalconDotNet;


namespace test_basler
{
    public partial class Form1 : Form
    {

        List<ICameraInfo> allCameras = null;
        HImage image = null;
        Camera camera = null;

        public Form1()
        {
            InitializeComponent();


            string str_connectcamera = connectCamera("23970642");
            textBox1.AppendText(str_connectcamera + "\r\n");
        }

        public string connectCamera(string id)
        {
            allCameras = CameraFinder.Enumerate();//获取所有相机设备
            for (int i = 0; i < allCameras.Count; i++)
            {
                try
                {
                    textBox1.AppendText("已搜索相机:");
                    textBox1.AppendText(allCameras[i][CameraInfoKey.SerialNumber]+"\r\n");

                    if (allCameras[i][CameraInfoKey.SerialNumber] == id)
                    {
                        //如果当前相机信息中序列号是指定的序列号,则实例化相机类
                        camera = new Camera(allCameras[i]);
                        camera.Open();//打开相机
                        return "成功连接相机";
                    }
                    continue;
                }
                catch
                {
                    return "未找到";
                }
            }
            return "未找到";
        }


        private Boolean IsMonoData(IGrabResult iGrabResult)//判断图像是否为黑白格式
        {
            switch (iGrabResult.PixelTypeValue)
            {
                case PixelType.Mono1packed:
                case PixelType.Mono2packed:
                case PixelType.Mono4packed:
                case PixelType.Mono8:
                case PixelType.Mono8signed:
                case PixelType.Mono10:
                case PixelType.Mono10p:
                case PixelType.Mono10packed:
                case PixelType.Mono12:
                case PixelType.Mono12p:
                case PixelType.Mono12packed:
                case PixelType.Mono16:
                    return true;
                default:
                    return false;
            }
        }

        private void OneShot()
        {
            try
            {
                // 配置参数
                camera.Parameters[PLCamera.PixelFormat].TrySetValue(PLCamera.PixelFormat.Mono8);
                camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.SingleFrame);

                camera.StreamGrabber.Start();


                // 检索结果
                IGrabResult grabResult = camera.StreamGrabber.RetrieveResult(4000, TimeoutHandling.ThrowException);
                image = new HImage();
                using (grabResult)
                {
                    if (grabResult.GrabSucceeded)
                    {
                        if (IsMonoData(grabResult))
                        {
                            byte[] buffer = grabResult.PixelData as byte[];
                            IntPtr p = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
                            image.GenImage1("byte", grabResult.Width, grabResult.Height, p);
                        }
                        else
                        {
                            if (grabResult.PixelTypeValue != PixelType.RGB8packed)
                            {
                                byte[] buffer_rgb = new byte[grabResult.Width * grabResult.Height * 3];
                                Basler.Pylon.PixelDataConverter convert = new PixelDataConverter();
                                convert.OutputPixelFormat = PixelType.RGB8packed;
                                convert.Convert(buffer_rgb, grabResult);
                                IntPtr p = Marshal.UnsafeAddrOfPinnedArrayElement(buffer_rgb, 0);
                                image.GenImageInterleaved(p, "rgb", grabResult.Width, grabResult.Height, 0, "byte", grabResult.Width, grabResult.Height, 0, 0, -1, 0);
                            }
                        }

                    }
                    else
                    {
                        textBox1.AppendText("抓取图像失败: " + grabResult.ErrorDescription + "\r\n");
                    }
                }
            }
            catch (Exception ex)
            {
                textBox1.AppendText("拍照过程中发生错误: " + ex.Message + "\r\n");
            }
            finally
            {
                // 确保流抓取器停止
                if (camera != null && camera.StreamGrabber.IsGrabbing)
                {
                    camera.StreamGrabber.Stop();
                }
            }
        }


        private void show_img(HObject Image)
        {
            // 检查图像对象是否有效
            if (Image == null || !Image.IsInitialized())
            {
                MessageBox.Show("图像对象无效或未初始化");
                return;
            }

            // 获取窗口句柄
            HWindow hwnd = hWindowControl1.HalconWindow;

            // 清除窗口内容
            hwnd.ClearWindow();

            try
            {
                // 获取图片大小
                HTuple width, height;
                HOperatorSet.GetImageSize(Image, out width, out height);

                // 设置窗口显示部分为整个图像
                HOperatorSet.SetPart(hwnd, 0, 0, height - 1, width - 1);

                // 将图片投射到窗体上
                HOperatorSet.DispObj(Image, hwnd);
            }
            catch (HalconException ex)
            {
                MessageBox.Show($"处理图像时发生错误: {ex.Message}");
            }
        }


        private void button1_Click(object sender, EventArgs e)
        {
        


            OneShot();
            show_img(image);

        }








    }
}
cs 复制代码
namespace test_basler
{
    partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.hWindowControl1 = new HalconDotNet.HWindowControl();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(328, 721);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(312, 86);
            this.button1.TabIndex = 1;
            this.button1.Text = "拍照";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(981, 82);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(337, 538);
            this.textBox1.TabIndex = 2;
            // 
            // hWindowControl1
            // 
            this.hWindowControl1.BackColor = System.Drawing.Color.Black;
            this.hWindowControl1.BorderColor = System.Drawing.Color.Black;
            this.hWindowControl1.ImagePart = new System.Drawing.Rectangle(0, 0, 640, 480);
            this.hWindowControl1.Location = new System.Drawing.Point(123, 70);
            this.hWindowControl1.Name = "hWindowControl1";
            this.hWindowControl1.Size = new System.Drawing.Size(779, 611);
            this.hWindowControl1.TabIndex = 3;
            this.hWindowControl1.WindowSize = new System.Drawing.Size(779, 611);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1425, 915);
            this.Controls.Add(this.hWindowControl1);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.TextBox textBox1;
        private HalconDotNet.HWindowControl hWindowControl1;
    }
}

运行后:

二 c# 原生

用picturebox 来显示图像。

Basler Pylon SDK用于控制相机,提供相机发现、连接、参数设置和图像抓取的功能。

图像数据以字节数组形式获取,根据像素格式(如Mono8)处理为灰度图像。

Bitmap的创建需要正确设置调色板(灰度)和像素格式(Format8bppIndexed)。

锁定位图进行直接内存操作(LockBits),将数据从原始字节数组复制到位图的缓冲区,考虑步幅(每行字节数可能不等于宽度乘以每像素字节数,需要填充)。

代码如下:

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Basler.Pylon;



namespace test_basler
{
    public partial class Form1 : Form
    {

        List<ICameraInfo> allCameras = null;

        Camera camera = null;

        public Form1()
        {
            InitializeComponent();


            string str_connectcamera = connectCamera("23970642");
            textBox1.AppendText(str_connectcamera + "\r\n");
        }

        public string connectCamera(string id)
        {
            allCameras = CameraFinder.Enumerate();//获取所有相机设备
            for (int i = 0; i < allCameras.Count; i++)
            {
                try
                {
                    textBox1.AppendText("已搜索相机:");
                    textBox1.AppendText(allCameras[i][CameraInfoKey.SerialNumber]+"\r\n");

                    if (allCameras[i][CameraInfoKey.SerialNumber] == id)
                    {
                        //如果当前相机信息中序列号是指定的序列号,则实例化相机类
                        camera = new Camera(allCameras[i]);
                        camera.Open();//打开相机
                        return "成功连接相机";
                    }
                    continue;
                }
                catch
                {
                    return "未找到";
                }
            }
            return "未找到";
        }


        private Boolean IsMonoData(IGrabResult iGrabResult)//判断图像是否为黑白格式
        {
            switch (iGrabResult.PixelTypeValue)
            {
                case PixelType.Mono1packed:
                case PixelType.Mono2packed:
                case PixelType.Mono4packed:
                case PixelType.Mono8:
                case PixelType.Mono8signed:
                case PixelType.Mono10:
                case PixelType.Mono10p:
                case PixelType.Mono10packed:
                case PixelType.Mono12:
                case PixelType.Mono12p:
                case PixelType.Mono12packed:
                case PixelType.Mono16:
                    return true;
                default:
                    return false;
            }
        }



        public Bitmap OneShot()
        {
            try
            {
                // 配置参数
                camera.Parameters[PLCamera.PixelFormat].TrySetValue(PLCamera.PixelFormat.Mono8);
                camera.Parameters[PLCamera.AcquisitionMode].SetValue(PLCamera.AcquisitionMode.SingleFrame);
                camera.StreamGrabber.Start();

                // 抓取图像
                IGrabResult grabResult = camera.StreamGrabber.RetrieveResult(4000, TimeoutHandling.ThrowException);

                if (!grabResult.GrabSucceeded)
                    throw new Exception($"抓图失败: {grabResult.ErrorDescription}");

                // 直接处理原始字节数据
                byte[] pixelData = grabResult.PixelData as byte[];
                if (pixelData == null)
                    throw new InvalidOperationException("无像素数据");

                // 创建Bitmap(无需Halcon)
                return CreateBitmapFromPixelData(pixelData, grabResult.Width, grabResult.Height, grabResult.PixelTypeValue);
            }
            catch (Exception ex)
            {
                textBox1.AppendText($"拍照错误: {ex.Message}\r\n");
                return null;
            }
            finally
            {
                if (camera?.StreamGrabber.IsGrabbing == true)
                    camera.StreamGrabber.Stop();
            }
        }


        private void show_img()
        {
            
        }


        private Bitmap CreateBitmapFromPixelData(byte[] data, int width, int height, PixelType pixelType)
        {
            Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);

            // 设置灰度调色板
            ColorPalette palette = bmp.Palette;
            for (int i = 0; i < 256; i++)
                palette.Entries[i] = Color.FromArgb(i, i, i);
            bmp.Palette = palette;

            // 锁定位图进行直接内存操作
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),
                                              ImageLockMode.WriteOnly,
                                              bmp.PixelFormat);

            // 复制像素数据(支持多种像素格式)
            int stride = bmpData.Stride;
            int bufferSize = stride * height;
            byte[] buffer = new byte[bufferSize];

            // 填充空白区域(当实际数据宽度与Bitmap步幅不一致时)
            int bytesPerPixel = 1; // 灰度图
            int srcStride = width * bytesPerPixel;
            for (int y = 0; y < height; y++)
            {
                int srcOffset = y * srcStride;
                int dstOffset = y * stride;
                Buffer.BlockCopy(data, srcOffset, buffer, dstOffset, srcStride);
            }

            // 复制到Bitmap
            Marshal.Copy(buffer, 0, bmpData.Scan0, bufferSize);
            bmp.UnlockBits(bmpData);

            return bmp;
        }

        private void button1_Click(object sender, EventArgs e)
        {

            Bitmap image = OneShot();
            if (image != null)
            {
                // 使用PictureBox显示
                pictureBox1.Image = image;
                pictureBox1.SizeMode = PictureBoxSizeMode.Zoom; // 自动缩放
            }



        }








    }
}

流程:

初始化窗体时自动连接相机。

用户点击按钮时触发图像采集。

配置相机参数,启动采集,抓取图像。

处理图像数据,创建Bitmap,显示在UI上。

CameraFinder.Enumerate():枚举所有连接的相机。

Camera.Open():打开相机连接。

设置相机参数(如PixelFormat、AcquisitionMode)。

StreamGrabber.Start()和Stop():控制图像采集。

RetrieveResult:获取抓取结果。

CreateBitmapFromPixelData:将原始字节数据转换为Bitmap,处理步幅(stride)和像素格式。

使用PictureBox显示图像。

相关推荐
TomCode先生5 小时前
c#动态树形表达式详解
开发语言·c#
疾风铸境7 小时前
qt+halcon开发相机拍照软件步骤
数码相机·qt·halcon·拍照
上位机付工14 小时前
C#与倍福TwinCAT3进行ADS通信
开发语言·c#
土了个豆子的15 小时前
02.继承MonoBehaviour的单例模式基类
开发语言·visualstudio·单例模式·c#·里氏替换原则
疯狂的维修15 小时前
c#中public类比博图
c#·自动化
土了个豆子的18 小时前
03.缓存池
开发语言·前端·缓存·visualstudio·c#
xiaowu0801 天前
策略模式-不同的鸭子的案例
开发语言·c#·策略模式
VisionPowerful2 天前
九.弗洛伊德(Floyd)算法
算法·c#
ArabySide2 天前
【C#】 资源共享和实例管理:静态类,Lazy<T>单例模式,IOC容器Singleton我们该如何选
单例模式·c#·.net core