分类 文档 下的文章

使用方法:替换Toolblock的C#完整脚本,遍历输入项做为数据保存为.csv
Toolblock输入:必须包含两个String输入项:

  1. Path:保存文件的目录路径(如:"C:\Data")
  2. Filename:文件名前缀(如:"InspectionData")
#region namespace imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Cognex.VisionPro;
using Cognex.VisionPro.ToolBlock;
using Cognex.VisionPro3D;
using System.Text;
#endregion

public class CogToolBlockAdvancedScript : CogToolBlockAdvancedScriptBase
{
  #region Private Member Variables
  private Cognex.VisionPro.ToolBlock.CogToolBlock mToolBlock;
  #endregion

  /// <summary>
  /// Called when the parent tool is run.
  /// Add code here to customize or replace the normal run behavior.
  /// </summary>
  /// <param name="message">Sets the Message in the tool's RunStatus.</param>
  /// <param name="result">Sets the Result in the tool's RunStatus</param>
  /// <returns>True if the tool should run normally,
  ///          False if GroupRun customizes run behavior</returns>
  public override bool GroupRun(ref string message, ref CogToolResultConstants result)
  {
    // To let the execution stop in this script when a debugger is attached, uncomment the following lines.
//     #if DEBUG
//     if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();
//     #endif


    // Run each tool using the RunTool function
    foreach(ICogTool tool in mToolBlock.Tools)
      mToolBlock.RunTool(tool, ref message, ref result);
    
    SaveToolBlockData.SaveData(mToolBlock);

    return false;
  }

  #region When the Current Run Record is Created
  /// <summary>
  /// Called when the current record may have changed and is being reconstructed
  /// </summary>
  /// <param name="currentRecord">
  /// The new currentRecord is available to be initialized or customized.</param>
  public override void ModifyCurrentRunRecord(Cognex.VisionPro.ICogRecord currentRecord)
  {
  }
  #endregion

  #region When the Last Run Record is Created
  /// <summary>
  /// Called when the last run record may have changed and is being reconstructed
  /// </summary>
  /// <param name="lastRecord">
  /// The new last run record is available to be initialized or customized.</param>
  public override void ModifyLastRunRecord(Cognex.VisionPro.ICogRecord lastRecord)
  {
  }
  #endregion

  #region When the Script is Initialized
  /// <summary>
  /// Perform any initialization required by your script here
  /// </summary>
  /// <param name="host">The host tool</param>
  public override void Initialize(Cognex.VisionPro.ToolGroup.CogToolGroup host)
  {
    // DO NOT REMOVE - Call the base class implementation first - DO NOT REMOVE
    base.Initialize(host);


    // Store a local copy of the script host
    this.mToolBlock = ((Cognex.VisionPro.ToolBlock.CogToolBlock)(host));
  }
  #endregion

}

public class SaveToolBlockData
{
  public static void SaveData(CogToolBlock toolBlock)
  {
    try
    {
      // 1. 获取当前日期时间
      DateTime currentTime = DateTime.Now;
            
      // 2. 获取路径和文件名
      string savePath = Convert.ToString(toolBlock.Inputs["Path"].Value);
      string filenamePrefix = Convert.ToString(toolBlock.Inputs["Filename"].Value);
      string fileName = filenamePrefix + "_" + currentTime.ToString("yyyyMMdd") + ".csv";
      string fullPath = Path.Combine(savePath, fileName);

      // 3. 确保目录存在
      Directory.CreateDirectory(savePath);

      // 4. 准备表头和数据行
      StringBuilder csvLine = new StringBuilder();
      List<string> headers = new List<string> { "Time" };
      List<string> values = new List<string> { currentTime.ToString("HH:mm:ss:fff") };

      // 5. 遍历输入项
      foreach (CogToolBlockTerminal input in toolBlock.Inputs)
      {
        string name = input.Name;
                
        // 跳过路径和文件名参数
        if (name.Equals("Path", StringComparison.OrdinalIgnoreCase) || 
          name.Equals("Filename", StringComparison.OrdinalIgnoreCase))
          continue;

        headers.Add(name);
        values.Add(Convert.ToString(input.Value));
      }

      // 6. 创建或追加文件
      bool isNewFile = !File.Exists(fullPath);
            
      using (StreamWriter sw = new StreamWriter(fullPath, true, Encoding.UTF8))
      {
        // 7. 写入表头(新文件)
        if (isNewFile)
        {
          sw.WriteLine(string.Join(",", headers));
        }
                
        // 8. 写入数据行
        sw.WriteLine(string.Join(",", values));
      }
    }
    catch
    {
      // 错误处理(可选)
    }
  }
}

设物体当前坐标为 (X1, Y1, R1),模组当前坐标为 (X2, Y2, R2),物体目标坐标为 (X3, Y3, R3)。计算旋转差 ΔR = R3 - R1,则模组的新坐标 (X4, Y4, R4) 为:

X4 = X3 + cos(ΔR) (X2 - X1) - sin(ΔR) (Y2 - Y1)
Y4 = Y3 + sin(ΔR) (X2 - X1) + cos(ΔR) (Y2 - Y1)
R4 = R2 + ΔR

其中角度单位需一致(如弧度),必要时可将结果归一化到适当范围(如 [-π, π])。

一个简单的 C# 方法,适用于 .NET Framework 4.5。

using System;

public static class CompensationCalculator
{
    /// <summary>
    /// 根据四个顶点的XY补偿值,通过双线性插值计算指定位置的XY补偿值。
    /// 注意:此方法假设输入参数有效(n>2, m>2, i在0到n*m-1范围内)。
    /// </summary>
    public static Tuple<double, double> GetCompensation(
        int n, int m,
        double topLeftX, double topLeftY,
        double topRightX, double topRightY,
        double bottomLeftX, double bottomLeftY,
        double bottomRightX, double bottomRightY,
        int i)
    {
        int r = i / m; // 行索引
        int c = i % m; // 列索引

        double u = (double)c / (m - 1); // 归一化列位置
        double v = (double)r / (n - 1); // 归一化行位置

        // 双线性插值计算X和Y补偿值
        double xComp = (1 - u) * (1 - v) * topLeftX + u * (1 - v) * topRightX + (1 - u) * v * bottomLeftX + u * v * bottomRightX;
        double yComp = (1 - u) * (1 - v) * topLeftY + u * (1 - v) * topRightY + (1 - u) * v * bottomLeftY + u * v * bottomRightY;

        return Tuple.Create(xComp, yComp);
    }
}

使用示例:

// 示例:3行3列矩阵,计算位置i=4的补偿值
var result = CompensationCalculator.GetCompensation(
    n: 3, m: 3,
    topLeftX: 0.0, topLeftY: 0.0,
    topRightX: 1.0, topRightY: 0.0,
    bottomLeftX: 0.0, bottomLeftY: 1.0,
    bottomRightX: 1.0, bottomRightY: 1.0,
    i: 4);

Console.WriteLine($"X补偿值: {result.Item1}, Y补偿值: {result.Item2}");
// 输出: X补偿值: 0.5, Y补偿值: 0.5

说明:

  • 返回类型:使用 Tuple<double, double>(.NET Framework 4.5 原生支持)。
  • 验证移除:假设调用方确保输入参数有效(n>2, m>2, i在0到n*m-1范围内)。
  • 核心逻辑:使用双线性插值计算 。


为离线设备安装语言对话大模型流程(LM-Studio qwen3vl-4b)

0. 准备工作

0.1 下载LM Studio安装包

a. 访问LM Studio官方网站
b. 下载适用于Windows 64位系统的安装包

0.2 下载模型文件

a. 访问LM Studio模型目录

b. 选择并下载推荐的模型:

模型名称推荐版本适用场景预估大小
Qwen3-VL-4BQ4_K_M多模态、图文理解2.5-3GB
Deepseek Coder 6.7BQ4_K_S代码生成与理解3.5-4GB

c. 下载模型所需的全部文件:

  • GGUF主模型文件(必需):模型名-量化版本.gguf
  • 投影文件(如有):模型名-F16.ggufmmproj-模型名-F16.gguf
  • 配置文件(如有):config.json
  • 分词器文件(如有):tokenizer.json

0.3 文件整理与打包

a. 创建文件夹结构

   离线模型安装包/
   ├── LM-Studio-0.3.36-1-x64.exe
   └── models/
       └── lmstudio-community/
           ├── Qwen3-VL-4B-Instruct-GGUF/
           │   ├── Qwen3-VL-4B-Instruct-Q4_K_M.gguf
           │   └── mmproj-Qwen3-VL-4B-Instruct-F16.gguf
           └── deepseek-coder-6.7B-instruct-GGUF/
               ├── deepseek-coder-6.7B-instruct-Q4_K_S.gguf
               └── tokenizer.json

b. 模型选择建议

  • 内存12GB以下设备: 选择4-7B参数量的Q4_K_S版本
  • 内存16GB设备: 选择7-14B参数量的Q4_K_M版本
  • 内存32GB以上设备: 可考虑Q8或更高精度的量化版本

0.4 系统要求检查

项目最低要求推荐配置
操作系统Windows 10 64位Windows 11 64位
处理器4核心CPU8核心及以上CPU
内存8GB RAM16GB RAM或更高
存储空间10GB可用空间50GB可用空间
显卡集成显卡NVIDIA显卡(支持CUDA)

1. 安装 LM Studio

  1. 双击运行下载好的 LM-Studio-0.3.36-1-x64.exe(版本号可能不同)。
  2. 若系统提示“是否允许此应用对设备进行更改?”,点击
  3. 按照安装向导提示完成安装:

    • 选择安装语言(通常为英文或自动识别系统语言)。
    • 点击 Next,接受许可协议。
    • 选择安装路径(建议保持默认,或自定义至空间充足的磁盘)。
    • 点击 Install 开始安装。
    • 安装完成后,勾选“Launch LM Studio”(启动 LM Studio),点击 Finish

2. 放置模型文件

  1. 找到 LM Studio 的模型默认存储路径(通常在以下位置之一):

    • C:\Users\[用户名]\AppData\Local\lm-studio\models
    • 或在 LM Studio 设置中查看“Model Directory”路径。
  2. 将您打包好的 lmstudio-community 文件夹(内含整理好的模型文件夹)整体复制到上述模型存储路径中。
  3. 若您下载了多个模型(例如 Qwen3-VL-4B 和 Deepseek-Coder-6.7B),请确保每个模型文件夹都按照以下结构放置:
lm-studio/models/
    ├── lmstudio-community/
    │   ├── Qwen3-VL-4B-Instruct-GGUF/
    │   │   ├── Qwen3-VL-4B-Instruct-Q4_K_M.gguf
    │   │   └── mmproj-Qwen3-VL-4B-Instruct-F16.gguf
    │   └── deepseek-coder-6.7B-GGUF/
    │       ├── deepseek-coder-6.7B-instruct-Q4_K_M.gguf
    │       └── config.json(如有)

3. 在 LM Studio 中加载模型

  1. 打开 LM Studio 软件。
  2. 点击左侧菜单栏中的 “Select a model”(选择模型)。
  3. 在模型列表中,找到您放置的模型文件夹(如 lmstudio-community),点击进入,选择对应的 .gguf 模型文件(如 Qwen3-VL-4B-Instruct-Q4_K_M.gguf)。
  4. 点击 “Load model”(加载模型)。
  5. 加载成功后,右侧对话界面会显示“Model loaded successfully”提示。

4. 配置模型参数(可选)

  1. 在加载模型后,可点击右上角 “Settings”(设置)调整运行参数:

    • GPU Offload:如果有独立显卡,可适当分配显存以加速推理。
    • Context Length:根据内存大小调整上下文长度(建议初次保持默认)。
    • Threads:设置 CPU 线程数(通常自动检测,可手动调整以提高性能)。
  2. 调整后点击 “Save” 保存设置。

5. 测试模型运行

  1. 在右侧对话框输入问题,例如:“请用 Python 写一个 Hello World 程序。”
  2. 点击发送或按 Enter,观察模型回复是否正常。
  3. 如无响应或报错,请检查:

    • 模型文件是否完整、未损坏。
    • 内存是否足够(任务管理器中查看内存占用)。
    • 是否选择了正确的 .gguf 文件。

6. 常见问题与解决

问题可能原因解决方案
模型加载失败模型文件路径错误确认模型文件是否放在 LM Studio 默认模型路径中
运行速度极慢内存不足或未启用 GPU关闭其他程序,或在设置中开启 GPU Offload
对话无响应模型未成功加载重新启动 LM Studio,重新加载模型
提示“Out of Memory”模型过大,内存不足更换更小量化版本的模型(如 Q4_K_S)