opencv之稠密光流跟踪

注:此教程是对贾志刚老师的opencv课程学习的一个记录,在此表示对贾老师的感谢.
稠密光流跟踪是将当前帧的所有像素点与前一帧比较,有变化的标记出来。对比的点比较多,不是对比变化的那几个特征点。所以速度较慢。没有稀疏光流的速度快。但有的时候效果比稀疏光流要好。

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

void drawOpticalFlowHF(const Mat &flowdata, Mat& image, int step);
int main(int argc, char** argv)
{
	VideoCapture capture;
	capture.open("/home/fuhong/code/cpp/opencv_learning/src/object_tracing/video/video_006.mp4");
	if (!capture.isOpened()) {
		printf("could not load image...\n");
		return -1;
	}

	Mat frame, gray;
	Mat prev_frame, prev_gray;
	Mat flowResult, flowdata;
	capture.read(frame);
	cvtColor(frame, prev_gray, COLOR_BGR2GRAY);
	namedWindow("flow", CV_WINDOW_AUTOSIZE);
	namedWindow("input", CV_WINDOW_AUTOSIZE);

	while(capture.read(frame))
	{
		cvtColor(frame, gray, COLOR_BGR2GRAY);
		if (!prev_gray.empty()) {
			calcOpticalFlowFarneback(prev_gray, gray, flowdata, 0.5, 3, 15, 3, 5, 1.2, 0);
			cvtColor(prev_gray, flowResult, COLOR_GRAY2BGR);
			drawOpticalFlowHF(flowdata, flowResult, 10);
			imshow("flow", flowResult);
			imshow("input", frame);
		}
		char c = waitKey(1);
		if (c == 27) {
			break;
		}
	}
	return 0;
}

void drawOpticalFlowHF(const Mat &flowdata, Mat& image, int step) {
	for (int row = 0; row < image.rows; row++) {
		for (int col = 0; col < image.cols; col++) {
			const Point2f fxy = flowdata.at<Point2f>(row, col);
			if (fxy.x > 1 || fxy.y > 1) {
				line(image, Point(col, row), Point(cvRound(col + fxy.x), cvRound(row + fxy.y)), Scalar(0, 255, 0), 2, 8, 0);
				circle(image, Point(col, row), 2, Scalar(0, 0, 255), -1);
			}
		}
	}
}

效果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现视频的稠密光流法跟踪需要以下步骤: 1. 创建一个PictureBox控件来显示视频帧。 2. 导入OpenCV库。 3. 打开视频文件,使用VideoCapture类来读取每一帧。 4. 对每一帧应用稠密光流法跟踪算法,使用CalcOpticalFlowFarneback方法来计算光流向量。 5. 为了可视化光流向量,可以在每一帧上绘制箭头来表示光流方向和大小。 6. 将处理后的帧显示在PictureBox控件中。 以下是实现视频的稠密光流法跟踪的C#代码示例: ```csharp using System; using System.Drawing; using System.Windows.Forms; using OpenCvSharp; namespace DenseOpticalFlowDemo { public partial class Form1 : Form { private VideoCapture _capture; private Mat _previousFrame; private Mat _currentFrame; private Mat _outputFrame; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 打开视频文件 _capture = new VideoCapture("test.mp4"); if (!_capture.IsOpened()) { MessageBox.Show("Failed to open video file!"); Close(); return; } // 读取第一帧并转换为灰度图像 _capture.Read(_previousFrame); Cv2.CvtColor(_previousFrame, _previousFrame, ColorConversionCodes.BGR2GRAY); // 创建输出帧 _outputFrame = new Mat(_previousFrame.Rows, _previousFrame.Cols, MatType.CV_8UC3); } private void timer1_Tick(object sender, EventArgs e) { // 读取下一帧并转换为灰度图像 _capture.Read(_currentFrame); Cv2.CvtColor(_currentFrame, _currentFrame, ColorConversionCodes.BGR2GRAY); // 计算稠密光流向量 var flow = new Mat(); Cv2.CalcOpticalFlowFarneback(_previousFrame, _currentFrame, flow, 0.5, 3, 15, 3, 5, 1.2, 0); // 可视化光流向量 for (int y = 0; y < _outputFrame.Rows; y += 10) { for (int x = 0; x < _outputFrame.Cols; x += 10) { var flowVec = flow.At<Point2f>(y, x); Cv2.Line(_outputFrame, new Point(x, y), new Point((int)(x + flowVec.X), (int)(y + flowVec.Y)), Scalar.Red, 2); Cv2.Circle(_outputFrame, new Point(x, y), 2, Scalar.Blue, 2); } } // 将处理后的帧显示在PictureBox中 pictureBox1.Image = BitmapConverter.ToBitmap(_outputFrame); // 更新上一帧为当前帧 _previousFrame = _currentFrame.Clone(); } } } ``` 在上述代码中,我们使用了一个Windows Forms应用程序,其中包含一个PictureBox控件和一个计时器控件。在窗体加载时,我们打开视频文件并读取第一帧作为上一帧,以便在下一次计时器事件时使用。在计时器事件中,我们读取下一帧并计算稠密光流向量,然后在每个像素位置绘制箭头来表示光流方向和大小。最后,我们将处理后的帧显示在PictureBox控件中,更新上一帧为当前帧。 请注意,稠密光流法跟踪是一项计算密集型任务,可能需要较长时间才能处理完整个视频。为了避免在UI线程上进行长时间计算,建议将计算过程放在单独的线程中执行,并使用Invoke方法在UI线程上更新PictureBox控件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值