OpenCV 2.4.2 calcOpticalFlowPyrLK 找不到任何点
OpenCV 2.4.2 calcOpticalFlowPyrLK doesn't find any points
我在Linux上使用OpenCV 2.4.2。我在用C++写作。我想跟踪简单的对象(例如,白色背景上的黑色矩形)。首先,我使用goodFeaturesToTrack,然后使用calcOpticalFlowPyrLK在另一张图像上找到这些点。问题是calcOpticalFlowPyrLK找不到这些点。
我在C中找到了这样做的代码,但在我的情况下不起作用:http://dasl.mem.drexel.edu/~noahKuntz/openCVTut9.html
我已将其转换为C++:
int main(int, char**) {
Mat imgAgray = imread("ImageA.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat imgBgray = imread("ImageB.png", CV_LOAD_IMAGE_GRAYSCALE);
Mat imgC = imread("ImageC.png", CV_LOAD_IMAGE_UNCHANGED);
vector<Point2f> cornersA;
goodFeaturesToTrack(imgAgray, cornersA, 30, 0.01, 30);
for (unsigned int i = 0; i < cornersA.size(); i++) {
drawPixel(cornersA[i], &imgC, 2, blue);
}
// I have no idea what does it do
// cornerSubPix(imgAgray, cornersA, Size(15, 15), Size(-1, -1),
// TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 20, 0.03));
vector<Point2f> cornersB;
vector<uchar> status;
vector<float> error;
// winsize has to be 11 or 13, otherwise nothing is found
int winsize = 11;
int maxlvl = 5;
calcOpticalFlowPyrLK(imgAgray, imgBgray, cornersA, cornersB, status, error,
Size(winsize, winsize), maxlvl);
for (unsigned int i = 0; i < cornersB.size(); i++) {
if (status[i] == 0 || error[i] > 0) {
drawPixel(cornersB[i], &imgC, 2, red);
continue;
}
drawPixel(cornersB[i], &imgC, 2, green);
line(imgC, cornersA[i], cornersB[i], Scalar(255, 0, 0));
}
namedWindow("window", 1);
moveWindow("window", 50, 50);
imshow("window", imgC);
cvWaitKey(0);
return 0;
}
图片A:http://oi50.tinypic.com/14kv05v.jpg
图片B:http://oi46.tinypic.com/4l3xom.jpg
图片C:http://oi47.tinypic.com/35n3uox.jpg
我发现它只适用于winsize=11。我试着在一个移动的矩形上使用它来检查它离原点有多远。它几乎无法检测到所有四个角。
int main(int, char**) {
std::cout << "Compiled at " << __TIME__ << std::endl;
Scalar white = Scalar(255, 255, 255);
Scalar black = Scalar(0, 0, 0);
Scalar red = Scalar(0, 0, 255);
Rect rect = Rect(50, 100, 100, 150);
Mat org = Mat(Size(640, 480), CV_8UC1, white);
rectangle(org, rect, black, -1, 0, 0);
vector<Point2f> features;
goodFeaturesToTrack(org, features, 30, 0.01, 30);
std::cout << "POINTS FOUND:" << std::endl;
for (unsigned int i = 0; i < features.size(); i++) {
std::cout << "Point found: " << features[i].x;
std::cout << " " << features[i].y << std::endl;
}
bool goRight = 1;
while (1) {
if (goRight) {
rect.x += 30;
rect.y += 30;
if (rect.x >= 250) {
goRight = 0;
}
} else {
rect.x -= 30;
rect.y -= 30;
if (rect.x <= 50) {
goRight = 1;
}
}
Mat frame = Mat(Size(640, 480), CV_8UC1, white);
rectangle(frame, rect, black, -1, 0, 0);
vector<Point2f> found;
vector<uchar> status;
vector<float> error;
calcOpticalFlowPyrLK(org, frame, features, found, status, error,
Size(11, 11), 5);
Mat display;
cvtColor(frame, display, CV_GRAY2BGR);
for (unsigned int i = 0; i < found.size(); i++) {
if (status[i] == 0 || error[i] > 0) {
continue;
} else {
line(display, features[i], found[i], red);
}
}
namedWindow("window", 1);
moveWindow("window", 50, 50);
imshow("window", display);
if (cvWaitKey(300) > 0) {
break;
}
}
}
Lucas Kanade的OpenCV实现似乎无法跟踪二进制图像上的矩形。是我做错了什么,还是这个功能不起作用?
Lucas Kanade方法通过使用区域中的梯度来估计该区域的运动。这是一种梯度下降的方法。因此,如果在x和y方向上没有梯度,该方法将失败。第二个重要的注意事项是Lucas Kanade方程
E=sum_{winsize}(Ix*u+Iy*v*It)²
是强度恒定性约束的一阶泰勒近似。
I(x,y,t)=I(x+u,y+v,t+1)
因此没有级别(图像金字塔)的方法的限制是图像需要是线性函数。在实践中,这意味着只能根据你选择的winsize来估计小动作。这就是为什么你使用的水平,线性化的图像(它)。因此,5的水平有点高,3就足够了。在您的情况下,顶级图像的大小为640x480/2^5=20x15。
最后,代码中的问题是:
if (status[i] == 0 || error[i] > 0) {
从lucas kanade方法返回的错误是生成的SSD,意思是:
error=sum(winSize)(I(x,y,0)-I(x+u,y+u,1)^2)/(winSize*winSize)
错误不太可能为0。所以最后您可以跳过所有功能。我有忽略错误的好经验,这只是一个信心的衡量标准。有非常好的替代信心指标,如前向/后向信心。如果有太多的feaurtes被丢弃,您也可以忽略状态标志来开始实验
KLT通过查找关于某个窗口的两组点之间的变换来进行点跟踪。窗口大小是一个区域,在该区域上,每个点都将被追赶,以便与另一帧上的点相匹配。
它是另一种基于梯度的算法,可以找到好的特征进行跟踪。
通常情况下,KLT使用金字塔方法来保持跟踪,即使有大的移动。对于您指定的"窗口大小",它可能使用"maxLevel"时间。
从未在二进制图像上尝试过KLT。问题可能出在KLT实现上,它从错误的方向开始搜索,然后就丢了点。当您更改窗口大小时,搜索算法也会随之更改。在你的照片上,你只有4个最大兴趣点,只有1个像素。
以下是您感兴趣的参数:
winSize – Size of the search window at each pyramid level
maxLevel – 0-based maximal pyramid level number. If 0, pyramids are not used (single level), if 1, two levels are used etc.
criteria – Specifies the termination criteria of the iterative search algorithm (after the specified maximum number of iterations criteria.maxCount or when the search window moves by less than criteria.epsilon
建议:
- 你尝试过自然的照片吗?(例如两张照片),您将有更多的功能可供跟踪。4或以下是很难保持的。我会先试试这个
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- CMake 問題:找不到 Visual Studio 的任何執行個體
- 找不到 QRegularExpression 行为的任何解释。它有效,但不应该
- 给定一个 3 x 3 矩阵或任何 n x n 矩阵,为什么我的以下函数找不到对角线差异?
- ncurses 找不到任何关于cchar_t的文档
- 我想使用 "cout" 命令慢慢打印文本,但我真的找不到任何解决方案
- 这个基于范围的'for'语句需要一个合适的函数,但找不到任何函数
- SWIG c++ 到 C# 错误找不到入口点SWIGRegisterExceptionCallbacks_xxxx
- 使用 Cmake 编译 LZO 时,它注意到找不到任何 VS 实例
- 如果找不到解决方案,我如何留下递归循环,而不会打印任何东西
- C++ minGW 找不到过程入口点
- 找不到浮点异常
- String.find() 在 C++ 中找不到任何内容时不会返回 -1
- Cereal 找不到任何输出序列化函数
- 运行 exe - C++ 时找不到入口点
- 错误的任何修复:二进制">>"找不到运算符
- 找不到 DLL 入口点
- 使用 libusb-win32 与 USB 到 DMX512 接口通信,找不到任何端点
- 找不到名为的入口点
- OpenCV 2.4.2 calcOpticalFlowPyrLK 找不到任何点