目录
一联合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();
}
#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显示图像。