Closed mengpengfei closed 2 years ago
@mengpengfei The forward pass should be identical between java and python. We share the same underlying C++ API.
If the results are different, most likely is because of preprocessing (in most case is resizing). Can you share your model, so we can test your code?
I can send my model to your email,but please do not public the model.Is it ok? if it is ok,please give me your email address.
Follwing is the test picture:
@frankfliu can you help me? thank you any way.
@mengpengfei we will try to compare your image processing first. I will ask for your model if needed. Most likely the difference comes from resize().
It's looks like you didn't resize on python, but resized in java. Is that intentional?
@frankfliu No,It not intentional,I had resized the data on python too.The image processing operator is same.
Above picture is theversion that I used.
@mengpengfei I tried opencv in java, I'm able to generate identical result between DJL and python code.
I noticed your image processing is wrong in both python and java code. Here is the code I tested:
Python:
pic = cv2.imread('test.png')
pic = cv2.resize(pic, dsize=(128, 32), fx=0, fy=0, interpolation=cv2.INTER_LINEAR)
pic = np.asarray(pic)
mean_std = (MEAN, STD)
input_transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(*mean_std)
])
tensor = input_transform(pic)
tensor = torch.unsqueeze(tensor, 0)
with open("python.bin", "wb") as f:
f.write(tensor.detach().numpy().tobytes())
Java code:
OpenCV.loadShared();
float[] MEAN = new float[]{0.485f, 0.456f, 0.406f};
float[] STD = new float[]{0.229f, 0.224f, 0.225f};
try (NDManager manager = NDManager.newBaseManager()) {
String file = "test.png";
Mat mat = Imgcodecs.imread(file);
Mat mat1 = new Mat();
Imgproc.resize(mat, mat1, new Size(128, 32), 0, 0, Imgproc.INTER_LINEAR);
byte[] buf = new byte[128 * 32 * mat1.channels()];
mat1.get(0, 0, buf);
Shape shape = new Shape(32, 128, mat1.channels());
NDArray imageArray = manager.create(ByteBuffer.wrap(buf), shape, DataType.UINT8);
// NDArray ndArray = imageArray
// .expandDims(0)
// .div(255.0) // you missed this
// .transpose(0, 3, 1, 2)
// .toType(DataType.FLOAT32, true);
//
// Normalize normalize = new Normalize(MEAN, STD);
// NDArray ret = normalize.transform(ndArray);
Pipeline pipeline = new Pipeline();
pipeline.add(new ToTensor())
.add(new Normalize(MEAN, STD))
.add(a -> a.expandDims(0));
NDList list = pipeline.transform(new NDList(imageArray));
buf = list.head().toByteArray();
try (OutputStream os = Files.newOutputStream(Paths.get("java_cv.bin"))) {
os.write(buf);
}
}
@mengpengfei by the way, do you have to use cv2 to resize? Can you use transforms.Resize()? DJL's Resize() is identical to transforms.Resize().
When i use follwing code,the problem is solved,thank you very much!
byte[] bytes = new byte[32 * 128 * 3];
int i1 = mat1.get(0, 0, bytes);
Shape shape = new Shape(32, 128, 3);
NDArray imageArray = manager.create(ByteBuffer.wrap(bytes), shape, DataType.UINT8);
The project had make me very excited,but when i use it,some problem is too hard for me to solve. I use djl to inference onnx model,but the result of djl is diffrent from the result of python. This issue cause lower accuracy when i use djl to inference my model of onnx.
the result of python is "normalize",it is right. but the result of java is "normaiz" ,it is not right. I had meet many similar problems. the python code is:
the java code:
please help me! thanks very much.Wait for your answer.