OpenCV SIFT detectorAndCompute 在 Android 上崩溃且没有错误

问题描述 投票:0回答:2

我正在尝试在 Android 应用程序中实现一些计算机视觉。

我集成了 opencv,并且正在为其编写本机 C++ 代码,称为使用 JNI。这一切似乎都在发挥作用。我的问题是,当执行计算机视觉代码时,以下行会使应用程序崩溃而没有任何错误。

detector->detectAndCompute(usr_img,usr_mask,usr_keypoints,usr_descriptors);

如果我使用球体探测器,而不是筛子,它确实有效。在我的物理设备上,它在 knnMatch 上崩溃。而在模拟 Pixel 5 上它可以正确完成。也许跟我的opencv和android版本有关系?

这是完整的计算机视觉代码:

void process_image(char* in_filepath,char* out_filepath){

   Mat usr_img = imread(in_filepath); //read images from the disk
   Mat ref_img = imread("redacted");
   Mat overlay_img = imread("redacted");
   Mat out_img;//make a copy for output
   usr_img.copyTo(out_img);

   //Set up feature detector
   Ptr<SIFT> detector = SIFT::create();
   //Ptr<ORB> detector = ORB::create(); //detectAndCompute works if I use this instead

   //Set up feature matcher
   Ptr<BFMatcher> matcher = BFMatcher::create(NORM_HAMMING,true);

   //generate mask for ref image (so features are not created from the background)
   Mat ref_mask; //defines parts of the ref image that will be searched for features.
   inRange(ref_img,Scalar(0.0,0.0,252.0),Scalar(2.0,2.0,255.0),ref_mask);
   bitwise_not(ref_mask,ref_mask);//invert the mask

   //and an all white mask for the usr image
   Mat usr_mask = Mat(usr_img.cols,usr_img.rows, CV_8UC1, Scalar(255.0));

   //detect keypoints
   std::vector<KeyPoint> ref_keypoints, usr_keypoints;
   Mat ref_descriptors, usr_descriptors;
   detector->detectAndCompute(ref_img,ref_mask,ref_keypoints,ref_descriptors);
   detector->detectAndCompute(usr_img,usr_mask,usr_keypoints,usr_descriptors);

   //match descriptors between images, each match is a vector of matches by decreasing "distance"
   std::vector<std::vector<DMatch>> matches;
   matcher->knnMatch(usr_descriptors,ref_descriptors,matches,2);

   //throw out bad matches
   std::vector<DMatch> good_matches;
   for(uint32_t i = 0; i < matches.size(); i++){
       //consider it a good match if the next best match is 33% worse
       if(matches[i][0].distance*1.33 < matches[i][1].distance){
           good_matches.push_back(matches[i][0]);
       }
   }

   //visualize the matches for debugging purposes
   Mat draw_match_img;
   drawMatches(usr_img,usr_keypoints,ref_img,ref_keypoints,good_matches,draw_match_img);
   imwrite("redacted",draw_match_img);
}

我的opencv版本是4.5.4

我的 Android 版本在物理手机上是 9,在模拟 Pixel 5 上是 11,api 30

android opencv computer-vision sift
2个回答
2
投票
我发现问题了。

我的图像尺寸为 4000x3000 像素,约为 3000x1600。将两个图像缩小 2 倍会使一切正常工作。

我在每次读取后添加了一个调整大小,如下所示:

resize(x_img,x_img,Size(),0.5,0.5,INTER_CUBIC);
这告诉我,opencv 4.5.4 中的 SIFT 有图像大小限制,超过该限制执行将崩溃,并且不会出现错误消息。 ..烦人。

它还解释了为什么有些检测器起作用而有些检测器不起作用,甚至当我在真实设备和模拟设备上运行它时,它似乎有所不同。


0
投票
为了补充答案,调整图像大小确实有帮助,你必须记住的问题是 OpenCV 消耗了多少内存。

在我的例子中,缩小图像有助于直到某个点,我们正在执行多个线程来运行并发 SIFT 特征匹配逻辑,并且我们仍然会根据我们有多少并发请求来重新启动。因此,还要查看机器的整体内存并找到最佳位置。在我们的例子中,我们能够减少 JVM 最大内存,以便为 OpenCV 提供更多内存来完成其工作,并且能够运行更多并发线程。

不要忘记使用 mat.release() 来释放你的 Mats

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.