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);

抓图。

完整代码如下:

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);}}
}

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();}#endregionprivate 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);}// 复制到BitmapMarshal.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显示图像。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/95889.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/95889.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《2025年AI产业发展十大趋势报告》四十六

《2025年AI产业发展十大趋势报告》四十六随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;作为引领新一轮科技革命和产业变革的战略性技术&#xff0c;正逐步渗透到各个行业和领域&#xff0c;成为推动经济社会发展的重要引擎。2023年&#xff0c;生成式AI的…

c++ 杂记

1. 为什么返回*this?2. 3. 友元函数的使用&#xff1a;需要头文件中类内外声明&#xff0c;cpp文件中实现定义哦// Sales_data.h #ifndef SALES_DATA_H #define SALES_DATA_H#include <string>class Sales_data {std::string bookNo;int units_sold 0;double revenue …

PDF文件基础-计算机字体

计算机字体的原理包含了字符编码、字形渲染和字体文件存储三个关键技术。 字符编码负责将每个字符映射到一个唯一的数字码&#xff1b;字形渲染则将这些数字码转换成屏幕或纸张上可识别的图形&#xff1b;字体文件存储则包含了字符的编码、图形描述信息以及字体的其他属性&…

华为IP(9)

OSPF的基本配置OSPF路由计算前言&#xff1a;1)同一区域内的OSPF路由器拥有完全一致的LSDB&#xff0c;在区域内部&#xff0c;OSPF采用SPF算法完成路由计算。2&#xff09;随着网络规模不断扩大&#xff0c;路由器为了完成路由计算所消耗的内存、CPU资源也越来越多。通过区域划…

java.nio.file.InvalidPathException异常

一.问题概述 本人在ubuntu22.04的操作系统上&#xff0c;运行java程序时创建一个文件时&#xff0c;由于文件名称中包含了中文&#xff0c;所以导致了程序抛出了java.nio.file.InvalidPathException的异常。 java.nio.file.InvalidPathException: Malformed input or input co…

Next系统总结学习(一)

下面我按题号逐条 详细 解释并给出示例与最佳实践。为便于阅读&#xff0c;我会同时给出关键代码片段&#xff08;伪代码/实用例子&#xff09;&#xff0c;并指出常见坑与解决方案。 1. 你是如何理解服务端渲染&#xff08;SSR&#xff09;的&#xff1f;它的核心工作流程是怎…

房屋安全鉴定需要什么条件

房屋安全鉴定需要什么条件&#xff1a;专业流程与必备要素解析房屋安全鉴定是保障建筑使用安全的重要环节&#xff0c;它通过对建筑结构、材料性能及使用状况的全面评估&#xff0c;为房屋的安全使用、改造或维护提供科学依据。随着城市建筑老化及自然灾害频发&#xff0c;房屋…

现代C++:现代C++?

C语言正在走向完美&#xff0c;所以&#xff0c;C语言值得学习&#xff08;甚至研究&#xff09;&#xff0c;这些知识可以成为一切编程的基础。然而在实践中&#xff0c;不必全面的使用C语言的各种特性&#xff0c;而应根据工程项目的实际情况&#xff0c;适当取舍&#xff08…

【C++】哈希表实现

1. 哈希概念 哈希(hash)又称散列&#xff0c;是⼀种组织数据的方式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希 函数把关键字Key跟存储位置建立一个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进行快速查找 1.1 直接定址法…

ai 玩游戏 llm玩街霸 大模型玩街霸 (3)

1. 开源代码地址&#xff1a; https://github.com/OpenGenerativeAI/llm-colosseum 2. 架构&#xff1a; 3. 图片&#xff1a; 4. 感觉还是下面的步骤&#xff1a; a. 实时理解游戏当前环境&#xff0c;英雄角色&#xff0c;英雄状态 b. 根据当前状态感知&#xff0c;生成英雄…

2025年渗透测试面试题总结-59(题目+回答)

安全领域各种资源&#xff0c;学习文档&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具&#xff0c;欢迎关注。 目录 一、SQL注入全解 二、XSS与文件漏洞 三、服务端漏洞专题 四、职业经验与能力评估 1、注入攻击原理是什么…

GPT系列--类GPT2源码剖析

无需多言&#xff0c;大家应该都用过了&#xff0c;如今都更新到GPT-5了。1. GPT-1回到2018年的NLP&#xff0c;神仙打架&#xff0c;BERT与GPT不分先后。GPT是“Generative Pre-Training”的简称&#xff0c;生成式的预训练。BERT和GPT肯定是GPT难训练&#xff0c;引用量也是B…

这是一款没有任何限制的免费远程手机控制手机的软件

这是一款没有任何限制的免费远程手机控制手机的软件支持安卓和苹果1.安装1.1被控制端安装airdroid1.2控制端air mirror2.登录账号控制端和被控制端登录同一个账号3.控制打开控制端软件选择要控制的机器直接点“远程控制“

Observability:更智能的告警来了:更快的分诊、更清晰的分组和可操作的指导

作者&#xff1a;来自 Elastic Drew Post 探索 Elastic Stack 告警的最新增强功能&#xff0c;包括改进的相关告警分组、将仪表盘链接到告警规则&#xff0c;以及将调查指南嵌入到告警中。 在 9.1 版本中&#xff0c;我们对告警进行了重大升级&#xff0c;帮助 SRE 和运维人员更…

数智之光燃盛景 共同富裕创丰饶

8月29日&#xff0c;2025数博会“一带一路”国际大数据产业发展暨数智赋能新时代、共同富裕向未来的会议在贵阳国际生态会议中心隆重举行。作为全球大数据领域的重要盛会&#xff0c;此次活动吸引了来自联合国机构、国际组织、科研院所、知名企业等社会各界的百余位代表&#x…

【网络编程】recv函数的本质是什么?

一、为什么说recv函数的本质是 “copy”&#xff1f; recv是用于从网络连接&#xff08;或其他 IO 对象&#xff09;接收数据的函数&#xff0c;它的核心动作不是 “从网络上拉取数据”&#xff0c;而是 “把已经到达内核缓冲区的数据复制到用户程序的缓冲区”。 具体流程拆解&…

JSP程序设计之输入/输出对象 — out对象

目录1、out对象概述2.实例&#xff1a;out对象方法运用输入/输出对象&#xff0c;可以控制页面的输入和输出&#xff0c;用于访问与所有请求和响应有关的数据&#xff0c;包括out、request和response对象。 1、out对象概述 out对象是JspWriter类的一个实例&#xff0c;是一个…

UE里为什么要有提升变量

1、为了简洁当一个类里面的函数比较多&#xff0c;并且使用比较频繁的时候&#xff0c;就要不断的从这个类节点往外拉线&#xff0c;从而获取不同的函数节点&#xff0c;这样的蓝图就会看起来比较乱&#xff0c;这时候&#xff0c;就可以将这个常用的类提升为变量。2、为了存储…

玩转物联网只需十行代码,可它为何悄悄停止维护

文章目录玩转物联网只需十行代码&#xff0c;可它为何悄悄停止维护1 背景&#xff1a;MQTT 遇上 asyncio&#xff0c;为什么选 hbmqtt&#xff1f;2 hbmqtt 是什么&#xff1f;3 安装&#xff1a;一行命令&#xff0c;但别装最新4 五大核心 API&#xff1a;10 行代码跑通发布订…

从零开始学大模型之预训练语言模型

预训练语言模型 本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型开发 学习视频/籽料/面试题 都在这>>Github<< >>Gitee<< 3.1 Encoder-only PLM 在上一章&#xff0c;我们详细讲解了给 NLP 领域带来巨大变革注意力机制以及使用…