HarmonyOS NDK 中的 opencv cv::mat 格式数据如何转?

HarmonyOS NDK 中的 opencv cv::mat 格式数据如何转为 ArkTS 正确解析的 pixelMap 图片数据?在分割模型算法中,推断的结果数据,通过 opencv 处理后得到一个 cv::mat 格式的数据,如何将该数据转为HarmonyOS平台的图片格式的数据?

阅读 791
avatarAI BotBETA

在HarmonyOS中,如果你正在使用OpenCV库处理图像数据,并希望将这些cv::Mat格式的数据转换为ArkTS(一种HarmonyOS的UI框架,支持声明式UI开发)能够解析的PixelMap格式,你可以通过以下步骤来实现:

步骤 1: 转换 cv::Mat 到标准的图像格式

首先,确保你的cv::Mat图像数据是以一个ArkTS支持的格式存储的(如RGBA, RGB等)。如果不是,你可能需要先转换颜色空间。

// 假设你的cv::Mat是BGR格式的,你可以转换它为RGBA
cv::Mat mat; // 你的原始cv::Mat图像
cv::cvtColor(mat, mat, cv::COLOR_BGR2RGBA);

步骤 2: 创建 PixelMap

在HarmonyOS中,PixelMap是处理图像数据的主要类。你需要根据cv::Mat的数据来创建一个PixelMap实例。由于HarmonyOS的API通常是Java或Kotlin(取决于你使用的ArkUI版本),这里假设你有一个JNI接口来从C++层传递数据到Java层。

在Java层(或Kotlin层),你可以这样创建PixelMap

import ohos.media.image.PixelMap;
import ohos.media.image.PixelMap.PixelFormat;

public PixelMap createPixelMapFromCvMat(byte[] data, int width, int height) {
    PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
    options.size(width, height);
    options.pixelFormat(PixelFormat.PIXEL_FORMAT_RGBA_8888); // 根据你的cv::Mat格式调整

    PixelMap pixelMap = PixelMap.create(options);
    if (pixelMap != null) {
        // 注意:这里的data必须是ByteBuffer或适当的类型,取决于API的具体实现
        // 这里仅作为示例,你可能需要调整以适应你的具体实现
        pixelMap.writePixels(data, 0, width, height, PixelFormat.PIXEL_FORMAT_RGBA_8888);
    }
    return pixelMap;
}

步骤 3: 从C++传递数据

在C++层,你需要将cv::Mat的数据转换为字节数组(byte[]),并调用Java层的函数。这通常通过JNI来完成:

extern "C" JNIEXPORT jobject JNICALL
Java_com_example_yourapp_YourClass_createPixelMapFromCvMat(JNIEnv* env, jobject thiz, jlong matAddr, jint width, jint height) {
    cv::Mat& mat = *(cv::Mat*)matAddr;
    // 将mat的数据转换为byte数组
    std::vector<uchar> buf;
    cv::imencode(".png", mat, buf, [](int* param, const uchar* _ptr, int bytes){
        // 这里不直接使用imencode,因为它返回压缩数据,而是直接操作mat的data
        // 实际上,你应该直接将mat.data复制到byte数组中
        // 注意:这里只是示例,实际转换需要根据你的mat格式和颜色空间来
        // 可能需要手动处理行对齐等问题
    }, 0);

    // 假设你有一个方法可以直接将byte数组传递给Java(这里省略了JNI的复杂部分)
    jclass cls = env->FindClass("com/example/yourapp/YourClass");
    jmethodID mid = env->GetStaticMethodID(cls, "createPixelMapFromCvMat", "([BII)Lohos/media/image/PixelMap;");
    jbyteArray byteArray = env->NewByteArray(buf.size());
    env->SetByteArrayRegion(byteArray, 0, buf.size(), reinterpret_cast<const jbyte*>(buf.data()));

    jobject pixelMap = env->CallStaticObjectMethod(cls, mid, byteArray, width, height);
    env->DeleteLocalRef(byteArray);
    return pixelMap;
}

注意:上面的C++代码示例中,使用cv::imencode来生成PNG数据是不正确的,因为这会压缩数据并且不直接适用于PixelMapwritePixels方法。你应该直接访问cv::Matdata成员,并将其内容(可能需要注意行对齐)复制到一个新的字节数组中,然后传递给Java层的createPixelMapFromCvMat方法。此外,JNI部分的实现可能需要根据你的具体环境和需求进行调整。

总结

cv::Mat转换为HarmonyOS的PixelMap通常涉及在C++层处理图像数据,并通过JNI或类似机制将其传递到Java/Kotlin层,在那里使用

2 个回答

napi接受及转换,可以参考NDK开发部分 https://developer.huawei.com/consumer/cn/doc/harmonyos-guides...

//JS和C++相互调用ArrayBuffer

//具体实现如下
//Native侧接受传入的 ArkTS Array

static napi_value TS2NAPI(napi_env env, napi_callback_info info)
{
// 获取TS层传来的参数
size_t argc = 1;
napi_value args;
napi_get_cb_info(env, info, &argc, &args, NULL, NULL);
napi_value input_array = args;

// 获取传入数组typedarray生成input_buffer
napi_typedarray_type type;// 数据类型
napi_value input_buffer;
size_t byte_offset;//数据偏移
size_t i, length;//数据字节大小
napi_get_typedarray_info(env, input_array, &type, &length, NULL, &input_buffer, &byte_offset);

// 获取数组数据z
void *data;
size_t byte_length;
napi_get_arraybuffer_info(env, input_buffer, &data, &byte_length);

if (type == napi_int32_array) {
int32_t *data_bytes = (int32_t *)(data);
for (i = 0; i < length/sizeof(int32_t); i++) {
OH_LOG_INFO(LOG_APP, "TS2NAPI: C++ %{public}d", *((int32_t *)(data_bytes) + i));
}
}
return NULL;
}


//TS侧 接收 Native侧返回的Array
// NAPI层 array 传到TS层
static napi_value NAPI2TS(napi_env env, napi_callback_info info)
{
// 数据个数
int num = 10;
// 创建output_buffer
napi_value output_buffer;
void *output_ptr = NULL;
napi_create_arraybuffer(env, num * sizeof(int32_t), &output_ptr, &output_buffer);

// output_array
napi_value output_array;
napi_create_typedarray(env, napi_int32_array, num, output_buffer, 0, &output_array);

// 给output_ptr、output_buffer赋值
int32_t * output_bytes = (int32_t *)output_ptr;
for (int32_t i = 0; i < num; i++) {
output_bytes[i] = i;
}

for (int32_t i = 0; i < num; i++) {
OH_LOG_INFO(LOG_APP, "NAPI2TS: C++ %{public}d", *((int32_t *)(output_ptr) + i));
}

return output_array;
}



//TS 获取 Native 层回调的Object 值
//Native 层创建Object,通过ArkTS 传入的callback,并将Object回调给ArkTS
//具体实现如下:

//ArkTS 侧调用如下
let da:Record<string, number> = testNapi.CallbackToArkTs((value:object)=>
{
let data:Record<string, number> = value as Record<string, number>;
console.info("修改前type: " + data["type"].toString())
console.info(JSON.stringify(value))
data["type"] += 10
return value;
});
console.info(JSON.stringify(da))

//C++ 侧接收ArkTS 传入的 callback
static bool Napi_AddPropertyInt32(napi_env env, napi_value obj, const char *key, int32_t value) {
napi_value key_napi = nullptr;
napi_status status = napi_create_string_utf8(env, key, NAPI_AUTO_LENGTH, &key_napi);

napi_value value_napi = nullptr;
status = napi_create_int32(env, value, &value_napi);
status = napi_set_property(env, obj, key_napi, value_napi);
return true;
}

static napi_value CallbackToArkTs(napi_env env, napi_callback_info info) {

// 获取ArkTS参数
size_t argc = 1;
napi_value js_cb = nullptr;
napi_get_cb_info(env, info, &argc, &js_cb, nullptr, nullptr);

// native回调到ts层的object
napi_value argv = nullptr;
napi_create_object(env, &argv);
Napi_AddPropertyInt32(env, argv, "type", 1);
Napi_AddPropertyInt32(env, argv, "index", 2);

// native回调到ts层
napi_value result = nullptr;
napi_call_function(env, NULL, js_cb, 1, &argv, &result);

// 获取ts修改后的object
napi_value typeNumber = nullptr;
napi_get_named_property(env, result, "type", &typeNumber);
int32_t number;
napi_get_value_int32(env, typeNumber, &number);
OH_LOG_INFO(LOG_APP, "修改后type: %{public}d", number);

// 返回修改后的object
return result;
}

你可以通过以下步骤将 OpenCV 的 cv::mat 格式数据转换为 HarmonyOS 的 PixelMap 图片数据,确保在 NDK 层已经正确处理了 cv::mat 数据,并且可以获取到图像的宽度、高度和像素数据。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
logo
HarmonyOS
子站问答
访问
宣传栏