1

I'm running an android camera app and I would like to do the image processing in Python. To test this, I want to pass a single image frame to a python function, divide all values by 2 using integer division and return the result.

For that end, I have the following code:

in 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");

    }

In python, I have the following:

import numpy as np

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

I have several issues with this code.

  1. It does not behave as expected - the value at location 33 is not half. I probably have a mix-up with the byte values, but I'm not sure what's going on exactly. The same code without "tobytes" and using a python list rather than a numpy array does work as expected.

  2. Passing parameters - not sure what happens under the hood. Is it pass by value or by reference? Is the array being copied, or just a pointer being passed around?

  3. It is SLOW. it takes about 90 seconds to compute this operation over 12 million values. Any pointers on speeding this up?

Thanks!

1 Answer 1

3

Your last two questions are related, so I'll answer them together.

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

This passes by reference: the Python code receives a jarray object which accesses the original array.

np.array(o)

As of Chaquopy 8.x, this is a direct memory copy when o is a Java primitive array, so performance shouldn't be a problem. On older versions of Chaquopy, you can avoid a slow element-by-element copy by converting to a Python bytes object first, which can be done in either language:

  • In Java: PyObject array1 = py.getBuiltins().callAttr("bytes", bytes)
  • Or in Python: np.array(bytes(o))
b.tobytes()
toJava(byte[].class)

Both of these expressions will also make a copy, but they will also be direct memory copies, so performance shouldn't be a problem.

As for it returning the wrong answer, I think that's probably because NumPy is using its default data type of float64. When calling np.array, you should specify the data type explicitly by passing dtype=np.int8 or dtype=np.uint8. (If you search for byte[] in the Chaquopy documentation you'll find the exact details of how signed/unsigned conversion works, but it's probably easier just to try both and see which one gives the answer you expect.)

Sign up to request clarification or add additional context in comments.

3 Comments

A small follow up - python's bytes(o) requires o to be an iterable such that every member is between 0 and 255. However, java's byte is signed. passing a java byte [] to python's bytes() results in a ValueError. any idea how to cast one to the other?
As documented, if o is a Java array, then Java values -128 to -1 should be mapped to Python values 128 to 255. Here are some examples of that in the unit tests.
If you still can't work it out, please edit your question to include the ValueError message and the relevant part of the stack trace and the code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.