我正在尝试使用cv::calcOpticalFlowPyrLK
但有时在该函数中的内部断言失败。断言是npoints = prevPtsMat.checkVector(2, CV_32F, true)) >= 0
。我正在使用OpenCV 2.3.1。此功能的源代码可用here。
很难绕过他们的代码,特别是因为我对计算机图形学的经验有限以及缺乏评论。为什么这个断言被触发,它对我的问题说了什么?
编辑:我按如下方式调用该函数:
cv::calcOpticalFlowPyrLK(curBwFrame, prvFrame, features, newFeatures, trackingStatus, errors);
我发现features
向量是通过调用cv::goodFeaturesToTrack(curBwFrame, features, 5, 0.2, 0.5, skinMask);
获得的非空掩码获得的,该掩码看起来足够大且有效图像,不包含任何特征。怎么会发生这种情况?
curBwFrame
skinMask
我可以使用以下代码段重现问题:
#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;
}
答案 0 :(得分:4)
主要问题是你的参数。在OpenCV 2.3.2 documentation(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 )
参数:
我建议您使用qualityLevel和minDistance来玩一点,以满足您的需求。
答案 1 :(得分:1)
您是否尝试过goodFeaturesToTrack 没有遮罩来查看它是否检测到遮罩区域内的功能?有可能因为图像很暗,而且区域有点无纹理,所以goodFeaturesToTrack无法在那里找到特征。
您也可以尝试ORB or FAST而不是goodFeaturesToTrack。我已成功使用ORB和calcOpticalFlowPyrLK(但没有尝试使用掩码)。
或者您可以尝试使图像变亮或甚至增强对比度。不确定这是否会带来改进,因为我认为你的场景中最大的问题是场景中的物体没有足够的纹理或角落,这些是这些探测器更合适的特征。 我建议您尝试ORB并查看是否获得更多积分。
答案 2 :(得分:0)
图像是否以彩色开始?在转换为灰色之前,使用cv :: transform增强颜色对比度。拍摄全范围的灰色,从0到255.不要担心屏幕外的图像饱和。
答案 3 :(得分: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时将显示断言