使用 Chaquopy 在 Android 上将字节数组从 java 传递到 python

Passing a byte array from java to python on Android using Chaquopy

我是 运行 一个 android 相机应用程序,我想在 Python 中进行图像处理。为了对此进行测试,我想将单个图像帧传递给 python 函数,使用整数除法将所有值除以 2,然后 return 结果。

为此,我有以下代码:

在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 秒。关于加快速度的任何指示?

谢谢!

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

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[],您将找到有关 signed/unsigned 转换如何工作的确切细节,但尝试两者并查看哪一个给出答案可能更容易期待。)