features2d: fix ORB::setFirstScale() handling
authorAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 11 Dec 2020 17:21:48 +0000 (17:21 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Fri, 11 Dec 2020 18:05:24 +0000 (18:05 +0000)
modules/features2d/src/orb.cpp
modules/features2d/test/test_orb.cpp

index ee4e55c..39ebec7 100644 (file)
@@ -1025,15 +1025,20 @@ void ORB_Impl::detectAndCompute( InputArray _image, InputArray _mask,
     Mat imagePyramid, maskPyramid;
     UMat uimagePyramid, ulayerInfo;
 
-    int level_dy = image.rows + border*2;
-    Point level_ofs(0,0);
-    Size bufSize((cvRound(image.cols/getScale(0, firstLevel, scaleFactor)) + border*2 + 15) & -16, 0);
+    float level0_inv_scale = 1.0f / getScale(0, firstLevel, scaleFactor);
+    size_t level0_width = (size_t)cvRound(image.cols * level0_inv_scale);
+    size_t level0_height = (size_t)cvRound(image.rows * level0_inv_scale);
+    Size bufSize((int)alignSize(level0_width + border*2, 16), 0);  // TODO change alignment to 64
+
+    int level_dy = (int)level0_height + border*2;
+    Point level_ofs(0, 0);
 
     for( level = 0; level < nLevels; level++ )
     {
         float scale = getScale(level, firstLevel, scaleFactor);
         layerScale[level] = scale;
-        Size sz(cvRound(image.cols/scale), cvRound(image.rows/scale));
+        float inv_scale = 1.0f / scale;
+        Size sz(cvRound(image.cols * inv_scale), cvRound(image.rows * inv_scale));
         Size wholeSize(sz.width + border*2, sz.height + border*2);
         if( level_ofs.x + wholeSize.width > bufSize.width )
         {
index 01d1746..0ffaa62 100644 (file)
@@ -90,7 +90,7 @@ TEST(Features2D_ORB, _1996)
     ASSERT_EQ(0, roiViolations);
 }
 
-TEST(Features2D_ORB, crash)
+TEST(Features2D_ORB, crash_5031)
 {
     cv::Mat image = cv::Mat::zeros(cv::Size(1920, 1080), CV_8UC3);
 
@@ -123,4 +123,23 @@ TEST(Features2D_ORB, crash)
     ASSERT_NO_THROW(orb->compute(image, keypoints, descriptors));
 }
 
+
+TEST(Features2D_ORB, regression_16197)
+{
+    Mat img(Size(72, 72), CV_8UC1, Scalar::all(0));
+    Ptr<ORB> orbPtr = ORB::create();
+    orbPtr->setNLevels(5);
+    orbPtr->setFirstLevel(3);
+    orbPtr->setScaleFactor(1.8);
+    orbPtr->setPatchSize(8);
+    orbPtr->setEdgeThreshold(8);
+
+    std::vector<KeyPoint> kps;
+    Mat fv;
+
+    // exception in debug mode, crash in release
+    ASSERT_NO_THROW(orbPtr->detectAndCompute(img, noArray(), kps, fv));
+}
+
+
 }} // namespace