PyDetector: adding check if returned descriptors are empty (#1715)

* PyDetector: adding check if returned descriptors are empty (addressing #1714)

* Throwing error instead of asserting if keypoints and descriptors mistmatch

* ading error instead of warning

* lets do warnings instead (could be possible that images are blanck)
This commit is contained in:
matlabbe
2026-06-01 21:04:08 -07:00
committed by GitHub
parent 6f34498651
commit f29676deb0
3 changed files with 38 additions and 12 deletions
+11 -2
View File
@@ -887,8 +887,17 @@ cv::Mat Feature2D::generateDescriptors(
UASSERT(!image.empty()); UASSERT(!image.empty());
UASSERT(image.type() == CV_8UC1); UASSERT(image.type() == CV_8UC1);
descriptors = generateDescriptorsImpl(image, keypoints); descriptors = generateDescriptorsImpl(image, keypoints);
UASSERT_MSG(descriptors.rows == (int)keypoints.size(), uFormat("descriptors=%d, keypoints=%d", descriptors.rows, (int)keypoints.size()).c_str()); if(descriptors.rows != (int)keypoints.size())
UDEBUG("Descriptors extracted = %d, remaining kpts=%d", descriptors.rows, (int)keypoints.size()); {
UWARN("Descriptor extraction returned %d rows for %d keypoints — "
"clearing keypoints to keep them in sync.",
descriptors.rows, (int)keypoints.size());
keypoints.clear();
descriptors = cv::Mat();
}
else {
UDEBUG("Descriptors extracted = %d, remaining kpts=%d", descriptors.rows, (int)keypoints.size());
}
} }
return descriptors; return descriptors;
} }
+19 -7
View File
@@ -202,18 +202,30 @@ std::vector<cv::KeyPoint> PyDetector::generateKeypointsImpl(const cv::Mat & imag
arrayPtr = reinterpret_cast<PyArrayObject*>(descPtr); arrayPtr = reinterpret_cast<PyArrayObject*>(descPtr);
int nDesc = PyArray_SHAPE(arrayPtr)[0]; int nDesc = PyArray_SHAPE(arrayPtr)[0];
UASSERT(nDesc = nKpts);
int dim = PyArray_SHAPE(arrayPtr)[1]; int dim = PyArray_SHAPE(arrayPtr)[1];
type = PyArray_TYPE(arrayPtr); type = PyArray_TYPE(arrayPtr);
UDEBUG("Desc array %dx%d (type=%d)", nDesc, dim, type); UDEBUG("Desc array %dx%d (type=%d)", nDesc, dim, type);
UASSERT_MSG(type == NPY_FLOAT, uFormat("Returned matches should type FLOAT=11, received type=%d", type).c_str());
c_out = reinterpret_cast<float*>(PyArray_DATA(arrayPtr)); if(nDesc != nKpts || dim <= 0)
for (int i = 0, kpt_idx = 0; i < nDesc*dim; i+=dim, kpt_idx++)
{ {
if(keep_kpt[kpt_idx]) { UWARN("Python detector returned mismatched arrays: "
cv::Mat descriptor = cv::Mat(1, dim, CV_32FC1, &c_out[i]).clone(); "%d keypoints vs %d descriptors (dim=%d). "
descriptors_.push_back(descriptor); "Returning empty features.",
nKpts, nDesc, dim);
keypoints.clear();
descriptors_ = cv::Mat();
}
else
{
UASSERT_MSG(type == NPY_FLOAT, uFormat("Returned matches should type FLOAT=11, received type=%d", type).c_str());
c_out = reinterpret_cast<float*>(PyArray_DATA(arrayPtr));
for (int i = 0, kpt_idx = 0; i < nDesc*dim; i+=dim, kpt_idx++)
{
if(keep_kpt[kpt_idx]) {
cv::Mat descriptor = cv::Mat(1, dim, CV_32FC1, &c_out[i]).clone();
descriptors_.push_back(descriptor);
}
} }
} }
} }
+8 -3
View File
@@ -144,7 +144,12 @@ std::vector<cv::KeyPoint> SPDetector::detect(const cv::Mat &img, const cv::Mat &
UASSERT(img.type() == CV_8UC1); UASSERT(img.type() == CV_8UC1);
UASSERT(mask.empty() || (mask.type() == CV_8UC1 && img.cols == mask.cols && img.rows == mask.rows)); UASSERT(mask.empty() || (mask.type() == CV_8UC1 && img.cols == mask.cols && img.rows == mask.rows));
detected_ = false; detected_ = false;
if(model_) if(!model_)
{
UERROR("No model is loaded!");
return std::vector<cv::KeyPoint>();
}
try
{ {
torch::NoGradGuard no_grad_guard; torch::NoGradGuard no_grad_guard;
auto x = torch::from_blob(img.data, {1, 1, img.rows, img.cols}, torch::kByte); auto x = torch::from_blob(img.data, {1, 1, img.rows, img.cols}, torch::kByte);
@@ -199,9 +204,9 @@ std::vector<cv::KeyPoint> SPDetector::detect(const cv::Mat &img, const cv::Mat &
detected_ = true; detected_ = true;
return keypoints; return keypoints;
} }
else catch(const std::exception & e)
{ {
UERROR("No model is loaded!"); UERROR("SPDetector::detect() threw: %s", e.what());
return std::vector<cv::KeyPoint>(); return std::vector<cv::KeyPoint>();
} }
} }