欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 双相机结合halcon的条码检测

双相机结合halcon的条码检测

2025/4/19 0:07:09 来源:https://blog.csdn.net/dsafefvf/article/details/147097192  浏览:    关键词:双相机结合halcon的条码检测

以下是针对提供的C#代码的详细注释和解释,结合Halcon库的功能和代码结构进行说明:

---

### **代码整体结构**
该代码是一个基于Halcon库的条码扫描类`GeneralBarcodeScan`,支持单台或双台相机的条码检测,并通过回调接口返回结果。主要功能包括:
1. 相机初始化与图像采集。
2. 条码检测模型配置(静区、容错等)。
3. 单/双相机图像处理与条码识别。
4. 资源管理(释放相机、图像对象等)。

---

### **关键代码注释**

#### **1. 类定义与成员变量**
```csharp
public class GeneralBarcodeScan : IDisposable
{
    private string mLastErrorMsg;  // 存储最后的错误信息
    private ICcdCallback mCallback;  // 相机回调接口,用于处理扫描到的条码数据
    private HTuple mHvAcqHandle;    // 第一台相机的句柄
    private HTuple mHvAcqHandle2;   // 第二台相机的句柄
    private HObject mHoImage;       // 存储第一台相机捕获的图像
    private HObject mHoImage2;      // 存储第二台相机捕获的图像
    // ... 其他窗口相关变量 ...
}
```
- **功能**:定义类的成员变量,包括相机句柄、图像对象、错误信息和回调接口。
- **关键点**:`HTuple`是Halcon中常用的参数传递类型,`HObject`用于存储图像数据。

---

#### **2. 构造函数与资源初始化**
```csharp
public GeneralBarcodeScan()
{
    mHvAcqHandle = new HTuple();    // 初始化相机句柄
    mHvAcqHandle2 = new HTuple();
    HOperatorSet.GenEmptyObj(out mHoImage);  // 创建空图像对象
    HOperatorSet.GenEmptyObj(out mHoImage2);
    // 设置系统默认图像大小为512x512
    HOperatorSet.SetSystem("width", 512);
    HOperatorSet.SetSystem("height", 512);
    // 初始化第二个窗口的尺寸为0
    mWndWidth2 = 0;
    mWndHeight2 = 0;
}
```
- **功能**:初始化类成员变量,并设置Halcon的默认图像尺寸。
- **关键函数**:
  - `GenEmptyObj`:创建空的`HObject`对象。
  - `SetSystem`:设置Halcon系统参数(如默认图像尺寸)。

---

#### **3. 相机打开与初始化方法**
```csharp
public bool OpenImageAcq(HWindow hHalconWnd, int wndWidth, int wndHeight, int deviceQty)
{
    this.mHPreviewWnd = hHalconWnd;  // 设置显示窗口
    this.mWndWidth = wndWidth;
    this.mWndHeight = wndHeight;
    // ... 省略部分代码 ...
    // 获取相机设备信息
    HOperatorSet.InfoFramegrabber("GigEVision2", "device", out hvDeviceInfo, out hvDeviceInfoValues);
    if (hvDeviceInfoValues.Length == 0)  // 检查设备是否存在
    {
        this.mLastErrorMsg = "获取不到相机设备";
        return false;
    }
    // 打开第一台相机
    HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",
        -1, "default", -1, "false", "default", hvDeviceInfoValues.TupleSelect(0), 0, -1, out mHvAcqHandle);
    // 设置相机超时参数
    HOperatorSet.SetFramegrabberParam(mHvAcqHandle, "grab_timeout", 2000);
    HOperatorSet.GrabImageStart(mHvAcqHandle, -1);  // 开始异步图像采集
    // ... 双相机处理逻辑 ...
    return true;
}
```
- **功能**:打开相机并初始化参数,支持单/双相机配置。
- **关键函数**:
  - `OpenFramegrabber`:通过GigE Vision协议连接相机。
  - `GrabImageStart`:开始异步图像采集(`-1`表示连续采集)。
- **参数说明**:
  - `"GigEVision2"`:指定相机协议类型。
  - `hvDeviceInfoValues.TupleSelect(0)`:选择第一个检测到的相机设备。

---

#### **4. 相机关闭与资源释放**
```csharp
public void CloseImageAcq()
{
    if (this.mHoImage != null)
    {
        this.mHoImage.Dispose();  // 释放图像对象
        this.mHoImage = null;
    }
    if (this.mHvAcqHandle != null)
    {
        HOperatorSet.CloseFramegrabber(this.mHvAcqHandle);  // 关闭相机
        this.mHvAcqHandle.Dispose();
        this.mHvAcqHandle = null;
    }
    // ... 处理第二个相机和窗口 ...
}
```
- **功能**:释放相机句柄、图像对象和窗口资源。
- **关键函数**:
  - `CloseFramegrabber`:关闭相机连接。
  - `Dispose`:释放Halcon对象资源。

---

#### **5. 条码扫描核心逻辑(单相机)**
```csharp
public void StartScanBarcode(int qty)
{
    List<string> barcodeList = new List<string>();
    HObject hoImage;  // 当前捕获的图像
    HTuple hvBarCodeHandle;  // 条码检测模型句柄
    // ... 省略部分代码 ...
    // 创建条码检测模型并配置参数
    HOperatorSet.CreateBarCodeModel(new HTuple("quiet_zone"), new HTuple("true"), out hvBarCodeHandle);
    HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "majority_voting", "true");  // 启用多数表决
    HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "element_size_variable", "true");  // 允许模块尺寸变化
    // 捕获图像并检测条码
    HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);  // 异步获取图像
    HOperatorSet.FindBarCode(hoImage, out hoSymbolRegions, hvBarCodeHandle, "Code 128", out hvDecodedDataStrings);
    // 处理检测结果
    for (int i = 0; i < hvDecodedDataStrings.Length; i++)
    {
        barcodeList.Add(hvDecodedDataStrings[i]);  // 存储解码后的条码数据
    }
    // 释放资源并触发回调
    if (mCallback != null) mCallback.FoundBarcode(barcodeList);  // 通知回调函数
}
```
- **功能**:捕获图像并检测Code 128条码,通过回调返回结果。
- **关键步骤**:
  1. **创建检测模型**:`CreateBarCodeModel`配置静区检测。
  2. **设置参数**:启用多数表决(减少误检)、允许模块尺寸变化(适应变形条码)。
  3. **图像采集**:`GrabImageAsync`异步获取单张图像。
  4. **条码检测**:`FindBarCode`返回解码结果。
- **参数解释**:
  - `quiet_zone`:检测条码周围的空白区域,提升稳定性。
  - `majority_voting`:通过多条扫描线投票选择最终解码结果。

---

#### **6. 双相机拼接与检测**
```csharp
public void StartScanBarcodeBy2Device(bool reverse)
{
    HObject hoImage, hoImage2, hoImages;  // 两台相机的图像
    // ... 省略部分代码 ...
    // 捕获并拼接图像
    HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);
    HOperatorSet.GrabImageAsync(out hoImage2, mHvAcqHandle2, -1);
    if (reverse)  // 根据参数决定拼接顺序
    {
        HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);
        HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);
    }
    else
    {
        HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);
        HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);
    }
    HOperatorSet.TileImages(hoImages, out hoObjectsConcat, 2, "horizontal");  // 水平拼接
    // 执行检测(后续步骤与单相机相同)
}
```
- **功能**:同时捕获双相机图像并拼接,再进行条码检测。
- **关键函数**:
  - `ConcatObj`:合并图像对象。
  - `TileImages`:将图像拼接成单个图像(`horizontal`表示水平方向)。
- **参数`reverse`**:控制图像拼接的顺序(是否反转双相机的顺序)。

---

#### **7. 窗口适配与显示**
```csharp
private HTuple[] GetDisplayRect(int wndWidth, int wndHeight, int imageWidth, int imageHeight)
{
    // 计算图像在窗口中的显示区域,保持比例
    double widthRatio = (double)imageWidth / wndWidth;
    double heightRatio = (double)imageHeight / wndHeight;
    HTuple row1, column1, row2, column2;
    if (widthRatio >= heightRatio)  // 宽度占优,以宽度比例缩放
    {
        row1 = -(wndHeight * widthRatio - imageHeight) / 2;
        column1 = 0;
        row2 = row1 + wndHeight * widthRatio;
        column2 = column1 + wndWidth * widthRatio;
    }
    else  // 高度占优,以高度比例缩放
    {
        row1 = 0;
        column1 = -(wndWidth * heightRatio - imageWidth) / 2;
        row2 = row1 + wndHeight * heightRatio;
        column2 = column1 + wndWidth * heightRatio;
    }
    return new HTuple[] { row1, column1, row2, column2 };
}
```
- **功能**:根据窗口尺寸计算图像显示区域,保持图像比例。
- **实现逻辑**:
  - 计算宽高比,选择占优方向进行缩放。
  - 调整显示区域的坐标,确保图像居中显示。

---

### **关键函数与参数说明**
#### **Halcon函数**
| 函数名 | 功能 | 参数示例 |
|--------|------|----------|
| `OpenFramegrabber` | 打开相机 | `"GigEVision2"`, 设备标识符 |
| `GrabImageAsync` | 异步抓取图像 | `out HObject`, 相机句柄 |
| `CreateBarCodeModel` | 创建条码检测模型 | `'quiet_zone'`, `'true'` |
| `FindBarCode` | 检测图像中的条码 | `'Code 128'` |
| `TileImages` | 拼接图像 | `'horizontal'` |

#### **参数解释**
| 参数名 | 作用 |
|--------|------|
| `quiet_zone` | 启用条码周围空白区域检测 |
| `majority_voting` | 启用多条扫描线投票机制 |
| `element_size_variable` | 允许条码模块尺寸变化(适应变形条码) |
| `start_stop_tolerance` | 设置起始符/终止符的容错级别 |

---

### **代码优势与注意事项**
#### **优势**
1. **资源管理**:通过`IDisposable`接口确保相机和图像对象的正确释放。
2. **双相机支持**:可扩展至多相机协同检测,提升检测范围。
3. **条码检测优化**:通过静区和容错参数提升鲁棒性。

#### **注意事项**
1. **相机配置**:
   - 需确保相机型号与`GigEVision2`协议兼容。
   - 网络配置(如IP地址)需提前设置。
2. **资源泄漏风险**:
   - 必须在`using`块或`Dispose()`中调用`CloseImageAcq()`。
3. **性能优化**:
   - 双相机拼接可能增加处理时间,需根据场景调整。

---

### **典型使用流程**
```csharp
// 1. 初始化类并设置回调
var scanner = new GeneralBarcodeScan();
scanner.setCallback(new MyCcdCallback());

// 2. 打开相机(假设单相机)
scanner.OpenImageAcq(window, 1280, 720, 1);

// 3. 开始检测
scanner.StartScanBarcode(1);

// 4. 关闭资源
scanner.Dispose();
```

通过以上注释和解释,开发者可以清晰理解代码功能、参数含义及实现逻辑。

using HalconDotNet;  // 引用 Halcon 图像处理库
using Hggit.Hwodc.Common;  // 引用其他库
using System;  // 引用系统库
using System.Collections.Generic;  // 引用集合类库
using System.Linq;  // 引用 LINQ 查询库
using System.Text;  // 引用字符串处理类库
using System.Threading.Tasks;  // 引用异步任务处理库namespace Hggit.Hwodc.Halcon
{public class GeneralBarcodeScan : IDisposable{private string mLastErrorMsg;  // 保存最后的错误信息private ICcdCallback mCallback;  // 相机回调接口,用于处理扫描到的条形码/// <summary>/// 相机句柄,用于相机图像捕获/// </summary>private HTuple mHvAcqHandle;/// <summary>/// 第二个相机句柄/// </summary>private HTuple mHvAcqHandle2;/// <summary>/// 捕获的图像对象/// </summary>private HObject mHoImage;/// <summary>/// 第二个捕获的图像对象/// </summary>private HObject mHoImage2;/// <summary>/// 窗口的宽度/// </summary>private int mWndWidth;/// <summary>/// 窗口的高度/// </summary>private int mWndHeight;/// <summary>/// Halcon 图像显示窗口/// </summary>private HWindow mHPreviewWnd;/// <summary>/// Halcon 图像显示窗口内部句柄/// </summary>HTuple mHvWindowHandle;/// <summary>/// 第二个窗口宽度/// </summary>private int mWndWidth2;/// <summary>/// 第二个窗口高度/// </summary>private int mWndHeight2;/// <summary>/// 第二个窗口的句柄/// </summary>HTuple mHvWindowHandle2;public void Dispose(){// 清理资源,关闭相机及图像对象CloseImageAcq();}public GeneralBarcodeScan(){// 初始化相机句柄和图像对象mHvAcqHandle = new HTuple();mHvAcqHandle2 = new HTuple();HOperatorSet.GenEmptyObj(out mHoImage);HOperatorSet.GenEmptyObj(out mHoImage2);// 设置系统默认图像大小HOperatorSet.SetSystem("width", 512);HOperatorSet.SetSystem("height", 512);mWndWidth2 = 0;mWndHeight2 = 0;}public void setCallback(ICcdCallback callback){// 设置回调接口this.mCallback = callback;}/// <summary>/// 打开相机并初始化图像采集/// </summary>/// <returns>返回是否成功打开相机</returns>public bool OpenImageAcq(HWindow hHalconWnd, int wndWidth, int wndHeight, int deviceQty){this.mHPreviewWnd = hHalconWnd;this.mWndWidth = wndWidth;this.mWndHeight = wndHeight;// 检查操作系统是否为 Windows,设置线程安全if (HalconAPI.isWindows)HOperatorSet.SetSystem("use_window_thread", "true");HTuple hvDeviceInfo;HTuple hvDeviceInfoValues;// 获取相机设备信息HOperatorSet.InfoFramegrabber("GigEVision2", "device", out hvDeviceInfo, out hvDeviceInfoValues);// 如果没有设备信息,返回错误if (hvDeviceInfoValues.Length == 0){this.mLastErrorMsg = "获取不到相机设备";return false;}// 检查是否有两个相机设备if (deviceQty == 2){if (hvDeviceInfoValues.Length < 2){this.mLastErrorMsg = "只检测到了一个相机设备!";return false;}}// 打开第一个相机HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",-1, "default", -1, "false", "default", hvDeviceInfoValues.TupleSelect(0), 0, -1, out mHvAcqHandle);// 设置相机参数HOperatorSet.SetFramegrabberParam(mHvAcqHandle, "grab_timeout", 2000);HOperatorSet.GrabImageStart(mHvAcqHandle, -1);// 打开第二个相机(如果有)if (deviceQty == 2){HOperatorSet.OpenFramegrabber("GigEVision2", 0, 0, 0, 0, 0, 0, "progressive",-1, "default", -1, "false", "default", hvDeviceInfoValues.TupleSelect(1), 0, -1, out mHvAcqHandle2);HOperatorSet.SetFramegrabberParam(mHvAcqHandle2, "grab_timeout", 2000);HOperatorSet.GrabImageStart(mHvAcqHandle2, -1);}// 关闭之前打开的窗口if (HDevWindowStack.IsOpen()){var hvWnd = HDevWindowStack.Pop();while (hvWnd != null){HOperatorSet.CloseWindow(hvWnd);}}// 打开显示窗口并设置窗口句柄HOperatorSet.OpenWindow(0, 0, wndWidth, wndHeight, hHalconWnd, "visible", "", out this.mHvWindowHandle);HDevWindowStack.Push(mHvWindowHandle);return true;}public void CloseImageAcq(){// 清理相机和图像资源if (HalconAPI.isWindows)HOperatorSet.SetSystem("use_window_thread", "true");if (this.mHoImage != null){this.mHoImage.Dispose();this.mHoImage = null;}if (this.mHvWindowHandle != null){this.mHvWindowHandle.Dispose();this.mHvWindowHandle = null;}if (this.mHvAcqHandle != null){HOperatorSet.CloseFramegrabber(this.mHvAcqHandle);this.mHvAcqHandle.Dispose();this.mHvAcqHandle = null;}if (mHoImage2 != null){this.mHoImage2.Dispose();this.mHoImage2 = null;}if (this.mHvWindowHandle2 != null){this.mHvWindowHandle2.Dispose();this.mHvWindowHandle2 = null;}if (this.mHvAcqHandle2 != null){HOperatorSet.CloseFramegrabber(this.mHvAcqHandle2);this.mHvAcqHandle2.Dispose();this.mHvAcqHandle2 = null;}}public string GetLastErrorMsg(){// 获取最后的错误信息return this.mLastErrorMsg;}public void GrabImage(){// 异步捕获图像并显示在窗口HObject hoImage;HTuple imageWidth;HTuple imageHeight;if (HalconAPI.isWindows)HOperatorSet.SetSystem("use_window_thread", "true");HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);HOperatorSet.GetImageSize(hoImage, out imageWidth, out imageHeight);if (HDevWindowStack.IsOpen()){HTuple[] displayRect = GetDisplayRect(mWndWidth, mWndHeight, imageWidth, imageHeight);HOperatorSet.SetPart(HDevWindowStack.GetActive(), displayRect[0], displayRect[1], displayRect[2], displayRect[3]);}if (HDevWindowStack.IsOpen()){HOperatorSet.DispImage(hoImage, HDevWindowStack.GetActive());}if (hoImage != null){hoImage.Dispose();}if (imageWidth != null){imageWidth.Dispose();}if (imageHeight != null){imageHeight.Dispose();}}public void StartScanBarcode(int qty){// 执行条形码扫描List<string> barcodeList = new List<string>();HObject hoImage;HObject hoObjectsConcat;HObject hoSymbolRegions;HTuple hvBarCodeHandle;HTuple imageWidth;HTuple imageHeight;HTuple hvWindowHandle;int wndWidth, wndHeight;if (qty == 1){// 如果是单台相机,使用第一个相机窗口和尺寸wndWidth = this.mWndWidth;wndHeight = this.mWndHeight;hvWindowHandle = this.mHvWindowHandle;}else{// 如果是双台相机,使用第二个相机窗口和尺寸wndWidth = this.mWndWidth2;wndHeight = this.mWndHeight2;hvWindowHandle = this.mHvWindowHandle2;}HTuple hvDecodedDataStrings;// 创建空对象,用于存放图像和检测到的条形码区域HOperatorSet.GenEmptyObj(out hoObjectsConcat);HOperatorSet.GenEmptyObj(out hoSymbolRegions);// 创建条形码检测模型,指定条形码检测的类型HOperatorSet.CreateBarCodeModel("quiet_zone", "true", out hvBarCodeHandle);// 设置条形码检测的参数HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "majority_voting", "true");  // 启用多数投票HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "element_size_variable", "true");  // 启用可变元素大小HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "start_stop_tolerance", "low");  // 设置开始/停止容差为低// 根据相机数量,选择相应的相机进行图像捕获if (qty == 1){// 如果只有一台相机,捕获图像HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);}else{// 如果有两台相机,捕获两台相机的图像HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);}// 获取图像的尺寸HOperatorSet.GetImageSize(hoImage, out imageWidth, out imageHeight);// 根据窗口尺寸和图像尺寸,计算显示区域if (HDevWindowStack.IsOpen()){HTuple[] displayRect = GetDisplayRect(wndWidth, wndHeight, imageWidth, imageHeight);HOperatorSet.SetPart(hvWindowHandle, displayRect[0], displayRect[1], displayRect[2], displayRect[3]);}// 显示捕获的图像if (HDevWindowStack.IsOpen()){HOperatorSet.DispImage(hoImage, hvWindowHandle);}// 执行条形码查找HOperatorSet.FindBarCode(hoImage, out hoSymbolRegions, hvBarCodeHandle,"Code 128", out hvDecodedDataStrings);// 显示条形码区域if (HDevWindowStack.IsOpen()){HOperatorSet.DispRegion(hoSymbolRegions, hvWindowHandle);}// 将找到的条形码数据加入列表for (int i = 0; i < hvDecodedDataStrings.Length; i++){string item = hvDecodedDataStrings[i];barcodeList.Add(string.Copy(item));}// 释放资源if (hoObjectsConcat != null){hoObjectsConcat.Dispose();}if (hoSymbolRegions != null){hoSymbolRegions.Dispose();}if (hvBarCodeHandle != null){hvBarCodeHandle.Dispose();}if (hoImage != null){hoImage.Dispose();}if (imageWidth != null){imageWidth.Dispose();}if (imageHeight != null){imageHeight.Dispose();}if (hvDecodedDataStrings != null){hvDecodedDataStrings.Dispose();}// 调用回调函数,将条形码数据返回if (mCallback != null){mCallback.FoundBarcode(barcodeList);}}public void StartScanBarcodeBy2Device(bool revease){// 使用两台相机进行条形码扫描List<string> barcodeList = new List<string>();HObject hoImage;HObject hoImage2;HObject hoImages;HObject hoObjectsConcat;HObject hoSymbolRegions;HTuple hvBarCodeHandle;HTuple imageWidth;HTuple imageHeight;HTuple hvWindowHandle;int wndWidth, wndHeight;// 设置第一个相机的窗口尺寸wndWidth = this.mWndWidth;wndHeight = this.mWndHeight;hvWindowHandle = this.mHvWindowHandle;HTuple hvDecodedDataStrings;// 创建空对象,用于存放图像和检测到的条形码区域HOperatorSet.GenEmptyObj(out hoImage);HOperatorSet.GenEmptyObj(out hoImage2);HOperatorSet.GenEmptyObj(out hoImages);HOperatorSet.GenEmptyObj(out hoObjectsConcat);HOperatorSet.GenEmptyObj(out hoSymbolRegions);// 创建条形码检测模型HOperatorSet.CreateBarCodeModel("quiet_zone", "true", out hvBarCodeHandle);// 设置条形码检测的参数HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "majority_voting", "true");HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "element_size_variable", "true");HOperatorSet.SetBarCodeParam(hvBarCodeHandle, "start_stop_tolerance", "low");// 捕获第一台相机的图像HOperatorSet.GrabImageAsync(out hoImage, mHvAcqHandle, -1);// 捕获第二台相机的图像HOperatorSet.GrabImageAsync(out hoImage2, mHvAcqHandle2, -1);// 根据 `revease` 参数的值,决定图像的拼接顺序if (revease){HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);}else{HOperatorSet.ConcatObj(hoImages, hoImage, out hoImages);HOperatorSet.ConcatObj(hoImages, hoImage2, out hoImages);}// 将两台相机的图像拼接在一起HOperatorSet.TileImages(hoImages, out hoObjectsConcat, 2, "horizontal");// 获取拼接后的图像尺寸HOperatorSet.GetImageSize(hoObjectsConcat, out imageWidth, out imageHeight);// 根据窗口尺寸和图像尺寸,计算显示区域if (HDevWindowStack.IsOpen()){HTuple[] displayRect = GetDisplayRect(wndWidth, wndHeight, imageWidth, imageHeight);HOperatorSet.SetPart(hvWindowHandle, displayRect[0], displayRect[1], displayRect[2], displayRect[3]);}// 显示拼接后的图像if (HDevWindowStack.IsOpen()){HOperatorSet.DispImage(hoObjectsConcat, hvWindowHandle);}// 执行条形码查找HOperatorSet.FindBarCode(hoObjectsConcat, out hoSymbolRegions, hvBarCodeHandle,"Code 128", out hvDecodedDataStrings);// 显示条形码区域if (HDevWindowStack.IsOpen()){HOperatorSet.DispRegion(hoSymbolRegions, hvWindowHandle);}// 将找到的条形码数据加入列表for (int i = 0; i < hvDecodedDataStrings.Length; i++){string item = hvDecodedDataStrings[i];barcodeList.Add(string.Copy(item));}// 释放资源if (hoObjectsConcat != null){hoObjectsConcat.Dispose();}if (hoImages != null){hoImages.Dispose();}if (hoSymbolRegions != null){hoSymbolRegions.Dispose();}if (hvBarCodeHandle != null){hvBarCodeHandle.Dispose();}if (hoImage != null){hoImage.Dispose();}if (hoImage2 != null){hoImage2.Dispose();}if (imageWidth != null){imageWidth.Dispose();}if (imageHeight != null){imageHeight.Dispose();}if (hvDecodedDataStrings != null){hvDecodedDataStrings.Dispose();}// 调用回调函数,将条形码数据返回if (mCallback != null){mCallback.FoundBarcode(barcodeList);}}/// <summary>/// 计算显示区域的矩形,以适应图像与窗口的大小比例/// </summary>/// <param name="wndWidth">窗口宽度</param>/// <param name="wndHeight">窗口高度</param>/// <param name="imageWidth">图像宽度</param>/// <param/// <summary>/// 计算显示区域的矩形,以适应图像与窗口的大小比例/// </summary>/// <param name="wndWidth">窗口宽度</param>/// <param name="wndHeight">窗口高度</param>/// <param name="imageWidth">图像宽度</param>/// <param name="imageHeight">图像高度</param>/// <returns>显示区域矩形</returns>private HTuple[] GetDisplayRect(int wndWidth, int wndHeight, int imageWidth, int imageHeight){// 计算图像与窗口的宽高比例double widthRatio = (1.0) * imageWidth / wndWidth;double heightRatio = (1.0) * imageHeight / wndHeight;HTuple row1, colume1, row2, colume2;// 如果图像的宽度比高度占优,则以宽度比例为主if (widthRatio >= heightRatio){row1 = -(1.0) * (wndHeight * widthRatio - imageHeight) / 2;colume1 = 0;row2 = row1 + wndHeight * widthRatio;colume2 = colume1 + wndWidth * widthRatio;}else{// 否则,以高度比例为主row1 = 0;colume1 = -(1.0) * (wndWidth * heightRatio - imageWidth) / 2;row2 = row1 + wndHeight * heightRatio;colume2 = colume1 + wndWidth * heightRatio;}// 返回显示区域的四个坐标点(行列)return new HTuple[] { row1, colume1, row2, colume2 };}}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词