gpt4 book ai didi

c++ - OpenCV 2.4.2 calcOpticalFlowPyrLK 没有找到任何点

转载 作者:太空狗 更新时间:2023-10-29 23:41:23 24 4
gpt4 key购买 nike

我在 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;
}

ImageA: http://oi50.tinypic.com/14kv05v.jpg

ImageB: http://oi46.tinypic.com/4l3xom.jpg

ImageC: 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)

所以没有层次的方法(图像金字塔)的一个限制是图像需要是一个线性函数。实际上,这意味着只能估计小 Action ,具体取决于您选择的 winsize。这就是为什么要使用将图像线性化的级别 (It)。所以5级有点高3级应该足够了。在您的案例中,顶级图像的尺寸为 640x480/2^5 = 20 x 15。

最后,您的代码中的问题在于:

 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 的可能性很小。所以最后你跳过了所有特征。我通过忽略错误获得了很好的经验,这只是一种信心措施。有非常好的替代信心措施作为前向/后向信心。如果丢弃了太多的特征,你也可以通过忽略状态标志来开始实验

关于c++ - OpenCV 2.4.2 calcOpticalFlowPyrLK 没有找到任何点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11688767/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com