chaquo / chaquopy

Chaquopy: the Python SDK for Android
https://chaquo.com/chaquopy/
MIT License
807 stars 132 forks source link

How to return multipe values from python? #1125

Closed aijim closed 6 months ago

aijim commented 6 months ago

Hi, I'm trying to run a python project on android. The python function returns three values, (crops, detections, confidences). crops is a list of numpy array, detections is a list of self-defined type of namedtuple, confidences is a list of numpy array. What is a best practice to return mulpile values with difference types?

I tried to call the python function as follow and convert the return value to list, but I had a syntax error.

val barcodePostProcessor = module.callAttr("BarcodePostProcessor")
List<PyObject> result = barcodePostProcessor.callAttr("kotlin_call",image,inference_map,1.0).toList()

When I replace Listwith val, the error is gone. But I don't know what's the type of returned value. In python function I returned two numpy array to bytes. But in following code I can't call toJava() on crops and confidences. I'm new to android. I can't figure out what's the problem. Please help.

val barcodePostProcessor = module.callAttr("BarcodePostProcessor")
val result = barcodePostProcessor.callAttr("kotlin_call",image,inference_map,1.0).toList()
val crops = result[0]
val confidences = result[1]
println(crops)
>>>
(__add__, <method-wrapper '__add__' of tuple object at 0x7d198962c480>)
mhsmith commented 6 months ago

toList is a generic Kotlin function – the correct PyObject method here is [asList](https://chaquo.com/chaquopy/doc/current/java/com/chaquo/python/PyObject.html#asList()). Each element in the list will then be returned as a PyObject.

You could then call asList on each element, followed by one of the PyObject conversion methods. For example, if each element of crops is a 1-dimensional NumPy array of integers, you could do this:

val crops = result[0]
val crops0 = crops.asList()[0]
for (x in crops0.asList()) {
    println(x.toInt())
}

Or you could convert the whole NumPy array into a Java array at once:

crops0.toJava(IntArray::class.java)

Converting the whole array at once will be faster, especially if the data type matches exactly (e.g. a Java int corresponds to a NumPy int32). But for small arrays, you probably won't notice the difference.

aijim commented 6 months ago

Thank you very much!