我已经使用MATLAB Coder将MATLAB脚本转换为C。该脚本以uint 8格式的视频作为输入,使用自定义的YOLOv 4 DL网络执行对象检测任务以识别感兴趣的对象,并创建在对象边界内裁剪的新uint 8数组(视频)(参见下面的代码):
function [I] = Android3(Vrecorded)
%#codegen
% Loads and created pretrained YOLO v4 DL NW detector customized
% to detect LED array.
detector = coder.loadDeepLearningNetwork("trainedDetector_23022023.mat");
% Read all frames as grayscale images
frames = reshape(Vrecorded(:,:,1,:), size(Vrecorded,1), size(Vrecorded,2), []);
% extrai o número de quadros do vídeo capturado (NoF - Number of Frames)
NoF = size(frames,3);
%Detect objects in an unknown image / video by using the pretrained YOLO v4
FrameForDetection = zeros(size(Vrecorded,1),size(Vrecorded,2),3);
FrameForDetection(:,:,:) = Vrecorded(:,:,:,1);
%object detector
[bboxes,~,~] = detect(detector,FrameForDetection);
% This cell contains the cropped frames containing RoI after YOLO v4 object
% detection algoritm process the frames
croppedFrameVectors = cell(1,1);
sizes = imcrop(frames(:,:,1),bboxes(1,:));
croppedFrames = zeros(size(sizes,1),size(sizes,2),NoF);
for n = 1:1
croppedFrameVectors{n} = rand(0,0,0);
for k = 1:NoF
% crops the frames in each detected object according to bounding
% boxes results captured on the first frame
croppedFrames(:,:,k) = imcrop(frames(:,:,k),bboxes(1,:));
end
% Insert the cropped frames with bounding boxes within a cell to allow
% multiple cropped objects within the same variable
croppedFrameVectors{n} = croppedFrames;
% Erase variable to crop another object due to bbox different
% dimensions from one object to another (widht x height)
end
I = croppedFrameVectors{1};
字符串
其中Vrecorded是大小为240 x320 xF的视频矩阵,并且F取决于输入视频而变化。
在将其转换为C并尝试将其调整为JNI语法之后,这是我迄今为止所做的:
#include <jni.h>
/* Include files */
#include "main.h"
#include "Android3.h"
#include "Android3_emxAPI.h"
#include "Android3_terminate.h"
#include "Android3_types.h"
#include "rt_nonfinite.h"
#include <android/log.h>
JNIEXPORT jbyteArray JNICALL
Java_com_example_occ_MainActivity_teste(JNIEnv *env, jobject thiz, jbyteArray Vrecorded) {
emxArray_real_T *b_I;
//emxArray_uint8_T *Vrecorded;
// Call the entry-point function 'Android3'
emxInitArray_real_T(&b_I, 3);
Android3(Vrecorded, b_I);
// Clean up memory
emxDestroyArray_uint8_T(Vrecorded);
emxDestroyArray_real_T(b_I);
}
型
其中Android 3()是从MATLAB代码执行图像处理的函数。我的Java主应用程序是:
package com.example.occ;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.example.occ.databinding.ActivityMainBinding;
import java.util.Arrays;
public class MainActivity extends AppCompatActivity {
// Used to load the 'occ' library on application startup.
static {
System.loadLibrary("occ");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
byte[] c = new MainActivity().teste(I);
System.out.println("Value of matrix B is: " + Arrays.toString(c));
}
public native byte[] teste(byte[] I);
}
型
到目前为止,我有两个问题:
1.我将矩阵Vrecorded(uint 8格式)传递给JNI函数的逻辑是否正确(使用byteArray[])。该矩阵具有3个维度;
1.如果我在编译运行前不知道矩阵的大小,如何将矩阵'I'返回到Java,以便它可以显示在屏幕上**?**
2条答案
按热度按时间qnzebej01#
我看不出这一切是如何工作的。java
byte[]
是一个表示一维数组的对象。在JNI端,这是一个不透明的jbyteArray
对象。我所说的“opaque”是指不能单独使用这个值,必须使用像GetByteArryaElements
这样的JNI函数来获取指向实际字节数组(的副本)的指针。然而,Matlab代码将其视为四维数组。例如,三维数组
arr
将是byte[][][]
。在JNI侧,这是一个不透明的jobjectArray
,其中层的类型依次为:arr
的类型为byte[][][]
,JNI类型为jobjectArray
arr[x]
具有byte[][]
类型和JNI类型jobjectArray
arr[x][y]
具有byte[]
类型和JNI类型jbyteArray
因此,在输入端有许多选项:
byte[]
,在这种情况下,你需要使用Matlab emx API将其解压缩为一个四维向量。这需要提取每一层的维度(或者仅仅“知道”它们)。在输出端,您遇到了相反的问题:你是把它表示成一个平面的一维数组,还是完全三维的(如果我没看错你的Matlab代码的话)数组,还是介于两者之间的?在我看来,最自然的方法是创建一个小的助手类
Rect
,用宽度和高度装饰一个byte[]
,然后返回一个Rect[][]
,其中每个输入帧有一个Rect[]
。最后,如果性能在考虑范围内,您将需要查看直接字节缓冲区,它只是本地内存的块,您可以从Java传递到本地代码而无需复制。
rks48beu2#
我的意思是,你必须构建一个Java数组。我认为在将数组返回给java之前应该知道数组的大小。在JNI文档中查看如何创建Java基本类型之一的Java数组。
那么java是如何确定数组大小的呢?Java数组是对象,不像C中的数组那样简单(它只包含一个接一个的普通数组元素)数组有一个不可变的
length
元素和存储在其示例中的数组元素。只需深入研究JNDI文档,了解如何从C帮助程序库创建java数组。