万字长文,Electron高性能DLL调用实战:Worker线程处理图像

目录

前言

解析结构体数据

什么是buffer

异步队列

Worker threads中处理图像

Worker threads 是什么?

为什么需要它?

图像处理

图片渲染

核心问题:渲染进程被阻塞

解决方案

图片压缩

帧率优化


前言

在前面这篇文章中万字长文,Electron高性能DLL调用实战:手把手教你使用Koffi调用DLLhttps://blog.youkuaiyun.com/simon1030/article/details/153329559我们分享了如何通过Koffi调用DLL,并且通过回调函数,接收DLL传递过来的图像数据,今天我们将继续探讨一下,如果使用Node.js中的Worker线程来高效的处理DLL回调接收到的图像数据。

先回忆一下,在之前的回调函数中,我们解析了结构体中的图像数据,代码如下

const myImgInfoCallback = async (ImgInfoPtr) => {
 
    const imgInfo = koffi.decode(ImgInfoPtr, ImgInfo)
 
    const { deviceNum } = imgInfo
 
    const offset = koffi.sizeof(ImgInfo)
 
    const imgBuffer = koffi.decode(
        ImgInfoPtr,
        offset,
        imgInfoStruct,
        deviceNum
    )
 
}

可以看到代码中,有一个imgInfoStruct,这就是真正的图像数据了,下面结合C++头文件中的定义,先来完善一下这部分的代码,把图像数据,真正的解析到结构体中去。

解析结构体数据

在我们的C++头文件中,关于图像的相关结构体很多,主要的部分定义如下

enum MyImageAlignType
{
	DEPTH_2_COLOR = 0,
	COLOR_2_DEPTH = 1,
	UNALIGNED_TYPE = 2,
};

enum MyImageType
{
	RGB = 0,
	BGR = 1,
	GRAY = 2,
	DEPTH = 3,
	BINARY = 4,
};

typedef struct SingleImgInfo
{
	unsigned int deviceID;
	ImgInfo imgInfo;

	SingleImgInfo():deviceID(0)
	{}
}SingleImgInfo;

typedef struct ImgInfo
{
	MyImageAlignType alignType;
	MyImageType type;
	int channel;
	int width;
	int height;
	int dataLength;
	unsigned char* dataBuf;

	ImgInfo()
		: 
		alignType(UNALIGNED_TYPE), type(RGB),
		channel(0), width(0), height(0), dataLength(0), dataBuf(nullptr)
	{
	}
}ImgInfo;

现在在回调函数中,我们使用上面的结构体,将接收到的ImgInfo解析出来

const myImgInfoCallback = async (ImgInfoPtr) => {
 
    const imgInfo = koffi.decode(ImgInfoPtr, ImgInfo)
 
    const { deviceNum } = imgInfo
 
    const offset = koffi.sizeof(ImgInfo)
 
    const imgBuffer = koffi.decode(
        ImgInfoPtr,
        offset,
        koffi.struct({
            deviceID: 'unsigned int',
            colorImgInfo: koffi.struct({
                alignType: 'int',
                type: 'int',
                channel: 'int',
                width: 'int',
                height: 'int',
                dataLength: 'int',
                dataBuf: koffi.pointer('void')
            })
        }),
        deviceNum
    )
 
}

这样decode之后,就可以拿到图像数据的数组,数组中就包含了我们需要的图像buffer,以便进行下一步操作。前端同学看到这里或许有点迷茫,什么是buffer? 

什么是buffer

buffer 就是一个 Node.js Buffer 对象Uint8Array,里面存放着图片的原始像素字节。

Buffer = 原始的二进制数据块(内存区域)

在 C/C++ 里,图片、声音、视频、文件等数据,本质上都是一段连续的内存空间

unsigned char* dataBuf; // 指向内存首地址
int dataLength;         // 表示这块内存的长度(字节数)

这段内存就叫做一个 buffer(缓冲区)

异步队列

接下来,我们就需要将图片保存到本地,要求保存为无损的bmp格式。

保存之前,我们先来看一下,在定义的结构体中,有一个专门定义图片类型的枚举类型:

enum MyImageType
{
	RGB = 0,
	BGR = 1,
	GRAY = 2,
	DEPTH = 3,
	BINARY = 4,
}

这个枚举类型定义了多种格式,具体是什么呢?让我们先来翻译一下

名称 整数值 含义
RGB 0 彩色图像,像素按红绿蓝通道顺序排列
BGR 1 彩色图像,像素按蓝绿红通道顺序排列(OpenCV 默认格式)
GRAY 2 灰度图像(每个像素 1 个亮度
### 自然语言处理综述 #### 发展历程与现状 自然语言处理的发展经历了多个历史阶段的演进,不同学派之间相互补充促进,共同推动了这一技术的快速发展[^1]。作为人工智能领域的重要分支,自然语言处理涉及如何使计算机理解和生成人类自然语言的问题[^2]。 #### 技术方法演变 早期的研究主要依赖于基于规则的方法来描述语言的形式特征;然而这种方法对于复杂问题存在局限性,并且需要大量人工定义规则[^3]。随着研究深入和技术进步,出现了更多先进的技术和算法: - **基于统计的方法**:通过大规模语料库自动学习概率分布来进行预测和决策。 - **预训练语言模型**:近年来兴起的一种强大工具,在众多下游任务上取得了显著成果,如语言建模、机器翻译、问答系统等[^4]。 ```python import transformers as trfms from datasets import load_dataset # 加载预训练模型及其对应的分词器 model_name = "bert-base-cased" tokenizer = trfms.BertTokenizer.from_pretrained(model_name) model = trfms.BertModel.from_pretrained(model_name) def encode_text(text): """ 对输入文本进行编码 """ inputs = tokenizer.encode_plus( text, add_special_tokens=True, max_length=512, padding='max_length', truncation=True, return_attention_mask=True, return_tensors="pt", ) return inputs['input_ids'], inputs['attention_mask'] text_example = "这是一个用于展示BERT使用的例子。" encoded_input, attention_mask = encode_text(text_example) outputs = model(encoded_input, attention_mask=attention_mask)[0] print(outputs.shape) # 输出最后一层隐藏状态张量大小 ``` 此代码片段展示了如何利用Hugging Face提供的`transformers`库加载并使用预训练好的BERT模型对一段中文文本进行编码表示。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光芒万丈向远方

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值