如何解决如何将 Array<Mat> 从 Kotlin 导入 JNI?
我是 JNI 编码新手, 所以我的问题是当我调试我的 Android Studio 时,它给了我这个“错误:调用隐式删除的 'cv::Mat' 复制构造函数” 我不知道为什么。我想这是因为我如何尝试从 'jlong' 和 'jlongArray' 更改为 'Mat'。我的 native-lib.cpp 是:
JNIEXPORT jlong JNICALL
Java_com_android_example_panoramacamera_fragments_CameraFragment_imagesPass(jnienv *env,jobject thiz,jlongArray image_in_,jlong image_out_) {
// Todo: implement imagesPass()
Stitcher::Mode mode = Stitcher::PAnorAMA;
Mat *image_in = (Mat*) image_in_,*image_out = (Mat*) image_out_;
// Create a Stitcher class object with mode panoroma
Ptr<Stitcher> stitcher = Stitcher::create(mode,false);
// Command to stitch all the images present in the image array
Stitcher::Status status = stitcher->stitch(*image_in,*image_out);
if(status == Stitcher::OK){
return (jlong) image_out;
}
}
还有我的 kotlin-sript:
private external fun imagesPass(imageIn: LongArray,imageOut: Long): Long
override fun onActivityResult(requestCode: Int,resultCode: Int,data: Intent?) {
super.onActivityResult(requestCode,resultCode,data)
if (requestCode == pickImageCode && resultCode == RESULT_OK) {
if (data != null) {
if (data.clipData != null) {
val count = data.clipData!!.itemCount
for (i in 0 until count) {
val imageUri = data.clipData!!.getItemAt(i).uri
val imagestream: InputStream? = context?.contentResolver?.openInputStream(imageUri)
val bitmap = BitmapFactory.decodeStream(imagestream)
val mat = Mat()
Utils.bitmapToMat(bitmap,mat)
imagesMat[i] = mat
}
}
else {
val imageUri = data.data
val imagestream: InputStream? = imageUri?.let { context?.contentResolver?.openInputStream(it) }
val bitmap = BitmapFactory.decodeStream(imagestream)
val mat = Mat()
Utils.bitmapToMat(bitmap,mat)
imagesMat[0] = mat
}
}
for(i in imagesMat.indices){
longArray[i] = imagesMat[i].nativeObj
}
long = imagesPass(longArray,imageStitch.nativeObj)
imageStitch = Mat(long)
}
super.onActivityResult(requestCode,data)
}
如您所见,我尝试导入 Mat,但由于 jni.h 的语言非常有限,我必须将 Mat 转换为 Long,以便我可以同时使用 Array 和 Mat。 但是后来我的“opencv2/core/mat.inl.hpp”开始显示错误:
inline Mat _InputArray::getMat(int i) const
{
if( kind() == MAT && i < 0 )
return *(const Mat*)obj; //This line gets error
return getMat_(i);
}
所以我的问题是如何从 jlongArray 转换为 InputArray?或者如何从 Kotlin 将数组导入 JNI? 非常感谢。
解决方法
做类似的事情
Mat *image_in = (Mat*) image_in_
是不正确的代码。出于所有实际目的,始终将所有 JNI 对象视为不透明对象,不假设它们如何存储实际底层数据,而是使用 JNI API 来操作这些对象,包括从中检索实际数据。 jlongArray
与 jlong array[] = {1,2,3}
之类的东西不等价。
据我所知,您需要从 Java jlongArray
访问底层本机元素。有两种可能的选择:
-
使用
GetLongArrayElements()
获取支持的原生元素。这提供了一个原生的jlong
数组,该数组在调用ReleaseLongArrayElements()
之前一直有效。 -
使用
jlongArray
从GetLongArrayRegion()
创建一系列元素的副本,该副本提供缓冲区的副本到jlong*
缓冲区。此缓冲区的寿命不与实际的jlongArray
相关联。如果需要将此缓冲区中的元素复制回原始jlongArray
,则可以使用SetLongArrayRegion()
。
一旦您可以访问本机缓冲区,就可以像往常一样在 C++ 代码中使用它们,就像 long
的数组一样。
第一种方法的解决方案示例如下所示:
Java_com_android_example_panoramacamera_fragments_CameraFragment_imagesPass
(JNIEnv * env,jobject thiz,jlongArray imageIn,jlong ImageOut) {
jsize len = env->GetArrayLength(imageIn);
jlong * nativeImageList = env->GetLongArrayElements(imageIn,NULL);
//Now one can do something like
//Mat* image_in = reinterpret_cast<Mat*>(nativeImageList);
//This should give the native version of images
for(jsize idx = 0; idx < len; idx++) {
std::printf("%zd ",nativeImageList[idx]);
}
std::printf("\n");
//Once done with the array,release it back to JVM
env->ReleaseLongArrayElements(imageIn,nativeImageList,0);
return ImageOut;
}
在上面这段代码中,nativeImageList
是一个 jlong
数组,它等价从 Java/Kt 层传入 {{1} }}。此 longArray
中的每个元素都将与行中存储的相同
nativeImageList
因此 longArray[i] = imagesMat[i].nativeObj
应为 nativeImageList[0]
的值,依此类推。这显然是底层图像的句柄,可以用作
imagesMat[0].nativeObj
注意区别
Mat* image_in = reinterpret_cast<Mat*>(nativeImageList);
此处,检索 native 元素,然后将其转换为 Mat* image_in = (Mat*) image_in_
,而不是直接从 Mat*
对象中转换。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。