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
英文地址,請注明出處:http://en.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 領域帶來巨大變革注意力機制以及使用…