news 2026/4/29 14:34:31

鸿蒙开发-如何将C++侧接收的PixelMap转换成cv::mat格式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙开发-如何将C++侧接收的PixelMap转换成cv::mat格式

目录

  • 1. 解决措施
  • 2. 示例代码
  • 3. 将arraybuffer转换成cv::mat
  • 4. 使用OH_PixelMap_AccessPixels获取PixelMap的内存地址,将这个内存地址中的数据转换为cv::mat的

1. 解决措施

将PixelMap转换成cv::mat有两种方法:

  • 将PixelMap的arraybuffer转换成cv::mat。
  • 使用OH_PixelMap_AccessPixels获取PixelMap的内存地址,将这个内存地址中的数据转换为cv::mat。

上述两种方法都需确保PixelMap的格式与OpenCV中Mat的格式一致,否则会导致色彩偏差。

2. 示例代码

importcPixelMapToMatfrom'libcpixelmaptomat.so';import{BusinessError}from'@kit.BasicServicesKit';import{image}from'@kit.ImageKit';@Entry @Component struct Index{@State pixelMap:image.PixelMap|undefined=undefinedasyncarrayBufferToMat(){if(this.pixelMap==undefined||this.pixelMap){letcontext=this.getUIContext().getHostContext()ascommon.UIAbilityContext;letresourceManager=context.resourceManagerletimageArray=awaitresourceManager.getMediaContent($r('app.media.sample10'));letpixelBuffer=newUint8Array(imageArray).bufferasObjectasArrayBuffer console.info("pixelBuffer length: "+pixelBuffer.byteLength);letimageResource=image.createImageSource(pixelBuffer);letopts:image.DecodingOptions={editable:true,desiredPixelFormat:image.PixelMapFormat.RGBA_8888}this.pixelMap=awaitimageResource.createPixelMap(opts);}constreadBuffer:ArrayBuffer=newArrayBuffer(this.pixelMap.getPixelBytesNumber());// Obtain the array buffer of the pixelmapconsole.info("readBuffer length: "+readBuffer.byteLength);this.pixelMap.readPixelsToBuffer(readBuffer).then(()=>{console.info("No Error!")}).catch((err:BusinessError)=>{console.error("Error! "+err.message)})constdir=getContext(this).filesDir;console.info('save path: '+dir);cPixelMapToMat.arrayBufferToMat(this.pixelMap,readBuffer,dir);}asyncaccessToMat(){if(this.pixelMap==undefined||this.pixelMap){letresourceManager=getContext(this).resourceManagerletimageArray=awaitresourceManager.getMediaContent($r('app.media.sample14'));letpixelBuffer=newUint8Array(imageArray).bufferasObjectasArrayBuffer console.info("pixelBuffer length: "+pixelBuffer.byteLength);letimageResource=image.createImageSource(pixelBuffer);letopts:image.DecodingOptions={editable:true,desiredPixelFormat:image.PixelMapFormat.RGBA_8888}this.pixelMap=awaitimageResource.createPixelMap(opts);}constdir=getContext(this).filesDir;console.info('save path: '+dir);cPixelMapToMat.accessToMat(this.pixelMap,dir);}build(){Row(){Column(){Image(this.pixelMap).width(200).height(200)Button('ArrayBufferToMat').onClick(()=>{this.arrayBufferToMat();})Button('AccessToMat').onClick(()=>{this.accessToMat();})}.width('100%')}.height('100%')}}

3. 将arraybuffer转换成cv::mat

#include"napi/native_api.h"#include<multimedia/image_framework/image_mdk.h>#include<multimedia/image_framework/image_mdk_common.h>#include<multimedia/image_framework/image_pixel_map_mdk.h>#include<multimedia/image_framework/image_pixel_map_napi.h>#include"hilog/log.h"#include<opencv2/opencv.hpp>#include<bits/alltypes.h>staticnapi_valueArrayBufferToMat(napi_env env,napi_callback_info info){size_t argc=3;napi_value args[3]={nullptr};napi_get_cb_info(env,info,&argc,args,nullptr,nullptr);napi_value error;napi_create_int32(env,-1,&error);// Initialize PixelMap object dataNativePixelMap*native=OH_PixelMap_InitNativePixelMap(env,args[0]);if(native==nullptr){returnerror;}// Obtaining Image InformationstructOhosPixelMapInfospixelMapInfos;if(OH_PixelMap_GetImageInfo(native,&pixelMapInfos)!=IMAGE_RESULT_SUCCESS){OH_LOG_Print(LOG_APP,LOG_ERROR,0xFF00,"Test","Pure : -1");returnerror;}// Obtains the buffernapi_value buffer=args[1];napi_valuetype valueType;napi_typeof(env,buffer,&valueType);if(valueType==napi_object){boolisArrayBuffer=false;napi_is_arraybuffer(env,buffer,&isArrayBuffer);if(!isArrayBuffer){napi_throw_error(env,"EINVAL","Error");}}void*data=nullptr;size_t byteLength=0;napi_get_arraybuffer_info(env,buffer,&data,&byteLength);int32_t*saveBuffer=(int32_t*)(data);// Convert to Matcv::MatoriginMat(pixelMapInfos.height,pixelMapInfos.width,CV_8UC4,saveBuffer);if(!originMat.data){OH_LOG_Print(LOG_APP,LOG_ERROR,0xFF00,"Read Image","Pure : -1");returnerror;}// openCV defaults to BGRA or BGR. If the pixelmap is not created in one of these formats, a format conversion is requiredcv::Mat saveMat;cv::cvtColor(originMat,saveMat,cv::COLOR_BGRA2RGBA);charpathArray[1024];size_t length;napi_get_value_string_utf8(env,args[2],pathArray,1024,&length);std::stringpath(pathArray);path+="/buffer.jpg";if(!cv::imwrite(path,saveMat)){OH_LOG_Print(LOG_APP,LOG_ERROR,0xFF00,"Write Image","Pure : -1");returnerror;}napi_value res;napi_create_int32(env,1,&res);returnres;}

4. 使用OH_PixelMap_AccessPixels获取PixelMap的内存地址,将这个内存地址中的数据转换为cv::mat的

staticnapi_valueAccessToMat(napi_env env,napi_callback_info info){size_t argc=2;napi_value args[2]={nullptr};napi_get_cb_info(env,info,&argc,args,nullptr,nullptr);napi_value error;napi_create_int32(env,-1,&error);NativePixelMap*native=OH_PixelMap_InitNativePixelMap(env,args[0]);if(native==nullptr){returnerror;}structOhosPixelMapInfospixelMapInfos;if(OH_PixelMap_GetImageInfo(native,&pixelMapInfos)!=IMAGE_RESULT_SUCCESS){OH_LOG_Print(LOG_APP,LOG_ERROR,0xFF00,"Test","Pure : -1");returnerror;}void*pixel;// Obtain the memory address of the NativePixelMap object and lock the memoryOH_PixelMap_AccessPixels(native,&pixel);// Convert to Mat, pay attention to alignment, so rowSize needs to be passed incv::MatoriginMat(pixelMapInfos.height,pixelMapInfos.width,CV_8UC4,pixel,pixelMapInfos.rowSize);if(!originMat.data){OH_LOG_Print(LOG_APP,LOG_ERROR,0xFF00,"Read Image","Pure : -1");returnerror;}// openCV defaults to BGRA or BGR. If the pixelmap is not created in one of these formats, a format conversion is requiredcv::Mat saveMat;cv::cvtColor(originMat,saveMat,cv::COLOR_BGRA2RGBA);charpathArray[1024];size_t length;napi_get_value_string_utf8(env,args[1],pathArray,1024,&length);std::stringpath(pathArray);path+="/access.jpg";if(!cv::imwrite(path,saveMat)){OH_LOG_Print(LOG_APP,LOG_ERROR,0xFF00,"Write Image","Pure : -1");returnerror;}napi_value res;napi_create_int32(env,1,&res);returnres;}

在HarmonyOS开发中,针对图库支持硬解码的操作,需要指定图像的内存空间大小。OH_PixelMap_AccessPixels() 获取图片的内存地址并锁定该内存。实际图像的大小需要按 lineStride 对齐。因此,在构造成 mat 时,需指定 lineStride 对齐。lineStride即 rowSize。可以使用 OH_GetImageInfo 获取 imageInfo,其中包含 width、height 和 rowSize 等信息。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/19 4:19:33

Wan2.2-T2V-A14B:16倍压缩与双专家架构突破

Wan2.2-T2V-A14B&#xff1a;16倍压缩与双专家架构突破 你是否曾因视频生成模型的“三高”门槛而望而却步&#xff1f;——高参数量&#xff08;百亿级起步&#xff09;、高显存消耗&#xff08;>20GB&#xff09;、高推理延迟&#xff08;分钟级输出&#xff09;。如今&…

作者头像 李华
网站建设 2026/4/25 7:39:17

Thread类中run()和start()的区别

在Java中, run() 和 start() 方法是Thread类的两个关键方法&#xff0c;它们有本质区别&#xff1a;1.run()方法&#xff1a;run()方法是线程要执行的任务代码所在的方法。直接调用run()方法&#xff0c;它会在当前线程中执行&#xff0c;而不会启动新的线程。也就是说&#xf…

作者头像 李华
网站建设 2026/4/17 12:29:43

InstantX/FLUX.1-dev-IP-Adapter 效果实测

InstantX/FLUX.1-dev-IP-Adapter 效果实测 在生成式 AI 领域&#xff0c;我们正经历一场从“文生图”到“以图塑意、以文点睛”的深刻转变。过去&#xff0c;文本提示是图像生成的唯一指挥棒&#xff1b;如今&#xff0c;像 InstantX/FLUX.1-dev-IP-Adapter 这样的技术组合&am…

作者头像 李华
网站建设 2026/4/29 12:02:05

LobeChat能否合作高校?产学研结合新模式

LobeChat能否合作高校&#xff1f;产学研结合新模式 在人工智能技术加速渗透教育领域的今天&#xff0c;越来越多的高校开始探索如何将大语言模型&#xff08;LLM&#xff09;融入教学与科研。然而&#xff0c;一个现实问题摆在面前&#xff1a;主流闭源AI服务虽然功能强大&…

作者头像 李华
网站建设 2026/4/25 1:07:46

Windows部署GPT-SoVITS语音克隆与远程访问

Windows部署GPT-SoVITS语音克隆与远程访问 在内容创作日益个性化的今天&#xff0c;越来越多的创作者开始尝试用AI生成专属声音——无论是为短视频配音、制作有声书&#xff0c;还是打造虚拟主播形象。而在这股“声音定制”热潮中&#xff0c;GPT-SoVITS 凭借其极低的数据门槛和…

作者头像 李华
网站建设 2026/4/28 14:54:41

Playwright元素定位详解:8种定位策略实战指南

想象一下这样的场景&#xff1a;你正在编写一个自动化测试脚本&#xff0c;需要测试电商网站的购物流程。脚本运行得很顺利&#xff0c;直到某个元素突然无法定位——可能是因为开发人员修改了按钮的ID&#xff0c;或者页面结构发生了变化。这时&#xff0c;你会深刻体会到选择…

作者头像 李华