我遇到了奇怪的问题。为了简短起见:我编写了一个Android应用程序,它使用OpenCV和两个活动:
活动1 预览前置摄像头,用户点击启动Activity2,按意图发送当前帧的地址
Activity2 为其指定给定地址下的帧的Mat克隆类型的本地字段,并允许用户对其进行简单操作(即在HSV颜色空间中执行inRange方法)。 Mat转换为在ImageView中显示的Bitmap:这发生在Activity2启动(对于原始捕获的帧)和每个用户操作SeekBar之后。
Activity1是Activity2的父级,因此单击后退按钮会重新启动Activity1。 现在出现了奇怪的部分:
1)经过一段时间(不到1分钟),Activity1崩溃,libc: Fatal signal 11 (SIGSEGV)
- 如您所想,当Activity2永远不会启动时不会发生
2)如果我通过简单地返回到Activity1并再次单击来重新启动Activity2,则会调用OnCreate()和常规生命周期中的其他方法,当从Mat转换为Bitmap时,应用程序崩溃时会出现相同的致命信号错误:
Utils.matToBitmap(mCapturedFrame, bm);
因此,这是重新启动Activity后第一次调用OpenCV的函数。最好的部分是,mCapturedFrame exsists,并且在加载OpenCV库之后,前面提到的方法被称为。更重要的是,我发布了本地创建的Mats,以及包含捕获帧Mat的字段(当我从Activity2返回时)。在Activity1的情况下,错误看起来像内存泄漏,但在哪里?!
我真的看不出我在这里做错了什么,并且很乐意提出任何建议。随意从这里下载我的java代码文件:http://speedy.sh/RMPKH/thesis.zip
答案 0 :(得分:1)
如果我理解正确,你将Mat的本机对象地址从Activity 1发送到Activity 2.然后,在Activity 2中,你正在做这样的事情:
user_id
在这种情况下,问题是您遇到了双重错误。这样做的原因并非无足轻重,但我会引导您完成。首先让我们看看OpenCV的构造函数的Mat实现:
Mat receivingMat = new Mat(nativeAddrFromActivity1);
当然,receiveMat将来会在某个时候用完范围,然后由GarbageCollector收集。在这种情况下,将调用finalize方法。这导致调用OpenCV Mat实现的本机删除函数,因为finalize方法实现如下:
public Mat(long addr)
{
if (addr == 0)
throw new java.lang.UnsupportedOperationException("Native object address is NULL");
nativeObj = addr;
}
n_delete函数定义如下(see here):
@Override
protected void finalize() throws Throwable {
n_delete(nativeObj);
super.finalize();
}
从我的角度来看,这是OpenCV for Android中的一个错误。使用本机地址构造函数创建的Mat不应该调用n_delete函数,因为它没有本机Mat头的所有权,也不负责清理它。我想不出你想要这种行为的任何情况......
要解决您的问题,您应该将Mat转换为位图,将其保存到临时文件,并通过intent extras将活动1的路径发送到活动2。