Алгоритм оптического потока не будет работать для ваших тестовых изображений.
Первая проблема заключается в том, что ваши тестовые изображения имеют очень небольшую разницу в значениях соседних пикселей.Эти полностью черные линии и один цветной квадрат не дают подсказки алгоритму оптического потока, где области изображения перемещаются, так как алгоритм не способен обрабатывать все изображение сразу и вычисляет оптический поток с небольшими 15x15 (как вы установили его в calcOpticalFlowFarneback
) окно пикселей.
Вторая проблема заключается в том, что ваши тестовые изображения слишком сильно отличаются.Расстояние между позициями коричневого квадрата слишком велико.Опять же, Farneback не может его обнаружить.
Попробуйте код с некоторыми реальными видеокадрами или отредактируйте свои тесты, чтобы они были менее монотонными (установите некоторую текстуру в квадратные, фоновые и прямоугольные линии) и приблизьте квадратыдруг к другу на изображениях (попробуйте 2-10 пикселей).Вы также можете поиграть с calcOpticalFlowFarneback
аргументами (читай здесь ) в соответствии с вашими условиями.
Вы можете использовать этот код для сохранения оптического потока, который вы получаете к изображению для отладки:
Mat debugImage = Mat::zeros(fflow.size(), CV_8UC3);
float hsvHue, magnitude;
for (int x = 0; x < fflow.cols; x++)
{
for (int y = 0; y < fflow.rows; y++)
{
auto& item = fflow.at<Vec2f>(y, x);
magnitude = sqrtf(item[0] * item[0] + item[1] * item[1]);
hsvHue = atan2f(item[1], item[0]) / static_cast<float>(CV_PI)* 180.f;
// div 2 to fit 0..255 range
hsvHue = (hsvHue >= 0. ? hsvHue : (360.f + hsvHue)) / 2.f;
debugImage.at<Vec3b>(y, x)[0] = static_cast<uchar>(hsvHue);
debugImage.at<Vec3b>(y, x)[1] = 255;
debugImage.at<Vec3b>(y, x)[2] = static_cast<uchar>(255.f * magnitude);
}
}
cvtColor(debugImage, debugImage, CV_HSV2BGR);
imwrite("OpticalFlow.png", debugImage);
Здесь направление потока пикселей будет представлено цветом (оттенок), а расстояние перемещения пикселей будет представлено яркостью.
Попробуйте использовать изображения, которые я создал:
.
Также обратите внимание, что код
for (int y = 0; y < frame.rows; y++)
{
for (int x = 0; x < frame.cols; x++)
{
const Point2f fxy = fflow.at<Point2f>(y, x);
fy = CLAMP(y + fxy.y*0.5, 0, frame.rows);
fx = CLAMP(x + fxy.x*0.5, 0, frame.cols);
flowf.at<Vec3b>(fy, fx) = prevframe.at<Vec3b>(y, x);
...
не будет окрашивать некоторые flowf
пиксели, которые не имеютсоответствующие целевые позиции, в которые они переместились, и алгоритм оптического потока может создать такие ситуации.Я бы изменил его на:
for (int y = 0; y < frame.rows; y++)
{
for (int x = 0; x < frame.cols; x++)
{
const Point2f fxy = fflow.at<Point2f>(y, x);
fy = CLAMP(y - fxy.y*0.5, 0, frame.rows);
fx = CLAMP(x - fxy.x*0.5, 0, frame.cols);
flowf.at<Vec3b>(y, x) = prevframe.at<Vec3b>(fy, fx);
const Point2f bxy = bflow.at<Point2f>(y, x);
by = CLAMP(y - bxy.y*(1 - 0.5), 0, frame.rows);
bx = CLAMP(x - bxy.x*(1 - 0.5), 0, frame.cols);
flowb.at<Vec3b>(y, x) = frame.at<Vec3b>(by, bx);
}
}
С этим измененным кодом и моими тестами я получаю этот вывод: