I am using a trained Tensorflow model in Java on Android. I am trying to extract the output of an intermediary op.
The Tensor I am extracting has shape (150, 150, 256).
I have declared the output target to be
private float[] hybridValues;
hybridValues = new float[150 * 150 * 256];
I am then getting the output using.
inferenceInterface.fetch(OUTPUT_NODE, hybridValues);
The values are fine but they are stored as a 1D array. Is there a way to get inferenceinterface.fetch to return a multi-dimentional array?
I tried declaring hybridValue to be a three dimensional float array but that doesn't work as the fetch method expects a 1D array.
The end goal is to pass my output to a Python program that will feed the values to a Tensor of the same shape (150, 150, 256).
For comparison the Python a_output = graph.get_tensor_by_name('a2b_generator/Conv_7/Relu:0')
returns an ndarray with values in the same shape as the target tensor.
I'm using tensorflow with java on the desktop (which might be different) and all I do is create a multi-dimensional array with the correct size, then copy the values over, e.g. Tensor.copyTo(Object dst)
Related
I am working with opencv on android for the development of an image segmentation application, but specifically with the watershed algorithm. I'm opening the image and creating a mask with the same size as the image and passing 0 for all the rows and columns of that mask. However, in the following step, which is to add new values for certain rows and columns of this matrix, I have the error: No get method providing array access
With that, I am not able to pass the new values to the matrix, can someone help me with this?
COde:
// Load the image
val srcOriginal = Imgcodecs.imread(currentPhotoPath)
// Create a blank image of zeros (same dimension as img)
val markers = Mat.zeros(srcOriginal.rows(), srcOriginal.cols(), CvType.CV_32F)
// Example assigning a new value to a matrix index
markers.put(0,0,255)
Error:
OpenCV library in java doesn't take input Int as a parameter. You can see in the method declaration https://docs.opencv.org/3.4/javadoc/org/opencv/core/Mat.html#get(int,int,int%5B%5D).
Pass an IntArray for RGB values along with row and col values:
// Replace row and col with your values
markers.put(row, col, intArrayOf(0,0,255))
try this:
markers.put(0,0,X);
where x is array containing pixel vales (because it may be RGB,GRAY SCALE,etc)
In Java you can use Mat::get() and Mat::put() methods.
Read this for more details.
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.
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.
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?
It is SLOW. it takes about 90 seconds to compute this operation over 12 million values. Any pointers on speeding this up?
Thanks!
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.)
I am having trouble with an assignment of mine. I have a class which reads in PGM image files.
I need to create a few classes, the main one being a compression class. I need to compress the PGM (represented by 2D arrays) into a 1D array.
Here are the instructions:
public static short[] compress(short[][])
Is passed a 2D array of shorts which represents an image.
Returns the compressed image as a 1D array of shorts.
That method is my main concern.
Compression idea:
look for horizontal or vertical runs of like pixel values and record the number of times the
pixel value repeated itself.
note by Spektre: this is called RLE run length encoding used by PCX for example
algorithm:
1.Compute the compressed image array using horizontal runs
2.Compute the compressed image array using vertical runs
3.Choose to compress the image uses the best technique for this particular image.
4.Set the Header of image
Set the first and second values of your short [ ] result array to the width and height values.
Set the third value in your short[ ] result array to 1 for horizontal or 2 for vertical compression.
5.Set the image body
The rest of the short [ ] result array is filled with the RLE quantity and value
There are also a few other methods
if anyone wants to help with them:
public static void write(short[], String)
Is passed a 1D array of shorts which represents the compressed image and a desired filename.
Simply write the values to a text file with a .compressed extension added to the filename.
public static short[] read(String)
Is passed a compressed image filename.
Simply reads the values and returns them in a 1D array of shorts.
public static short[][] decompress(short[])
Is passed a 1D array of shorts which represents a compressed image.
Simply decompress the file so that we can display it on the screen
using our showGrayImage( ) code that we already have.
Thanks in advance!
I want to define a grid in which I specify an (x,y) coordinate for each point in the grid. So I want to do something like this:
int [][] pt;
for (x=0; x<numX; x=x+1) {
for (y=0; y<numY; y=y+1) {
pt[x][y] = {xval, yval};
}
}
The reason why is because I am mapping the values of an orderly grid to a disorderly grid. The above code of course causes an exception (unexpected token "{").
What is the best way to do what I'm trying to do? Thanks.
Two things:
You havent initialized your array (maybe you did just didnt put in code)
You are trying to put two values into a place where only one can be held.
Initialize your array like this (if you didnt)
int[][] pt = new int[numX][numY];
To store both values in the array you will need to use an object. The java Point class would be an example of something you could use
Point[][] pt = new Point[numX][numY];
for (x=0; x<numX; x=x+1) {
for (y=0; y<numY; y=y+1) {
pt[x][y] = new Point(xval, yval);;
}
}
You basically want to store a fixed number of values inside every array cell?
Then you are limited with 2 major cases:
Use an object
Java doesn't have user defined value types, so you are forced to use full-blown objects on the heap (with little hope that JVM will be very clever and optimize it, but chances are near zero), be it an array, or any other class.
If both of your values are less than 64 bits, you can pack them in built-in primitive type (such as long) using bitwise arithmetic. (You must be very careful here)
ints are 32 bit, so you can pack 2 ints in 1 long.
pt[x][y] = {xval, yval} is illegal, pt[][] is a double dimensional array. It only can store one value. Just like this pt[x][y] = value
You may try java map.
I'm quite new to MATLAB programming and I ran into some trouble:
I want to call a dSPACE MLIB libriary function. According to their samples, it requires a string array as argument:
variables = {'Model Root/Spring-Mass-Damper System/Out1';...
'Model Root/Signal\nGenerator/Out1'};
libFunction(variables);
This variables is passed to the function. My problem is now: I have a frontend application where the user can choose from an arbitary number of strings which should be passed to the matlab function. Since the frontend is writtten in Java, the type of the incoming data is java.lang.String[].
How can I convert an array of java strings to something with the same type as the sample variable above (I think it is a cell array of cell arrays or sth like that).
Thanks in advance!
Take a look at the documentation. MATLAB makes it very easy to convert to and from Java types.
Handling data returned from Java
Dealing with Java arrays
You can convert an array of Java strings to either a cell or char array in MATLAB. Using cell arrays can work even with jagged arrays (which are permitted in Java).
Here are two simple examples:
%# Preparing a java.lang.String[] to play with.
a = javaArray('java.lang.String',10);
b = {'I','am','the','very','model','of','a','modern','major','general'};
for i=1:10; a(i) = java.lang.String(b{i}); end;
%# To cell array of strings. Simple, eh?
c = cell(a);
%# To char array. Also simple.
c = char(a);