上海市网站建设公叿,目前流行的app网站开发模式,关键词百度云,网站改版 优化文章目录 开发环境工程目录CMakeLists.txtmain.cpp web端index.html效果图 遇到的问题JS与C传值Uncaught TypeError: Module._malloc is not a functioncanvas像素RGBA四通道 经验教训参考 最近因为项目原因#xff0c;研究了一下WebAssembly。2015年上线与JS、HTML… 文章目录 开发环境工程目录CMakeLists.txtmain.cpp web端index.html效果图 遇到的问题JS与C传值Uncaught TypeError: Module._malloc is not a functioncanvas像素RGBA四通道 经验教训参考 最近因为项目原因研究了一下WebAssembly。2015年上线与JS、HTML、CSS并称web界四语言额虽然已经上线快10年但是研究的人好少注定这个探索之路是崎岖的。事实也是这样已经耗进去快2周了人都麻了-_-|| 这篇文章主要介绍在引用图像增强算法时遇到的一些问题因涉及算法内容以下代码将做一些处理。。。javaer表示知识的海洋真广阔呀~ 开发环境
为啥要把开发环境放在第一位呢这里面也是采了无数的坑。
开发工具版本Ubuntu18.04emscripten3.1.55cmake3.28.3opencv3.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_RUNTIME1 -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.hextern 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.begincv::Vec4b(), end mat.endcv::Vec4b(); it ! end; it) {(*it)[2] 0; // 红色通道置零(*it)[1] 0; // 绿色通道置零}
}web端
使用emcccmake执行编译将生成后的js和wasm文件拷贝至web项目中web项目结构如下
┌─web 项目名称
│─imageAlgorithm.js
│ imageAlgorithm.wasm
│ index.htmlindex.html
主要变量的说明
canvas1为原图图片数据imageDatacanvas2为经过算法处理后的图图片数据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通道 经验教训
官网上都是解决方案耐心看刚学习某方面的知识可以去github上找demo跟踪问题时先从大的方面定位然后逐步缩小范围尝试在源码github的issue中寻找解决方案stackoverflow多看跟帖必然有很多大佬回复
参考
一些有用的学习文档 WebAssembly Emscripten-FAQ emscripten-core github issues C/C面向WebAssembly编程
最后在吐槽一句emscripten的知识真少啊~~~~ WebAssembly高级用法待后续探索TBC~