Skip to content

附录:调用示例 / 错误码 / 线程安全 / 调用流程

版本:1.26.0613


目录


1. 调用示例

1.1 C/C++ 示例

cpp
#include "include/export_dll.h"
#include <stdio.h>
#include <string.h>

int main() {
    // ===== 1. 通用工具 =====
    printf("版本: %s\n", version());
    printf("DLL目录: %s\n", getDllDir());

    // ===== 2. YOLOv8 检测 =====
    int ret = loadYolov8Model("detector", "yolov8n.onnx");
    if (ret == 1) {
        printf("模型加载成功\n");
        setYolov8Sim("detector", 0.6f);
        setYolov8Iou("detector", 0.45f);
        const char* result = yolov8Detect("detector", "test.jpg");
        printf("检测结果: %s\n", result);
        result = yolov8DetectDraw("detector", "test.jpg", "result.jpg");
        printf("绘制结果: %s\n", result);
    }

    // ===== 3. OCR 识别 =====
    ret = initOcrv4(4);
    if (ret == 1) {
        OcrParam param;
        param.sim = 0.6f;
        param.use_angle_cls = 1;
        const char* text = ocrv4Detect("text.png", &param);
        printf("OCR结果: %s\n", text);
        printf("OCR中文: %s\n", utf8ToGBK(text));
    }

    // ===== 4. 找图(多目标) =====
    const char* matches = findPic("screen.png", "icon.png", 1, 10, 0.8f);
    printf("找图结果: %s\n", matches);
    matches = findPicOut("screen.png", "icon.png", 1, 10, 0.8f, "marked.png");

    // ===== 5. 纯模板匹配(单目标) =====
    const char* tm = templateMatch("screen.png", "icon.png", 0.8f, 0, 1);
    printf("模板匹配: %s\n", tm);
    tm = templateMatch("screen.png", "icon.png", 0.8f, 1, 2);
    printf("快速匹配: %s\n", tm);

    // ===== 6. 多模板匹配 =====
    const char* multi = templateMatchMulti("screen.png",
        "icon1.png, icon2.png, icon3.png", 0.8f, 0, 1);
    printf("多模板匹配: %s\n", multi);

    // ===== 7. 图片灰度处理 =====
    const char* grayRet = imageToGray("photo.jpg", "");
    printf("灰度处理: %s\n", grayRet);
    grayRet = imageToGray("photo.jpg", "C:/out/gray.jpg");
    printf("灰度处理(指定路径): %s\n", grayRet);

    // ===== 8. 图像处理接口 =====
    const char* sc = screenCapture("screenshot.png", 0, 0, 1920, 1080);
    printf("截图: %s\n", sc);

    const char* crop = imageCrop("photo.jpg", 100, 100, 200, 200, "crop.jpg");
    printf("裁剪: %s\n", crop);

    const char* resize = imageResize("photo.jpg", 640, 480, "resized.jpg");
    printf("缩放: %s\n", resize);

    const char* color = findColor("screen.png", "FF0000", 10);
    printf("找色: %s\n", color);

    const char* pixel = getPixelColor("screen.png", 100, 200);
    printf("像素色: %s\n", pixel);

    const char* sim = imageCompare("img1.png", "img2.png");
    printf("相似度: %s\n", sim);

    return 0;
}

1.2 C# 示例

csharp
using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr version();

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr getLastError();

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int loadYolov8Model(string name, string modelPath);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr yolov8Detect(string name, string imgPath);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern int initOcrv4(int nThreads);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr ocrv4Detect(string img_path, ref OcrParam param);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr findPic(string img_path, string target_path,
        int model, int number, float sim);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr templateMatch(string imgPath, string templPath,
        float threshold, int mode, int method);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr templateMatchMulti(string imgPath, string templPaths,
        float threshold, int mode, int method);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr utf8ToGBK(string u8);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr imageToGray(string srcPath, string outPath);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr screenCapture(string outPath, int left, int top,
        int width, int height);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr imageCrop(string srcPath, int x, int y,
        int w, int h, string outPath);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr imageResize(string srcPath, int width,
        int height, string outPath);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr findColor(string imgPath, string colorHex,
        int tolerance);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr getPixelColor(string imgPath, int x, int y);

    [DllImport("Lkinfer32.dll", CallingConvention = CallingConvention.Cdecl)]
    public static extern IntPtr imageCompare(string img1, string img2);

    [StructLayout(LayoutKind.Sequential)]
    public struct OcrParam
    {
        public int padding;
        public int max_size;
        public float sim;
        public float box_thresh;
        public float un_clip_ratio;
        public int use_angle_cls;
        public int most_angle;
    }

    static string PtrToString(IntPtr ptr)
    {
        return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) ?? "" : "";
    }

    static void Main()
    {
        Console.WriteLine("版本: " + PtrToString(version()));

        // YOLOv8
        int ret = loadYolov8Model("detector", "yolov8n.onnx");
        if (ret == 1)
        {
            string result = PtrToString(yolov8Detect("detector", "test.jpg"));
            Console.WriteLine("检测: " + result);
        }

        // OCR
        ret = initOcrv4(4);
        if (ret == 1)
        {
            OcrParam param = new OcrParam();
            param.sim = 0.6f;
            param.use_angle_cls = 1;
            string text = PtrToString(ocrv4Detect("text.jpg", ref param));
            Console.WriteLine("OCR: " + text);
        }

        // 找图
        string matches = PtrToString(findPic("screen.png", "icon.png", 1, 10, 0.8f));
        Console.WriteLine("找图: " + matches);

        // 模板匹配
        string tm = PtrToString(templateMatch("screen.png", "icon.png", 0.8f, 0, 1));
        Console.WriteLine("匹配: " + tm);

        // 多模板匹配
        string multi = PtrToString(templateMatchMulti("screen.png",
            "icon1.png,icon2.png,icon3.png", 0.8f, 0, 1));
        Console.WriteLine("多模板: " + multi);

        // 截图
        string sc = PtrToString(screenCapture("screenshot.png", 0, 0, 1920, 1080));
        Console.WriteLine("截图: " + sc);

        // 裁剪
        string crop = PtrToString(imageCrop("photo.jpg", 100, 100, 200, 200, "crop.jpg"));
        Console.WriteLine("裁剪: " + crop);

        // 缩放
        string resize = PtrToString(imageResize("photo.jpg", 640, 480, "resized.jpg"));
        Console.WriteLine("缩放: " + resize);

        // 找色
        string color = PtrToString(findColor("screen.png", "FF0000", 10));
        Console.WriteLine("找色: " + color);

        // 像素颜色
        string pixel = PtrToString(getPixelColor("screen.png", 100, 200));
        Console.WriteLine("像素色: " + pixel);

        // 图片相似度
        string sim = PtrToString(imageCompare("img1.png", "img2.png"));
        Console.WriteLine("相似度: " + sim);
    }
}

1.3 Python 示例

python
import ctypes
import json
from ctypes import c_char_p, c_int, c_float, Structure, POINTER, byref

# 加载 DLL
dll = ctypes.CDLL("Lkinfer32.dll")
dll.version.restype = c_char_p
dll.getLastError.restype = c_char_p
dll.utf8ToGBK.restype = c_char_p
dll.yolov8Detect.restype = c_char_p
dll.ocrv4Detect.restype = c_char_p
dll.findPic.restype = c_char_p
dll.templateMatch.restype = c_char_p

# YOLOv8
dll.loadYolov8Model.argtypes = [c_char_p, c_char_p]
dll.loadYolov8Model.restype = c_int
dll.yolov8Detect.argtypes = [c_char_p, c_char_p]
dll.setYolov8Sim.argtypes = [c_char_p, c_float]

# OCR
dll.initOcrv4.argtypes = [c_int]
dll.initOcrv4.restype = c_int
dll.utf8ToGBK.argtypes = [c_char_p]

# findPic
dll.findPic.argtypes = [c_char_p, c_char_p, c_int, c_int, c_float]

# 纯模板匹配
dll.templateMatch.argtypes = [c_char_p, c_char_p, c_float, c_int, c_int]

# 多模板匹配
dll.templateMatchMulti.argtypes = [c_char_p, c_char_p, c_float, c_int, c_int]
dll.templateMatchMulti.restype = c_char_p

# 灰度处理
dll.imageToGray.argtypes = [c_char_p, c_char_p]
dll.imageToGray.restype = c_char_p

# 屏幕截图
dll.screenCapture.argtypes = [c_char_p, c_int, c_int, c_int, c_int]
dll.screenCapture.restype = c_char_p

# 裁剪
dll.imageCrop.argtypes = [c_char_p, c_int, c_int, c_int, c_int, c_char_p]
dll.imageCrop.restype = c_char_p

# 缩放
dll.imageResize.argtypes = [c_char_p, c_int, c_int, c_char_p]
dll.imageResize.restype = c_char_p

# 找色
dll.findColor.argtypes = [c_char_p, c_char_p, c_int]
dll.findColor.restype = c_char_p

# 取像素颜色
dll.getPixelColor.argtypes = [c_char_p, c_int, c_int]
dll.getPixelColor.restype = c_char_p

# 图片相似度
dll.imageCompare.argtypes = [c_char_p, c_char_p]
dll.imageCompare.restype = c_char_p

class OcrParam(Structure):
    _fields_ = [
        ("padding", c_int),
        ("max_size", c_int),
        ("sim", c_float),
        ("box_thresh", c_float),
        ("un_clip_ratio", c_float),
        ("use_angle_cls", c_int),
        ("most_angle", c_int),
    ]

dll.ocrv4Detect.argtypes = [c_char_p, POINTER(OcrParam)]
dll.ocrv4Detect.restype = c_char_p

print(f"版本: {dll.version().decode()}")

# YOLOv8
ret = dll.loadYolov8Model(b"detector", b"yolov8n.onnx")
if ret == 1:
    dll.setYolov8Sim(b"detector", c_float(0.6))
    result = dll.yolov8Detect(b"detector", b"test.jpg").decode()
    data = json.loads(result)
    for obj in data:
        print(f"  发现 {obj['name']} 在 ({obj['x']}, {obj['y']})")

# OCR
ret = dll.initOcrv4(4)
if ret == 1:
    param = OcrParam(sim=0.6, use_angle_cls=1)
    text = dll.ocrv4Detect(b"text.jpg", byref(param)).decode()
    print(f"OCR: {dll.utf8ToGBK(text.encode()).decode('gbk')}")

# 找图
matches = dll.findPic(b"screen.png", b"icon.png", 1, 10, 0.8).decode()
print(f"找图: {matches}")

# 纯模板匹配
tm = dll.templateMatch(b"screen.png", b"icon.png", 0.8, 0, 1).decode()
print(f"匹配: {tm}")
result = json.loads(tm)
if result["matched"]:
    print(f"  位置: ({result['x']}, {result['y']}), 分值: {result['score']}")

# 多模板匹配
multi = dll.templateMatchMulti(b"screen.png",
    b"icon1.png,icon2.png,icon3.png", 0.8, 0, 1).decode()
print(f"多模板: {multi}")
results = json.loads(multi)
for key in sorted(results):
    r = results[key]
    print(f"  {key}: matched={r['matched']}, score={r['score']}")

# 灰度处理
gray = dll.imageToGray(b"photo.jpg", b"").decode()
print(f"灰度: {gray}")

# 截图
sc = dll.screenCapture(b"screenshot.png", 0, 0, 1920, 1080).decode()
print(f"截图: {sc}")

# 裁剪
crop = dll.imageCrop(b"photo.jpg", 100, 100, 200, 200, b"crop.jpg").decode()
print(f"裁剪: {crop}")

# 缩放
resized = dll.imageResize(b"photo.jpg", 640, 480, b"resized.jpg").decode()
print(f"缩放: {resized}")

# 找色
color = dll.findColor(b"screen.png", b"FF0000", 10).decode()
print(f"找色: {color}")

# 像素颜色
pixel = dll.getPixelColor(b"screen.png", 100, 200).decode()
print(f"像素色: {pixel}")

# 图片相似度
sim = dll.imageCompare(b"img1.png", b"img2.png").decode()
print(f"相似度: {sim}")

2. 错误码与处理

2.1 统一错误码体系

2.1.1 通用错误码表

返回码含义说明
1成功操作正常完成
0一般性失败文件不存在、模型不存在、参数错误等
-1原图不存在输入图片路径无效或文件无法读取
-2模板/目标图不存在模板图片路径无效或文件无法读取
2模型不存在YOLOv8 指定名称的模型未加载
3模型不存在(等同上)部分旧接口使用此码
4运行时异常内部异常,调用 getLastError() 获取详细错误描述
"[]"无匹配结果findPic / yolov8Detect 未检测到目标
"{}"无信息/空对象getYolov8Info / templateMatchMulti 无结果

2.1.2 各模块错误码对照

A. 通用工具(均返回整数/字符串)

函数成功失败
version()版本字符串永不失败
getDllDir()目录路径空字符串
getLastError()错误描述空字符串(无错误)
utf8ToGBK(u8)GBK 字符串永不失败
clearCache()1永不失败
log_off()1永不失败

B. YOLOv8 检测(返回整数)

函数成功模型不存在异常
loadYolov8Model10(文件不存在)4
reLoadYolov8Model13(原模型不存在)4
setYolov8Sim10
setYolov8Iou10
existsYolov8Name1(存在) / 0(不存在)

C. YOLOv8 检测(返回 JSON 字符串)

函数成功图片不存在模型不存在无结果异常
yolov8DetectJSON 数组"0""2""[]""4"
yolov8DetectDrawJSON 数组"0""2""[]""4"
getYolov8InfoJSON 对象"{}""4"
getAllYolov8NameJSON 数组"[]"

D. OCR 文字识别

函数成功失败/异常
initOcrv4(nThreads)14
ocrv4DetectJSON 字符串"4"(异常)
ocrv4DetectParamJSON 字符串"4"(异常)

E. 模板匹配找图(findPic 系列)

函数成功原图不存在模板不存在无匹配
findPicJSON 数组"-1""-2""[]"
findPicDrawJSON 数组"-1""-2""[]"
findPicOutJSON 数组"-1""-2""[]"

F. 纯模板匹配(templateMatch 系列)

函数成功一般性失败
templateMatch{"matched":true/false, ...}{"matched":false, "error":"原因"}
templateMatchMulti{"in_0":{...}, ...}"{}"
imageToGray{"success":true}{"success":false, "error":"原因"}

templateMatch 的 error 字段取值:

error 值触发条件
"参数为空"imgPath 或 templPath 为 nullptr
"阈值范围错误"threshold 不在 [0, 1] 范围
"色彩模式参数错误"mode 不是 0 或 1
"算法模式参数错误"method 不是 1~6
"主图不存在"主图文件无法读取
"模板图不存在"模板文件无法读取
"模板图大于主图"模板尺寸超过主图
"未找到匹配"匹配分值低于阈值

templateMatchMulti 单条错误:"模板图无效"(该模板文件不存在或尺寸超过主图)。

imageToGray 的 error 字段取值:

error 值触发条件
"原图片路径为空"srcPath 为 nullptr 或空字符串
"原图片不存在或无法读取"图片文件无法读取
"不支持的图片通道数"图片通道数不是 1/3/4
"保存图片失败"imwrite 写入失败

G. 图像处理接口

所有图像处理接口统一返回 {"success":true/false, ...}

error 值触发函数触发条件
"输出路径为空"screenCapture / imageCrop / imageResizeoutPath 为 nullptr 或空字符串
"截图宽高必须大于0"screenCapturewidth ≤ 0 或 height ≤ 0
"保存截图失败"screenCaptureimwrite 写入失败
"原图片路径为空"imageCrop / imageResizesrcPath 为 nullptr 或空字符串
"裁剪宽高必须大于0"imageCropw ≤ 0 或 h ≤ 0
"原图片不存在或无法读取"imageCrop / imageResize / findColor / getPixelColor / imageCompareimread 返回空图
"裁剪区域超出图片范围"imageCropROI 超出图像边界
"保存裁剪图片失败"imageCropimwrite 写入失败
"目标宽高必须大于0"imageResizewidth ≤ 0 或 height ≤ 0
"保存缩放图片失败"imageResizeimwrite 写入失败
"图片路径为空"findColor / getPixelColor / imageCompare路径为 nullptr 或空字符串
"颜色值为空"findColorcolorHex 为 nullptr 或空字符串
"颜色值格式错误,需6位十六进制"findColorcolorHex 格式不正确
"坐标超出图片范围"getPixelColorx/y 超出图像边界

2.2 错误处理最佳实践

场景 1:整数返回接口

cpp
int ret = loadYolov8Model("detector", "model.onnx");
if (ret != 1) {
    if (ret == 4) {
        fprintf(stderr, "异常: %s\n", getLastError());
    } else if (ret == 0) {
        fprintf(stderr, "模型文件不存在\n");
    }
    return -1;
}

场景 2:JSON 字符串接口(yolov8Detect / findPic)

cpp
const char* result = yolov8Detect("detector", "test.jpg");
if (strcmp(result, "0") == 0) {
    printf("图片不存在\n");
} else if (strcmp(result, "2") == 0) {
    printf("模型不存在\n");
} else if (strcmp(result, "4") == 0) {
    printf("异常: %s\n", getLastError());
} else if (strcmp(result, "[]") != 0) {
    printf("检测到目标: %s\n", result);
}

场景 3:templateMatch 统一 JSON 格式

cpp
const char* tm = templateMatch("screen.png", "icon.png", 0.8f, 0, 1);
// 直接解析 JSON 判断 matched 字段

场景 4:imageToGray 统一 JSON 格式

cpp
const char* ret = imageToGray("photo.jpg", "");
// 解析 JSON 判断 success 字段

3. 线程安全说明

3.1 线程安全保证

模块安全级别说明
YOLOv8✅ 线程安全每个模型名称有独立的互斥锁。不同模型可并发调用
OCR⚠️ 单例安全全局单例 OcrLite 实例,建议外部加锁同步
找图✅ 无状态所有函数均为无状态调用,线程安全
模板匹配✅ 无状态线程安全(缓存字符串为独立 static 变量)
灰度处理✅ 无状态线程安全
图像处理✅ 无状态截图/裁剪/缩放/颜色查找/对比均为无状态调用,线程安全

3.2 多线程建议

cpp
// 安全:不同模型可并发
std::thread([] { yolov8Detect("model1", "img1.jpg"); });
std::thread([] { yolov8Detect("model2", "img2.jpg"); });

// OCR 建议外部同步
std::mutex ocr_mtx;
std::thread([&] {
    std::lock_guard<std::mutex> lock(ocr_mtx);
    ocrv4Detect("img.jpg", &param);
});
std::thread([&] {
    std::lock_guard<std::mutex> lock(ocr_mtx);
    ocrv4Detect("img2.jpg", &param);
});

4. 调用流程

4.1 YOLOv8 检测流程

1. loadYolov8Model("detector", "yolov8n.onnx")    // 加载模型

2. setYolov8Sim("detector", 0.6)                   // 可选:调参

3. yolov8Detect("detector", "test.jpg")            // 执行检测

4. 解析 JSON 结果                                   // 处理结果

4.2 OCR 识别流程

1. initOcrv4(4)                                     // 初始化(只需一次)

2. 构造 OcrParam 结构体                             // 设置参数

3. ocrv4Detect("text.jpg", &param)                  // 执行识别

4. utf8ToGBK(结果) → 显示中文                        // 编码转换(可选)

4.3 模板匹配与图像处理流程

1. templateMatch("screen.png", "icon.png", 0.8, 0, 1)  // 通用匹配
   └── 返回 {"matched":true, "x":100, "y":200, "score":0.95}

2. templateMatch("screen.png", "icon.png", 0.8, 1, 2)  // 灰度 + SQDIFF(最快)

3. templateMatch("screen.png", "icon.png", 0.7, 0, 1)  // 彩色 + CCOEFF_NORMED

4. templateMatchMulti("screen.png", "btn1.png, btn2.png, btn3.png", 0.8, 0, 1)
   └── 返回 {"in_0":{...}, "in_1":{...}, "in_2":{...}}

5. imageToGray("photo.jpg", "")                        // 灰度处理(自动命名)
   └── 生成 photo_gray.jpg,返回 {"success":true}

6. screenCapture("screenshot.png", 0, 0, 1920, 1080)   // 屏幕截图
   └── 返回 {"success":true, "path":"screenshot.png"}

7. imageCrop("photo.jpg", 100, 100, 200, 200, "crop.jpg")  // 裁剪
   └── 返回 {"success":true}

8. imageResize("photo.jpg", 640, 480, "resized.jpg")   // 缩放
   └── 返回 {"success":true}

9. findColor("screen.png", "FF0000", 10)               // 找色
   └── 返回 {"success":true, "count":5, "points":[[x1,y1],...]}

10. getPixelColor("screen.png", 100, 200)              // 取像素颜色
    └── 返回 {"success":true, "color":"FF0000", "hex":"#FF0000"}

11. imageCompare("img1.png", "img2.png")               // 图片相似度
    └── 返回 {"success":true, "similarity":0.95}

提示:所有返回字符串(const char*)为内部静态缓存,调用者无需释放内存。但在下一次调用同一函数前,需及时取出数据或拷贝。