【问题标题】:Passing a byte array from java to python on Android using Chaquopy使用 Chaquopy 在 Android 上将字节数组从 java 传递到 python
【发布时间】:2020-03-22 18:59:31
【问题描述】:

我正在运行一个安卓相机应用程序,我想用 Python 进行图像处理。为了测试这一点,我想将单个图像帧传递给 python 函数,使用整数除法将所有值除以 2 并返回结果。

为此,我有以下代码:

在 Java 中:

public void onCapturedImage(Image image)
    {

        Image.Plane[] tmp = image.getPlanes();
        byte[] bytes = null;
        ByteBuffer buffer = tmp[0].getBuffer();
        buffer.rewind();
        bytes = new byte[buffer.remaining()];
        buffer.get(bytes, 0, buffer.remaining());
        buffer.rewind();

        Log.d(TAG, "start python section");

        // assume python.start() is elsewhere

        Python py = Python.getInstance();
        PyObject array1 = PyObject.fromJava(bytes);
        Log.d(TAG, "get python module");
        PyObject py_module = py.getModule("mymod");
        Log.d(TAG, "call pic func");

        byte [] result  = py_module.callAttr("pic_func", array1).toJava(byte[].class);
        // compare the values at some random location to see make sure result is as expected
        Log.d(TAG, "Compare: "+Byte.toString(bytes[33]) + " and " + Byte.toString(result[33]));
        Log.d(TAG,"DONE");

    }

在 python 中,我有以下内容:

import numpy as np

def pic_func(o):
    a = np.array(o)
    b = a//2
    return b.tobytes()

我对这段代码有几个问题。

  1. 它的行为不符合预期 - 位置 33 处的值不是一半。我可能混淆了字节值,但我不确定到底发生了什么。没有“tobytes”并使用 python 列表而不是 numpy 数组的相同代码确实可以按预期工作。

  2. 传递参数 - 不确定幕后会发生什么。它是按值传递还是按引用传递?是数组被复制,还是只是一个指针被传递?

  3. 速度很慢。计算超过 1200 万个值的操作大约需要 90 秒。有什么加快速度的建议吗?

谢谢!

【问题讨论】:

    标签: java python android chaquopy


    【解决方案1】:

    你的最后两个问题是相关的,所以我会一起回答。

    PyObject array1 = PyObject.fromJava(bytes)
    py_module.callAttr("pic_func", array1)
    

    这是通过引用传递的:Python 代码接收到一个访问原始数组的jarray 对象。

    np.array(o)
    

    从 Chaquopy 8.x 开始,当 o 是 Java 原始数组时,这是一个直接内存副本,因此性能应该不是问题。在旧版本的 Chaquopy 上,您可以通过首先转换为 Python bytes 对象来避免缓慢的逐个元素复制,这可以用任何一种语言完成:

    • 在 Java 中:PyObject array1 = py.getBuiltins().callAttr("bytes", bytes)
    • 或者在 Python 中:np.array(bytes(o))
    b.tobytes()
    toJava(byte[].class)
    

    这两个表达式也会创建一个副本,但它们也将是直接内存副本,因此性能应该不是问题。

    至于它返回错误的答案,我认为这可能是因为 NumPy 使用其默认数据类型float64。调用np.array 时,应通过传递dtype=np.int8dtype=np.uint8 显式指定数据类型。 (如果您在 Chaquopy documentation 中搜索 byte[],您将找到有关有符号/无符号转换如何工作的确切详细信息,但尝试两者并查看哪一个给出您期望的答案可能更容易。)

    【讨论】:

    • 一个小的跟进 - python 的 bytes(o) 要求 o 是一个可迭代的,这样每个成员都在 0 到 255 之间。但是,java 的字节是有符号的。将 java byte [] 传递给 python 的 bytes() 会导致 ValueError。知道如何将一个转换为另一个吗?
    • As documented,如果o是一个Java数组,那么Java值-128到-1应该映射到Python值128到255。Here是单元中的一些例子测试。
    • 如果您仍然无法解决,请编辑您的问题以包含 ValueError 消息以及堆栈跟踪和代码的相关部分。
    猜你喜欢
    • 1970-01-01
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 2012-03-20
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多