gpt4 book ai didi

java - 如何在Android Activity中调用Jni对象?

转载 作者:行者123 更新时间:2023-12-02 11:57:21 26 4
gpt4 key购买 nike

我正在制作文档扫描仪。我正在使用 opencv 进行图像处理。在相机 View 中,我在最大轮廓上界定矩形。处理部分写在Native-lib.cpp中。它正在正确检测最大轮廓。现在我只想捕获在native-lib.cpp中编写的boudingRect。所以我想要java类中的native-lib对象。帮助实现这一目标。

Native-lib.cpp

extern "C"
JNIEXPORT void JNICALL
Java_prisca_ctest_OpenCvCamera_doWithMat(JNIEnv *env, jobject instance, jlong matAddrGr,
jlong matAddrRgba) {
try {
Mat &image = *(Mat *) matAddrRgba;
Rect bounding_rect;

Mat thr(image.rows, image.cols, CV_8UC1);
cvtColor(image, thr, CV_BGR2GRAY); //Convert to gray
threshold(thr, thr, 150, 255, THRESH_BINARY + THRESH_OTSU); //Threshold the gray

vector<vector<Point> > contours; // Vector for storing contour
vector<Vec4i> hierarchy;
findContours(thr, contours, hierarchy, CV_RETR_CCOMP,
CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image
sort(contours.begin(), contours.end(),
compareContourAreas); //Store the index of largest contour
bounding_rect = boundingRect((const _InputArray &) contours[0]);

rectangle(image, bounding_rect, Scalar(250, 250, 250) , 5);
} catch (int a) {

}
}

Activity

 protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.cam);
mOpenCvCameraView = (JavaCameraView) findViewById(R.id.tutorial1_activity_java_surface_view);
mOpenCvCameraView.setVisibility(View.VISIBLE);

mOpenCvCameraView.setCvCameraViewListener(this);
btnCapture = (Button) findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String timestamp = new SimpleDateFormat("ddMMyyyy_HHmmss", Locale.US).format(new Date());
File imgFolder = new File(FILE_LOCATION);
imgFolder.mkdir();
File image = new File(imgFolder, "Scan" + timestamp + ".jpg");
String fileName = FILE_LOCATION +
"/Scan" + timestamp + ".jpg";
Toast.makeText(OpenCvCamera.this, image + " saved", Toast.LENGTH_SHORT).show();
Imgcodecs.imwrite(fileName, mRgba);
}
}) ;
}

@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
// input frame has RGBA format
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
doWithMat(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
return mRgba;

}

我应该在 Imgcodecs.imwrite(fileName, mRgba) 上面添加什么来裁剪矩阵并仅保存 boundingRect 部分?

可能我必须在imwrite之前写这个 -

Mat cropped = mRgba.submat( bounding_rect );
Imgcodecs.imwrite(fileName, cropped);

但我无法从 Native-lib 调用bounding_rect。怎么称呼呢?提前谢谢你:)

最佳答案

您可以从native-lib接收org.opencv.core.Rect。最简单的方法是更改​​ native 方法签名 doWithMat(),如下所示:

private org.opencv.core.Rect mBoundingRect;

@Override
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
// input frame has RGBA format
mRgba = inputFrame.rgba();
mGray = inputFrame.gray();
mBoundingRect = doWithMat(mGray.getNativeObjAddr(), mRgba.getNativeObjAddr());
return mRgba;
}
<小时/>
extern "C"
JNIEXPORT jobject JNICALL
Java_prisca_ctest_OpenCvCamera_doWithMat(JNIEnv *env, jobject instance,
jlong matAddrGr, jlong matAddrRgba) {

Mat &image = *(Mat *) matAddrRgba;
Rect bounding_rect;

Mat thr(image.rows, image.cols, CV_8UC1);
cvtColor(image, thr, CV_BGR2GRAY); // Convert to gray
threshold(thr, thr, 150, 255, THRESH_BINARY + THRESH_OTSU); //Threshold the gray

vector<vector<Point> > contours; // Vector for storing contour
vector<Vec4i> hierarchy;
findContours(thr, contours, hierarchy, CV_RETR_CCOMP,
CV_CHAIN_APPROX_SIMPLE); // Find the contours in the image
sort(contours.begin(), contours.end(),
compareContourAreas); // Store the index of largest contour
bounding_rect = boundingRect((const _InputArray &) contours[0]);

rectangle(image, bounding_rect, Scalar(250, 250, 250) , 5);

jclass rectClass = env->FindClass("org/opencv/core/Rect");
jmethodID rectCtorID = env->GetMethodID(rectClass, "<init>", "(IIII)V");
return env->NewObject(rectClass, rectCtorID, bounding_rect.x, bounding_rect.y, bounding_rect.width, bounding_rect.height);
}

如您所见,我从 native 代码中删除了 try ... catch ;我不认为它真的有帮助,特别是当你 try catch int 而不是异常时。

请注意,提取 rectClassrectCtorID 是昂贵的操作,因此缓存这些值是明智的做法:

static jclass rectClass = nulltr;
ststic jmethodID rectCtorID = 0;
if (rectCtorID == 0) {
rectClass = env->NewGlobalRef(env->FindClass("org/opencv/core/Rect"));
rectCtorID = env->GetMethodID(rectClass, "<init>", "(IIII)V");
}

请注意,我们需要对 Java 类的全局引用,但方法 ID 只是一个 int。

<小时/>

我建议的另一个优化是使用matAddrGr。如果我理解正确的话,OpenCV 将为 onCameraFrame() 准备两个矩阵,因此您可能不需要将 RGB 转换为灰色。

关于java - 如何在Android Activity中调用Jni对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47511956/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com