WebAssembly探索篇(四)emcc和cmake编译opencv复杂案例

文章目录

  • 开发环境
  • 工程目录
    • CMakeLists.txt
    • main.cpp
  • web端
    • index.html
    • 效果图
  • 遇到的问题
    • JS与C++传值
    • Uncaught TypeError: Module._malloc is not a function
    • canvas像素RGBA四通道
  • 经验&&教训
  • 参考

    最近因为项目原因,研究了一下WebAssembly。2015年上线与JS、HTML、CSS并称web界四语言,额,虽然已经上线快10年,但是研究的人好少,注定这个探索之路是崎岖的。(事实也是这样,已经耗进去快2周了,人都麻了-_-||)
    这篇文章主要介绍在引用图像增强算法时遇到的一些问题,因涉及算法内容,以下代码将做一些处理。。。javaer表示知识的海洋真广阔呀~

开发环境

为啥要把开发环境放在第一位呢,这里面也是采了无数的坑。

开发工具版本
Ubuntu18.04
emscripten3.1.55
cmake3.28.3
opencv3.2.0

工程目录

┌─imageAlgorithm  项目名称 
│─build             编译文件(emcmake和emmake后的产物)
│  └─CMakeFile       
│  │  └─...      
│  └─cmake_install.cmake
│  └─CMakeCache.txt
│  └─Makefile
│  └─imageAlgorithm.js
│  └─imageAlgorithm.wasm
├─main.cpp          主入口
├─algorithm1.cpp          算法1
├─...           
├─algorithmN.cpp         算法N  
├─head1.h     算法1头文件 
├─headN.h 
├─CMakeLists.txt        

CMakeLists.txt


cmake_minimum_required( VERSION 3.8 )
set( CMAKE_CXX_STANDARD 17 )
project( imageAlgorithm )# Needed for opencv2/opencv.hpp
include_directories( /root/wasm/opencv-demo/opencv/include )# Needed by opencv.hpp for opencv2/opencv_modules.hpp
include_directories( /root/wasm/opencv-demo/opencv/platforms/js/build_wasm )# Needed by opencv_modules.hpp for every module
file( GLOB opencv_include_modules "/root/wasm/opencv-demo/opencv/modules/*/include" )
include_directories( ${opencv_include_modules} )# 此处将所有.cpp文件加入,此处省略下,可以把参与编译的cpp文件全部放在一个文件夹下面 
add_executable( imageAlgorithm main.cpp algorithm1.cpp algorithm2.cpp ... algorithmN.cpp)# Link to opencv.js precompiled libraries
file( GLOB opencv_js "/root/wasm/opencv-demo/opencv/platforms/js/build_wasm/lib/*.a" )
target_link_libraries( imageAlgorithm ${opencv_js} )set_target_properties(imageAlgorithm PROPERTIES LINK_FLAGS "-s EXIT_RUNTIME=1 -O3 -sNO_DISABLE_EXCEPTION_CATCHING -sALLOW_MEMORY_GROWTH -s EXPORTED_FUNCTIONS=\"['_postProcess', '_malloc', '_free', '_postProcess1']\"")

main.cpp

在编写过程中发现emscripten对C++支持度不够,不能直接暴露类的方法,所以不得不在最外面在包裹一层main.cpp

#include "algorithm.h"
#include <emscripten.h>extern "C"  void postProcess1(unsigned char* image, int width, int height) {  // 创建一个 Mat 对象来存储传入的图像数据cv::Mat mat(height, width, CV_8UC4, image);// 将红色和绿色通道全部置零cv::MatIterator_<cv::Vec4b> it, end;for (it = mat.begin<cv::Vec4b>(), end = mat.end<cv::Vec4b>(); it != end; ++it) {(*it)[2] = 0; // 红色通道置零(*it)[1] = 0; // 绿色通道置零}
}

web端

使用emcc+cmake执行编译,将生成后的js和wasm文件拷贝至web项目中,web项目结构如下:

┌─web  项目名称 
│─imageAlgorithm.js          
│  imageAlgorithm.wasm    
│  index.html

index.html

主要变量的说明:

  • canvas1为原图,图片数据imageData
  • canvas2为经过算法处理后的图,图片数据postImageData
// 从canvas1中获取图像数据                  
const imageData = ctx.getImageData(0, 0, width, height);
// 获取图像的像素数组 
const pixelData = imageData.data;
var pixels = new Uint8Array(pixelData);
// 分配内存 
var dataptr = Module._malloc(pixelData.length);
Module.HEAPU8.set(pixels, dataptr);
// 调用C/C++算法处理
Module._postProcess1(dataptr, width, height);// 设置canvas2的image对象
var postImageData = ctxNew.createImageData(width, height);
// 将像素数组数据从内存复制到 ImageData 对象
var imageDataArray = Module.HEAPU8.subarray(dataptr, dataptr + width * height * 4); // 假设每个像素有 RGBA 四个通道
postImageData.data.set(imageDataArray);
// 将 ImageData 对象绘制到 Canvas 上
ctxNew.putImageData(postImageData, 0, 0);// 释放内存
Module._free(dataptr)

效果图

在这里插入图片描述

遇到的问题

JS与C++传值

2.4 JavaScript与C交换数据

真的没想到啊,两者之间只能传递Number!!!

需要在JavaScript与C/C++之间交换大块的数据时,直接使用参数传递数据显然不可行,此时可以通过内存来交换数据

Uncaught TypeError: Module._malloc is not a function

在JS中调用Module._malloc报错,理论上,Emscripten应该会把C/C++所有的默认方法都exported出来,为啥会报这个错误呢?

BUG: Uncaught TypeError: Module._malloc is not a function

在emscripten-core项目issue中找到相同问题,有个大佬回复了:版本升级到3.1.31后为了减小emscripten导出体积,把这些默认的导出配置cut掉了,需要开发者自行配置,看官方的changelog
于是乎改一下CMakeLists中的导出命令行,在EXPORTED_FUNCTIONS中加入_malloc_free

canvas像素RGBA四通道

在将前面所有坑都淌过一遍后,觉得自己离最终胜利只有0.1m的距离了,然而现实很残酷,调用算法后的效果图明显不是那么回事!于是乎,不得不从数据对比上下手,将web端和C++算法里的数据取间隔打印,然后终于发现问题点了!

从canvas获取的像素数据是RGBA,而算法中接收时使用CV_8UC3创建cv::Mat对象(这不是RGB么)
最终方案:在算法中进行处理,保证算法处理完图像指针的内容是4通道!

经验&&教训

  1. 官网上都是解决方案,耐心看
  2. 刚学习某方面的知识,可以去github上找demo
  3. 跟踪问题时,先从大的方面定位,然后逐步缩小范围
  4. 尝试在源码github的issue中寻找解决方案
  5. stackoverflow多看跟帖,必然有很多大佬回复

参考

一些有用的学习文档
WebAssembly
Emscripten-FAQ
emscripten-core github issues
C/C++面向WebAssembly编程

最后在吐槽一句,emscripten的知识真少啊~~~~ WebAssembly高级用法待后续探索,TBC~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/744929.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言——详解字符函数和字符串函数(一)

Hi,铁子们好呀&#xff01;今天博主来给大家更一篇C语言的字符函数和字符串函数~ 具体讲的内容如下&#xff1a; 文章目录 &#x1f386;1.字符分类函数&#x1f4af;&#x1f4af;⏩1.1 什么是字符分类函数的&#xff1f;&#x1f4af;&#x1f4af;⏩1.2 字符函数的类型有哪…

基于Python的中医药知识问答系统设计与实现

[简介] 这篇文章主要介绍了基于Python的中医药知识问答系统的设计与实现。该系统利用Python编程语言&#xff0c;结合中医药领域的知识和技术&#xff0c;实现了一个功能强大的问答系统。文章首先介绍了中医药知识的特点和传统问答系统的局限性&#xff0c;然后提出了设计思路…

【Java探索之旅】运算符解析 算术运算符,关系运算符

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; Java编程秘籍 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1;前言一、什么是运算符二、算术运算符2.1 基本四则运算&#xff08;-*/%&#xff09;2.2 增…

ThreadLocal基本原理

ThreadLocal基本原理 一、定义 ThreadLocal是java中所提供的线程本地存储机制&#xff0c;可以利用改机制将数据缓存在线程内部&#xff0c;该线程可以在任意时刻、任意方法中获取数据 二、底层原理 ThreadLocal底层是通过ThreadLocalMap来实现的&#xff0c;每个Thread对象中…

Java代码基础算法练习---2024.3.14

其实这就是从我学校的资源&#xff0c;都比较基础的算法题&#xff0c;先尽量每天都做1-2题&#xff0c;练手感。毕竟离我真正去尝试入职好的公司&#xff08;我指的就是中大厂&#xff0c;但是任重道远啊&#xff09;&#xff0c;仍有一定的时间&#xff0c;至少要等我升本之后…

安装nginx

Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器&#xff0c;特点是占有内存少&#xff0c;并发能力强&#xff0c;事实上nginx的并发能力确实在同类型的网页服务器中表现较好&#xff0c;中国大陆使用nginx网站用户有&#xff1a;百度、京东、新浪、网易、腾…

Sui技术帮助Studio Mirai成功实现创意愿景

Brian和Ben Li兄弟对艺术充满热情&#xff0c;通过共同创立的研发工作室Studio Mirai&#xff0c;他们正在探索Web3技术与创意产业的交集。 Studio Mirai的第一个头像类项目&#xff08;profile picture&#xff0c;PFP&#xff09;Tamashi存在于Nozomi World中&#xff0c;这…

备战蓝桥杯Day25 - 二叉搜索树

一、基本概念 二叉搜索树&#xff08;Binary Search Tree&#xff09;&#xff0c;又称为二叉查找树或二叉排序树&#xff0c;是一种具有特定性质的二叉树。 定义&#xff1a;二叉搜索树可以是一棵空树&#xff0c;也可以是具有以下特性的非空二叉树&#xff1a; 若其左子树不…

【Memcached】

memcached 有一个很大的缺陷不能持久化&#xff0c;不能存储在硬盘里 1.NoSQL介绍 NoSQL是对 Not Only SQL、非传统关系型数据库的统称。 NoSQL一词诞生于1998年&#xff0c;2009年这个词汇被再次提出指非关系型、分布式、不提供ACID的数据库设计模式。 随着互联网时代的到…

基于springboot+vue实现电子商务平台管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现电子商务平台管理系统演示 研究的目的和意义 据我国IT行业发布的报告表明&#xff0c;近年来&#xff0c;我国互联网发展呈快速增长趋势&#xff0c;网民的数量已达8700万&#xff0c;逼近世界第一&#xff0c;并且随着宽带的实施及降价&#xff0c;每天约有…

Day63:WEB攻防-JS应用算法逆向三重断点调试调用堆栈BP插件发包安全结合

目录 前置知识 JS调试分析 JS分析调试结合Burp JS分析调试知识点&#xff1a; 1、JavaScript-作用域&调用堆栈 2、JavaScript-断点调试&全局搜索 3、JavaScript-Burp算法模块使用 前置知识 JS加密数据走向 浏览器调试 1、作用域&#xff1a;&#xff08;本地&全…

代码随想录算法训练营第四十七天|动态规划|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 文章 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代…

决策树 | 分裂算法:ID3,C4.5,CART

这里写目录标题 一. ID3算法1. 信息增益2. ID3算法特点 二. C4.5算法1. 信息增益率2. C4.5算法特点 三. CART算法1. Gini系数公式2. CART算法特点3. CART回归树的分裂评价指标 小节 在决策树算法逻辑篇中&#xff0c;我们讲解了决策树的构建方式&#xff0c;下面我们来聊一聊决…

Day16 面向对象进阶——接Day15

Day16 面向对象进阶——接Day15 文章目录 Day16 面向对象进阶——接Day15一、抽象类及抽象方法二、接口三、多态四、对象转型五、内部类 一、抽象类及抽象方法 //抽象类 public abstract class 类名{//抽象方法public abstract void method(); }1、抽象方法交给非抽象的子类去…

FreeRtos自学笔记4----参考正点原子视频

静态创建任务函数 TaskHandle_t xTaskCreateStatic { TaskFunction_t pxTaskCode, /* 指向任务函数的指针 / const char * const pcName, / 任务函数名 / const uint32_t ulStackDepth, / 任务堆栈大小注意字为单位 / void * const pvParameters, / 传递的任务函数参数 / UBase…

爬虫需要什么类型的代理ip?代理ip是必备的吗?

在信息时代&#xff0c;网络爬虫作为一种重要的数据采集工具&#xff0c;被广泛应用于各行各业。在这个过程中&#xff0c;代理IP成为了一个备受关注的话题。那么&#xff0c;爬虫需要什么类型的代理IP?代理IP是否是必不可少的呢? 今天我们就一起来看看~ 首先&#xff0c;我…

GPU服务器为什么需要DPU?

随着AI模型的复杂度增加以及数据量爆炸性增长&#xff0c;GPU服务器在执行训练和推理任务时&#xff0c;不仅面临计算密集型问题&#xff0c;还必须处理大量的数据移动、网络通信、存储I/O以及安全防护等非计算密集型任务。这些问题往往会成为性能瓶颈&#xff0c;消耗宝贵的CP…

【教学类-34-11】20240314 动物拼图(Midjounery生成线描图,8*8格拼图块 A4整张)(AI对话大师)

作品展示&#xff1a;——A4整页&#xff08;一人2张纸&#xff09; 背景需求&#xff1a; 通过春天拼图的个别化实验&#xff0c;我发现&#xff1a; 【教学类-34-10】20240313 春天拼图&#xff08;Midjounery生成线描图&#xff0c;4*4格拼图块&#xff09;&#xff08;AI…

在Docker上传我们自己的镜像(以springboot项目为例)

首先确定好在我们的centOS服务器上已经安装并配置好docker 配置自己的springboot镜像并运行 获取springboot的jar包 maven clean--》mavenue package --》复制target目录下生成的jar包 在服务器选择一个文件夹上传jar包&#xff0c;我这里选用的文件夹叫做/opt/dockertest…

【数据结构】树与堆 (向上/下调整算法和复杂度的分析、堆排序以及topk问题)

文章目录 1.树的概念1.1树的相关概念1.2树的表示 2.二叉树2.1概念2.2特殊二叉树2.3二叉树的存储 3.堆3.1堆的插入&#xff08;向上调整&#xff09;3.2堆的删除&#xff08;向下调整&#xff09;3.3堆的创建3.3.1使用向上调整3.3.2使用向下调整3.3.3两种建堆方式的比较 3.4堆排…