5

我正在尝试使用cv::calcOpticalFlowPyrLK,但有时该函数中的内部断言会失败。断言是npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0。我正在使用 OpenCV 2.3.1。此函数的源代码可在此处获得。

我很难理解他们的代码,尤其是因为我在计算机图形方面的经验有限并且他们缺乏评论。为什么会触发此断言,它对我的​​问题有什么看法?

编辑:我调用函数如下:

cv::calcOpticalFlowPyrLK(curBwFrame, prvFrame, features, newFeatures, trackingStatus, errors);

我发现通过使用看起来足够大和有效图像的非空掩码features调用获得的向量cv::goodFeaturesToTrack(curBwFrame, features, 5, 0.2, 0.5, skinMask);不包含任何特征。这怎么可能发生?

curBwFrame

curBwFrame

皮肤面膜

皮肤面膜

我可以使用以下代码片段重现该问题:

#include <vector>
#include <cassert>
#include <opencv2\opencv.hpp>
using std::vector;
using namespace cv;

int main() {
    vector<Point2f> features;
    cv::Mat curBwFrame = imread("curBwFrame.png");
    cv::cvtColor(curBwFrame, curBwFrame, CV_RGB2GRAY);
    imwrite("test.png", curBwFrame);

    cv::Mat skinMask = imread("skinMask.png");
    cv::cvtColor(skinMask, skinMask, CV_RGB2GRAY);
    imwrite("test.png", skinMask);

    cv::goodFeaturesToTrack(curBwFrame, features, 5, 0.2, 0.5, skinMask);
    assert(features.size() > 0);

    return 0;
}
4

4 回答 4

4

主要问题是您的参数。在OpenCV 2.3.2 文档中(2.3.1 之间没有兼容性更改)这是方法参数的描述:

void goodFeaturesToTrack(InputArray image, OutputArray corners, int maxCorners, double qualityLevel, double minDistance, InputArray mask=noArray(), int blockSize=3, bool useHarrisDetector=false, double k=0.04 )

参数:

  • image – 输入 8 位或浮点 32 位单通道图像。
  • 角 - 检测到的角的输出向量。
  • maxCorners – 要返回的最大角点数。如果角点多于找到的角点,则返回最强的角点。
  • qualityLevel – 表征图像角的最低可接受质量的参数。参数值乘以最佳角质量度量,即最小特征值(参见cornerMinEigenVal())或哈里斯函数响应(参见cornerHarris())。质量度量低于产品的角将被拒绝。例如,如果最佳角的质量度量 = 1500,并且 qualityLevel=0.01 ,则质量度量小于 15 的所有角都将被拒绝。
  • minDistance – 返回的角点之间可能的最小欧几里得距离。
  • 掩码——可选的感兴趣区域。如果图像不是空的(它需要具有 CV_8UC1 类型并且与 image 大小相同),它指定检测角的区域。
  • blockSize – 用于计算每个像素邻域的导数协变矩阵的平均块的大小。参见cornerEigenValsAndVecs()。
  • useHarrisDetector – 指示是否使用 Harris 检测器的参数(参见cornerHarris())或cornerMinEigenVal()。
  • k – Harris 检测器的自由参数。

我建议您使用 qualityLevel 和 minDistance 来满足您的需求。

于 2012-06-11T18:05:46.663 回答
1

您是否尝试过不带遮罩的 goodFeaturesToTrack以查看它是否检测到遮罩区域内的特征?可能是因为图像很暗,并且该区域有点无纹理,所以 goodFeaturesToTrack 无法在那里找到特征。

您也可以尝试ORB 或 FAST,而不是 goodFeaturesToTrack。我已经成功地将 ORB 与 calcOpticalFlowPyrLK 一起使用(但没有尝试使用掩码)。

或者您可以尝试使图像变亮,甚至增强对比度。不确定这是否会带来改进,因为我认为您的场景中最大的问题是场景中的对象没有足够的纹理或角落,这是这些检测器更适合的特征。我建议你试试ORB,看看你能不能得到更多的积分。

于 2012-06-11T13:43:10.480 回答
0

图像是否以彩色开始?在转换为灰色之前,使用 cv::transform 增强颜色对比度。拍摄从 0 到 255 的全范围灰度。不要担心蒙版外的图像会饱和。

于 2012-06-12T17:10:13.377 回答
0

如果您的代码与此类似:

 Imgproc.goodFeaturesToTrack(mCurrentFrame, initial, NUMBER_OF_FEATURES, 0.1, 10); 
 //The OpenCV opticalFlow will crash if the feature vector does not include any elements
 if (initial.elemSize() == 0) {
     return;
 }
 initial.convertTo(mPrevPts, CvType.CV_32FC2);

 Video.calcOpticalFlowPyrLK(mPreviousFrame, mCurrentFrame, mPrevPts, mNextPts, status,err);

确保不要忘记检查特征向量大小的语句 (initial.elemSize() == 0)。

如果此向量为空,则不会发生由 initial.convertTo() 行完成的从点矩阵到浮点的转换,并且在调用 calOpticalFlowPyrLK 时将显示断言

于 2016-11-22T19:15:52.167 回答