使用 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()
这段代码有几个问题。
它没有按预期运行 - 位置 33 的值不是一半。我可能混淆了字节值,但我不确定到底发生了什么。没有 "tobytes" 并使用 python 列表而不是 numpy 数组的相同代码确实按预期工作。
传递参数 - 不确定幕后发生了什么。是按值传递还是按引用传递?是复制数组,还是传递指针?
速度很慢。计算超过 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.int8
或 dtype=np.uint8
来明确指定数据类型。 (如果您在 Chaquopy documentation 中搜索 byte[]
,您将找到有关 signed/unsigned 转换如何工作的确切细节,但尝试两者并查看哪一个给出答案可能更容易期待。)
我是 运行 一个 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()
这段代码有几个问题。
它没有按预期运行 - 位置 33 的值不是一半。我可能混淆了字节值,但我不确定到底发生了什么。没有 "tobytes" 并使用 python 列表而不是 numpy 数组的相同代码确实按预期工作。
传递参数 - 不确定幕后发生了什么。是按值传递还是按引用传递?是复制数组,还是传递指针?
速度很慢。计算超过 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.int8
或 dtype=np.uint8
来明确指定数据类型。 (如果您在 Chaquopy documentation 中搜索 byte[]
,您将找到有关 signed/unsigned 转换如何工作的确切细节,但尝试两者并查看哪一个给出答案可能更容易期待。)