Método de flujo óptico OpenCV C ++ para la detección de objetivos en movimiento

Método de flujo óptico OpenCV C ++ para la detección de objetivos en movimiento

¿Qué es el flujo óptico?

El flujo óptico (flujo óptico) es la velocidad instantánea del movimiento de píxeles de un objeto en movimiento espacial en el plano de observación de imágenes.

El método de flujo óptico utiliza los cambios en el dominio del tiempo de los píxeles en la secuencia de imágenes y la correlación entre cuadros adyacentes para encontrar la correspondencia entre el cuadro anterior y el cuadro actual, calculando así el movimiento de objetos entre cuadros adyacentes Un método de información .

Por lo general, la tasa de cambio instantáneo de la escala de grises en un punto de coordenadas específico en un plano de imagen bidimensional se define como un vector de flujo óptico.

En otras palabras: el flujo óptico se utiliza para especificar la velocidad de movimiento del patrón de movimiento en la imagen que varía en el tiempo, porque cuando el objeto se mueve, el patrón de brillo del punto correspondiente en la imagen también se mueve. El movimiento aparente de este modo de brillo de imagen es el flujo óptico.

Descripción del procedimiento

// Descripción del programa: del programa de muestra oficial en la carpeta Samples bajo el directorio de instalación de OpenCV, usando el método de flujo óptico para la detección de objetivos en movimiento
// Sistema operativo: Windows 10 64bit
// Lenguaje de desarrollo: C ++
// Versión IDE: Visual Studio 2019
/ / Versión OpenCV: 4.20

/ ********************************************** ***********************

  • Derechos de autor © 2011 Yang Xian
  • Reservados todos los derechos.
  • Archivo: opticalFlow.cpp
  • Breve: método de flujo óptico lk para la detección de objetivos en movimiento
  • Versión: 1.0
  • Autor: Yang Xian
  • Correo electrónico: [email protected]
  • Fecha: 2011/11/18
  • Historia:
    ********************************************* ************************ /

Código

#include <opencv2/video/video.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <cstdio>

using namespace std;
using namespace cv;

//-----------------------------------【全局函数声明】-----------------------------------------
//		描述:声明全局函数
//-------------------------------------------------------------------------------------------------
void tracking(Mat& frame, Mat& output);
bool addNewPoints();
bool acceptTrackedPoint(int i);

//-----------------------------------【全局变量声明】-----------------------------------------
//		描述:声明全局变量
//-------------------------------------------------------------------------------------------------
string window_name = "optical flow tracking";
Mat gray;	// 当前图片
Mat gray_prev;	// 预测图片
vector<Point2f> points[2];	// point0为特征点的原来位置,point1为特征点的新位置
vector<Point2f> initial;	// 初始化跟踪点的位置
vector<Point2f> features;	// 检测的特征
int maxCount = 500;	// 检测的最大特征数
double qLevel = 0.01;	// 特征检测的等级
double minDist = 10.0;	// 两特征点之间的最小距离
vector<uchar> status;	// 跟踪特征的状态,特征的流发现为1,否则为0
vector<float> err;

//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main()
{

	Mat frame;
	Mat result;

	VideoCapture capture(0);

	if (capture.isOpened())	// 摄像头读取文件开关
	{
		while (true)
		{
			capture >> frame;

			if (!frame.empty())
			{
				tracking(frame, result);
			}
			else
			{
				printf(" --(!) No captured frame -- Break!");
				break;
			}

			int c = waitKey(50);
			if ((char)c == 27)
			{
				break;
			}
		}
	}
	return 0;
}

//-------------------------------------------------------------------------------------------------
// function: tracking
// brief: 跟踪
// parameter: frame	输入的视频帧
//			  output 有跟踪结果的视频帧
// return: void
//-------------------------------------------------------------------------------------------------
void tracking(Mat& frame, Mat& output)
{

	//此句代码的OpenCV3版为:
	cvtColor(frame, gray, COLOR_BGR2GRAY);
	//此句代码的OpenCV2版为:
	//cvtColor(frame, gray, CV_BGR2GRAY);

	frame.copyTo(output);

	// 添加特征点
	if (addNewPoints())
	{
		goodFeaturesToTrack(gray, features, maxCount, qLevel, minDist);
		points[0].insert(points[0].end(), features.begin(), features.end());
		initial.insert(initial.end(), features.begin(), features.end());
	}

	if (gray_prev.empty())
	{
		gray.copyTo(gray_prev);
	}
	// l-k光流法运动估计
	calcOpticalFlowPyrLK(gray_prev, gray, points[0], points[1], status, err);
	// 去掉一些不好的特征点
	int k = 0;
	for (size_t i = 0; i < points[1].size(); i++)
	{
		if (acceptTrackedPoint(i))
		{
			initial[k] = initial[i];
			points[1][k++] = points[1][i];
		}
	}
	points[1].resize(k);
	initial.resize(k);
	// 显示特征点和运动轨迹
	for (size_t i = 0; i < points[1].size(); i++)
	{
		line(output, initial[i], points[1][i], Scalar(0, 0, 255));
		circle(output, points[1][i], 3, Scalar(0, 255, 0), -1);
	}

	// 把当前跟踪结果作为下一此参考
	swap(points[1], points[0]);
	swap(gray_prev, gray);

	imshow(window_name, output);
}

//-------------------------------------------------------------------------------------------------
// function: addNewPoints
// brief: 检测新点是否应该被添加
// parameter:
// return: 是否被添加标志
//-------------------------------------------------------------------------------------------------
bool addNewPoints()
{
	return points[0].size() <= 10;
}

//-------------------------------------------------------------------------------------------------
// function: acceptTrackedPoint
// brief: 决定哪些跟踪点被接受
// parameter:
// return:
//-------------------------------------------------------------------------------------------------
bool acceptTrackedPoint(int i)
{
	return status[i] && ((abs(points[0][i].x - points[1][i].x) + abs(points[0][i].y - points[1][i].y)) > 2);
}

resultado de ejecución

Se puede llamar al video de la cámara y también se puede leer el video local; lo siguiente es el video de captura de la cámara, el efecto de seguimiento del método de flujo óptico
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/m0_51233386/article/details/115069149
Recomendado
Clasificación