【OpenCv光流法进行运动目标检测】

opencv系列文章目录

文章目录

  • opencv系列文章目录
  • 前言
  • 一、光流法是什么?
  • 二、光流法实例
    • 1.C的
    • 2.C++版本
    • 3.python版本
  • 总结


前言

随着计算机视觉技术的迅猛发展,运动目标检测在图像处理领域中扮演着至关重要的角色。在现实世界中,我们常常需要追踪视频中的运动目标,例如交通摄像头中的车辆、安防监控中的行人,甚至是自动驾驶领域中的车辆和行人。为了实现高效准确的运动目标检测,研究者们提出了各种各样的方法。

在众多运动目标检测方法中,光流法(Optical Flow)是一种经典且有效的技术。光流法通过追踪图像中像素点的运动轨迹,可以帮助我们实时了解运动目标的位置和速度信息。它不仅在实时性上具有优势,还在处理各种环境和运动类型下都表现出色。


一、光流法是什么?

光流法(Optical Flow)是计算机视觉领域中一种经典的技术,用于描述图像序列中像素点在时间上的运动轨迹。光流法的基本思想源于图像中的像素在相邻帧之间随时间的变化,通过检测像素点的移动,我们可以获得关于场景中物体运动的重要信息。这种技术在目标跟踪、运动分析、视觉导航等领域得到广泛应用。

光流法的基本假设是,相邻帧之间相邻像素的灰度值在短时间内基本保持不变。根据这个假设,光流法通过分析图像序列中相邻帧之间的灰度值变化,推断出像素点的运动信息。它可以帮助我们了解运动目标的速度、方向和轨迹,甚至可以用于运动目标的跟踪和分割。

在实际应用中,光流法的算法有多种。其中,Lucas-Kanade方法是最常见的一种,它假设了图像中的运动是局部的,即在图像上某一点附近的像素具有相似的运动。该方法通过计算像素点周围区域的梯度和时间上的灰度变化,求解一个线性方程组,从而估计出光流向量。另外,Horn-Schunck方法则假设了整幅图像的运动是平滑的,并且在整个图像上求解一个全局的光流场。

光流法的应用非常广泛。在视频压缩中,光流信息可以用于帧内预测,提高压缩效率。在自动驾驶领域,光流法可以用于车辆和行人的运动轨迹预测,帮助车辆规划路径。在医学图像分析中,光流法可以用于心脏和血流的运动分析,帮助医生诊断心脏疾病。

总的来说,光流法作为一种经典的计算机视觉技术,为我们提供了探测运动目标、分析动态场景的重要手段。它的应用不仅帮助我们更好地理解图像序列中的运动信息,也推动了计算机视觉领域的发展。
几种光流估计算法的简介

1) 基于梯度的方法

基于梯度的方法又称为微分法,它是利用时变图像灰度(或其滤波形式)的时空微分(即时空梯度函数)来计算像素的速度矢量。

由于计算简单和较好的结果,该方法得到了广泛应用和研究。典型的代表是Horn-Schunck算法与Lucas-Kanade(LK)算法。

Horn-Schunck算法在光流基本约束方程的基础上附加了全局平滑假设,假设在整个图像上光流的变化是光滑的,即物体运动矢量是平滑的或只是缓慢变化的。

基于此思想,大量的改进算法不断提出。Nagel采用有条件的平滑约束,即通过加权矩阵的控制对梯度进行不同平滑处理;Black和Anandan针对多运动的估计问题,提出了分段平滑的方法。

  1. 基于匹配的方法

基于匹配的光流计算方法包括基于特征和区域的两种。

基于特征的方法不断地对目标主要特征进行定位和跟踪,对目标大的运动和亮度变化具有鲁棒性。存在的问题是光流通常很稀疏,而且特征提取和精确匹配也十分困难。

基于区域的方法先对类似的区域进行定位,然后通过相似区域的位移计算光流。这种方法在视频编码中得到了广泛的应用。然而,它计算的光流仍不稠密。另外,这两种方法估计亚像素精度的光流也有困难,计算量很大。

3)基于能量的方法

基于能量的方法又称为基于频率的方法,在使用该类方法的过程中,要获得均匀流场的准确的速度估计,就必须对输入的图像进行时空滤波处理,即对时间和空间的整合,但是这样会降低光流的时间和空间分辨率。基于频率的方法往往会涉及大量的计算,另外,要进行可靠性评价也比较困难。

4)基于相位的方法

基于相位的方法是由Fleet和Jepson提出的,Fleet和Jepson最先提出将相位信息用于光流计算的思想。当我们计算光流的时候,相比亮度信息,图像的相位信息更加可靠,所以利用相位信息获得的光流场具有更好的鲁棒性。基于相位的光流算法的优点是:对图像序列的适用范围较宽,而且速度估计比较精确,但也存在着一些问题:第一,基于相位的模型有一定的合理性,但是有较高的时间复杂性;第二,基于相位的方法通过两帧图像就可以计算出光流,但如果要提高估计精度,就需要花费一定的时间;第三,基于相位的光流计算法对图像序列的时间混叠是比较敏感的。

5)神经动力学方法

神经动力学方法是利用神经网络建立的视觉运动感知的神经动力学模型,它是对生物视觉系统功能与结构比较直接的模拟。

尽管光流计算的神经动力学方法还很不成熟,然而对它的研究却具有极其深远的意义。随着生物视觉研究的不断深入,神经方法无疑会不断完善,也许光流计算乃至计算机视觉的根本出路就在于神经机制的引入。神经网络方法是光流技术的一个发展方向。

3.稠密光流与稀疏光流

除了根据原理的不同来区分光流法外,还可以根据所形成的光流场中二维矢量的疏密程度将光流法分为稠密光流与稀疏光流两种。

二、光流法实例

1.C的

设置参数放到C#版本里面,效果好像没有C++效果来的明显,可能是一些参数的设置导致的。

代码如下(示例):

using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Windows.Forms;namespace WindowsFormsApp
{public partial class Form1 : Form{// 当前图片public Mat gray = new Mat();      // 预测图片public Mat gray_prev = new Mat();// point1为特征点的原来位置,point2为特征点的新位置public Point2f[] points1;public Point2f[] points2;// 初始化跟踪点的位置public Point2f[] initial;// 检测的最大特征数public int maxCount = 500;         // 特征检测的等级public double qLevel = 0.01;       // 两特征点之间的最小距离public double minDist = 10.0;     // 跟踪特征的状态,特征的流发现为1,否则为0public byte[] status;       public float[] err;public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){var capture = new VideoCapture(@"1.avi");// 计算帧率int sleepTime = (int)Math.Round(1000 / capture.Fps);// 声明实例 Mat类Mat image = new Mat();// 进入读取视频每镇的循环while (true){capture.Read(image);//判断是否还有没有视频图像 if (image.Empty())break;Mat result = tracking(image);// 在pictureBox1中显示效果图pictureBox1.Image = BitmapConverter.ToBitmap(result);Cv2.WaitKey(sleepTime);}}//--------------------------------------// function: tracking// brief: 跟踪// parameter: frame 输入的视频帧//            output 有跟踪结果的视频帧// return: void//--------------------------------------public Mat tracking(Mat frame){Mat output = new Mat();Cv2.CvtColor(frame, gray, ColorConversionCodes.BGR2GRAY);frame.CopyTo(output);// 添加特征点if (addNewPoints()){// 只用这个好像也没啥区别points1 = Cv2.GoodFeaturesToTrack(gray, maxCount, qLevel, minDist, new Mat(), 10, true, 0.04);initial = points1; 像素级检测特征点//Point2f[] po = Cv2.GoodFeaturesToTrack(gray, maxCount, qLevel, minDist, new Mat(), 3, true, 0.04); 亚像素级检测//points1 = Cv2.CornerSubPix(gray, po, new Size(5, 5), new Size(-1, -1), new TermCriteria());}if (gray_prev.Empty()){gray.CopyTo(gray_prev);}//光流金字塔,输出图二的特征点points2 = new Point2f[points1.Length];Cv2.CalcOpticalFlowPyrLK(gray_prev, gray, points1, ref points2, out status, out err);// 去掉一些不好的特征点int k = 0;for (int i = 0; i < points2.Length; i++){if (acceptTrackedPoint(i)){initial[k] = initial[i];points2[k++] = points2[i];}}// 显示特征点和运动轨迹for (int i = 0; i < k; i++){Cv2.Line(output, (Point)initial[i], (Point)points2[i],new Scalar(0, 0, 255));Cv2.Circle(output, (Point)points2[i], 3,new Scalar(0, 255, 0), -1);}// 把当前跟踪结果作为下一此参考Swap(ref points2, ref points1);Swap(ref gray_prev, ref gray);return output;}static void Swap<T>(ref T a, ref T b){T t = a;a = b;b = t;}//-------------------------------------// function: addNewPoints// brief: 检测新点是否应该被添加// parameter:// return: 是否被添加标志//-------------------------------------public bool addNewPoints(){if (points1 == null) return true;// 这个实际上是限制了点数,最好别开//return  points1.Length <= 10;//System.Diagnostics.Debug.WriteLine(points1.Length);return true;}//--------------------------------------// function: acceptTrackedPoint// brief: 决定哪些跟踪点被接受// parameter:// return://-------------------------------------bool acceptTrackedPoint(int i){return status[i] == 1 && ((Math.Abs(points1[i].X - points2[i].X) + Math.Abs(points1[i].Y - points2[i].Y)) > 5);}}
}

这段代码是一个基于OpenCVSharp的C#程序,实现了光流法(Optical Flow)在视频中的运动目标跟踪。下面对代码进行逐行解释:

using OpenCvSharp; 和 using OpenCvSharp.Extensions;:导入OpenCVSharp库的命名空间,该库是OpenCV的C#封装。public partial class Form1 : Form:定义一个名为Form1的Windows窗体类,该类继承自基类Form。类中声明了一系列变量,如gray和gray_prev是用于存储灰度图像的Mat对象,points1和points2是特征点的原始和新位置,initial是特征点的初始位置,status和err是用于存储光流算法的状态和误差的数组。public Form1():构造函数,初始化窗体。private void button1_Click(object sender, EventArgs e):按钮点击事件的处理函数,该函数实现了视频的读取和光流法运动目标跟踪。var capture = new VideoCapture(@"1.avi");:打开名为"1.avi"的视频文件。Mat image = new Mat();:创建一个Mat对象用于存储视频帧。while (true):无限循环,用于处理视频的每一帧。capture.Read(image);:读取视频的一帧。Mat result = tracking(image);:调用tracking函数进行运动目标跟踪。pictureBox1.Image = BitmapConverter.ToBitmap(result);:将跟踪结果显示在Windows窗体中。public Mat tracking(Mat frame):跟踪函数,接受一个视频帧作为输入,返回一个Mat对象,其中包含了运动目标的跟踪结果。Cv2.CvtColor(frame, gray, ColorConversionCodes.BGR2GRAY);:将彩色图像转换为灰度图像。addNewPoints():检测是否需要添加新的特征点。Cv2.CalcOpticalFlowPyrLK(gray_prev, gray, points1, ref points2, out status, out err);:使用Lucas-Kanade光流法计算特征点的新位置。acceptTrackedPoint(int i):根据状态和位置信息,决定哪些跟踪点被接受。将跟踪结果画在output图像上,返回output。Swap(ref points2, ref points1); 和 Swap(ref gray_prev, ref gray);:交换points2和points1、gray_prev和gray的引用。

总的来说,这段代码实现了一个简单的视频运动目标跟踪系统。它使用Lucas-Kanade光流法计算特征点的运动轨迹,将跟踪结果实时显示在Windows窗体中。需要注意的是,该代码仅实现了基本的光流跟踪功能,实际应用中可能需要更多的优化和改进,例如处理光照变化、遮挡等问题。

2.C++版本

代码如下(示例):

#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;int main()
{Mat frame;Mat result;VideoCapture capture("1.avi");if (capture.isOpened())	// 摄像头读取文件开关{capture >> frame;imshow(window_name, frame);waitKey(0);while (true){capture >> frame;if (frame.empty()) break;tracking(frame, result);imshow(window_name, result);if ((char)waitKey(50) == 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);
}//-------------------------------------
// 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);
}
VideoCapture capture("1.avi");:打开名为"1.avi"的视频文件。
while (true):无限循环,用于处理视频的每一帧。
cvtColor(frame, gray, COLOR_BGR2GRAY);:将彩色图像转换为灰度图像。
goodFeaturesToTrack(gray, features, maxCount, qLevel, minDist);:检测图像中的好的特征点。
calcOpticalFlowPyrLK(gray_prev, gray, points[0], points[1], status, err);:使用Lucas-Kanade光流法计算特征点的新位置。
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);:交换points[1]和points[0]、gray_prev和gray的引用,为下一帧的计算做准备。

这段代码实现了基于Lucas-Kanade光流法的简单目标跟踪系统。在每一帧图像中,它通过检测特征点,并使用光流法计算特征点的运动轨迹,然后在图像上绘制特征点的运动路径,从而实现了目标的跟踪。

3.python版本

import cv2
import numpy as np# 初始化全局变量
gray_prev = None  # 上一帧的灰度图像
points1 = None    # 上一帧的特征点
points2 = None    # 当前帧的特征点
st = None         # 特征点的状态# 判断特征点是否应该被接受
def acceptTrackedPoint(a, b, c):return (c == 1) and ((abs(a[0][0] - b[0][0]) - abs(a[0][1] - b[0][1])) > 2)# 交换两个变量的值
def swap(a, b):return b, a# 跟踪函数
def tracking(frame):global gray_prev, points1, points2, stgray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 将彩色图像转换为灰度图像output = frame.copy()# 添加特征点if gray_prev is None:gray_prev = gray.copy()else:# 计算光流points2, st, err = cv2.calcOpticalFlowPyrLK(gray_prev, gray, points1, None)# 去掉一些不好的特征点k = 0for i in range(points2.size):if i >= st.size:breakif acceptTrackedPoint(points1[i], points2[i], st[i]):points1[k] = points1[i]points2[k] = points2[i]k += 1points1 = points1[:k]points2 = points2[:k]# 显示特征点和运动轨迹for (new, old) in zip(points2, points1):a, b = new.ravel()c, d = old.ravel()output = cv2.line(output, (int(a), int(b)), (int(c), int(d)), (0, 0, 255), 1)output = cv2.circle(output, (int(c), int(d)), 3, (0, 255, 0), -1)# 把当前跟踪结果作为下一次参考points1, points2 = swap(points1, points2)gray_prev, gray = swap(gray_prev, gray)return outputif __name__ == "__main__":# 打开视频文件video = cv2.VideoCapture('1.avi')fps = video.get(cv2.CAP_PROP_FPS)  # 获取视频帧率success = Truewhile success:success, frame = video.read()  # 读取视频帧if not success:breakresult = tracking(frame)  # 进行目标跟踪cv2.imshow('result', result)  # 显示结果cv2.waitKey(int(1000 / int(fps)))  # 设置延迟时间,使播放速度与视频原始帧率一致video.release()  # 释放视频文件cv2.destroyAllWindows()  # 关闭所有窗口

这段代码通过光流法实现了视频中运动目标的跟踪。它使用Lucas-Kanade光流法来估计特征点的运动轨迹。首先,它将视频的每一帧转换为灰度图像。然后,它利用光流法计算相邻两帧之间的特征点的运动。接着,通过acceptTrackedPoint函数筛选出好的特征点,并将它们连接起来形成运动轨迹。最终,它在原始视频帧上绘制了特征点的运动轨迹,并通过窗口展示结果。整个过程实现了对视频中运动目标的简单跟踪。

import numpy as np
import cv2# 打开默认摄像头(通常是编号为0的摄像头)
cap = cv2.VideoCapture(0)# ShiTomasi角点检测的参数
feature_params = dict(maxCorners=100,  # 最多返回的角点数qualityLevel=0.3,  # 角点的质量水平minDistance=7,      # 角点之间的最小距离blockSize=7)        # 计算角点检测时的窗口大小# 光流法参数
lk_params = dict(winSize=(15, 15),       # 搜索窗口的大小maxLevel=2,             # 金字塔的最大层数criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))  # 迭代终止条件# 随机生成100个颜色,用于绘制跟踪点的轨迹
color = np.random.randint(0, 255, (100, 3))# 读取视频的第一帧
ret, old_frame = cap.read()
# 将第一帧转换为灰度图像
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
# 使用ShiTomasi角点检测方法找到角点
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
# 创建一个和视频帧大小相同的黑色掩码图片
mask = np.zeros_like(old_frame)while True:# 读取视频帧ret, frame = cap.read()# 将当前帧转换为灰度图像frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 计算光流以获取点的新位置p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)# 选择good points(即成功跟踪的点)good_new = p1[st == 1]good_old = p0[st == 1]# 绘制跟踪框和跟踪点的轨迹for i, (new, old) in enumerate(zip(good_new, good_old)):a, b = new.ravel()  # 获取新点的坐标c, d = old.ravel()  # 获取旧点的坐标# 在掩码图片上绘制轨迹mask = cv2.line(mask, (int(a), int(b)), (int(c), int(d)), color[i].tolist(), 2)# 在当前帧上绘制跟踪点frame = cv2.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)# 将轨迹绘制到当前帧上img = cv2.add(frame, mask)# 显示带有跟踪点轨迹的当前帧cv2.imshow('frame', img)# 按下ESC键退出循环k = cv2.waitKey(30) & 0xffif k == 27:break# 更新旧帧和旧点old_gray = frame_gray.copy()p0 = good_new.reshape(-1, 1, 2)# 关闭所有窗口,释放摄像头
cv2.destroyAllWindows()
cap.release()

上述代码实现了一个基于光流法的实时目标跟踪系统。该系统使用了OpenCV的光流法函数来追踪视频帧中的角点。下面是代码的主要步骤和功能总结:

摄像头初始化: 代码使用OpenCV的VideoCapture类初始化摄像头,获取视频帧。角点检测: 使用ShiTomasi角点检测方法在视频的第一帧中找到特征点(角点),这些点将作为跟踪的起始点。光流估计: 利用Lucas-Kanade光流法(cv2.calcOpticalFlowPyrLK函数)计算特征点在下一帧中的位置。特征点筛选: 根据光流法的输出,筛选出成功跟踪的特征点。绘制跟踪结果: 将跟踪点绘制在当前视频帧上,并用线连接跟踪点的轨迹,形成了目标的运动轨迹。循环处理: 通过循环不断读取视频帧,进行光流法跟踪,并在每一帧上绘制跟踪点的轨迹。用户退出: 当用户按下ESC键时,程序退出循环,关闭窗口,释放摄像头资源。

这段代码演示了光流法在实时视频中的应用,能够捕捉目标在连续帧之间的运动轨迹,具有实时性和动态性。在这个例子中,代码使用Lucas-Kanade光流法实现了简单的目标跟踪,可以通过调整检测参数、光流法参数以及绘制效果来适应不同的场景和需求。

总结

提示:这里对文章进行总结:

光流法(Optical Flow)是一种计算图像中像素运动的技术。它基于图像序列中相邻帧之间像素灰度值的变化,通过分析这些变化,推断出像素在图像中的运动情况。光流法常被用于运动目标跟踪、视频压缩、图像稠密匹配等计算机视觉领域的任务。以下是光流法的使用总结和原理介绍:
使用总结:

目标跟踪: 光流法可以用于实时目标跟踪,通过追踪图像中的特征点,了解目标在视频帧之间的运动轨迹。动作分析: 在视频分析中,光流法可用于分析人体、车辆等物体的运动轨迹和动作,从而实现动作识别、行为分析等应用。图像稠密匹配: 光流法可以用于计算两幅图像之间的稠密匹配,即找到两幅图像中每个像素的对应点,通常在立体视觉和结构运动恢复中应用广泛。运动估计: 光流法用于估计图像序列中物体的运动速度和方向,这对于视频压缩和运动估计相关研究非常重要。

原理介绍:

光流法基于以下假设和原理:

空间一致性假设: 在图像的局部区域内,相邻像素的运动是一致的。这意味着,相邻像素的灰度值变化是由相同的运动引起的。亮度恒定假设(Brightness Constancy Assumption): 在短时间内,运动物体的像素灰度值保持不变。这意味着,同一物体上的像素在不同帧之间的灰度值保持恒定,变化的灰度值是由于光照变化或阴影引起的。

基于上述假设,光流法通常使用以下步骤进行计算:

构建光流约束方程: 通过亮度恒定假设,可以得到一个描述相邻帧像素之间关系的方程。光流方程可以通过对图像中每个像素应用亮度恒定假设得到。求解光流方程: 光流方程通常是一个局部的非线性方程组。常见的求解方法有Lucas-Kanade方法、Horn-Schunck方法等。这些方法通过最小化误差函数或优化约束条件来求解像素的运动速度。稠密光流与稀疏光流: 光流法可以得到稠密光流和稀疏光流。稠密光流计算图像中所有像素的运动信息,而稀疏光流只计算选定像素点的运动信息。

总的来说,光流法是一种基于局部运动假设的计算图像运动的方法。然而,它对光照变化和遮挡等情况敏感,因此在实际应用中,通常需要结合其他方法来处理复杂场景。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/104055.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ES相关面试问题整理

索引模板了解么 索引模板&#xff0c;一种复用机制&#xff0c;就像一些项目的开发框架如 Laravel 一样&#xff0c;省去了大量的重复&#xff0c;体力劳动。当新建一个 Elasticsearch 索引时&#xff0c;自动匹配模板&#xff0c;完成索引的基础部分搭建。 模板定义&#xf…

基于LSTM-Adaboost的电力负荷预测的MATLAB程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 主要内容&#xff1a; LSTM-AdaBoost负荷预测模型先通过 AdaBoost集成算法串行训练多个基学习器并计算每个基学习 器的权重系数,接着将各个基学习器的预测结果进行线性组合,生成最终的预测结果。代码中的LST…

Grafana 10 新特性解读:体验与协作全面提升

作者&#xff1a;徽泠(苏墨馨) 为了庆祝 Grafana 的 10 年里程碑&#xff0c;Grafana Labs 推出了 Grafana 10&#xff0c;这个具有纪念意义的版本强调增强用户体验&#xff0c;使各种开发人员更容易使用。Grafana v10.0.x 为开发者与企业展示卓越的新功能、可视化与协作能力&…

虚幻引擎5:增强输入的使用方法

一、基本配置 1.创建一个输入映射上下文&#xff08;映射表&#xff09; 2.创建自己需要的操作映射或者轴映射 3.创建完成之后进入这个映射&#xff0c;来设置类型&#xff0c;共有4个类型 1.Digital:是旧版操作映射类型&#xff0c;一般是按下抬起来使用&#xff0c;像跳跃…

Linux实现原理 — I/O 处理流程与优化手段

Linux I/O 接口 Linux I/O 接口可以分为以下几种类型&#xff1a; 文件 I/O 接口&#xff1a;用于对文件进行读写操作的接口&#xff0c;包括 open()、read()、write()、close()、lseek() 等。 网络 I/O 接口&#xff1a;用于网络通信的接口&#xff0c;包括 socket()、conne…

RabbitMQ常见的交换机类型

RabbitMQ安装 pom.xml里导入相关的依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency> application.properties配置文件 spring.rabbitmq.hos…

Nginx - 反向代理与负载均衡

目录 一、Nginx 1.1、Nginx 下载 1.2、nginx 基础配置的认识 a&#xff09;第一部分&#xff1a;全局块 b&#xff09;第二部分&#xff1a;events 块 c&#xff09;第三部分&#xff1a;http 块 http 块中 内嵌的 server 块 1.3、一些常用配置 1.3.1、location 匹配级…

java正则表达式 及应用场景爬虫,捕获分组非捕获分组

正则表达式 通常用于校验 比如说qq号 看输入的是否符合规则就可以用这个 public class regex {public static void main(String[] args) {//正则表达式判断qq号是否正确//规则 6位及20位以内 0不能再开头 必须全是数子String qq"1234567890";System.out.println(qq…

【机器学习】sklearn特征选择(feature selection)

文章目录 特征工程过滤法&#xff08;Filter&#xff09;方差过滤相关性过滤卡方过滤F验表互信息法小结 嵌入法&#xff08;Embedded&#xff09;包装法&#xff08;Wrapper&#xff09; 特征工程 特征提取(feature extraction)特征创造(feature creation)特征选择(feature se…

【软件设计师-下午题总结】

目录 下午题之总结于学习记录&#xff1a;题一、数据流图&#xff1a;1、熟悉相关的图形2、实体名称3、数据存储4、补充缺失的数据流和起点终点5、用结构化语言描述6、描述&#xff0c;找加工逻辑的时候7、如何保持数据流平衡 题二&#xff1a;实体联系图&#xff1a;1、常用图…

Django Test

Django--Laboratory drug management and early warning system-CSDN博客 创建项目doinglms django-admin startproject doinglms python manage.py runserver 运行开发服务器(Development Server) 创建一个自定义 App,名称为 lms: python manage.py startapp lms

minio桶命名规则

一、背景 今天做项目需要上传图片到minio&#xff0c;上传失败&#xff0c;查看错误是桶未创建成功。 minio桶的创建具有自己的命名规则&#xff0c;不符合则无法创建。 二、命名规则 1、存储桶名称的长度必须介于 3&#xff08;最小&#xff09;到 63&#xff08;最大&…

【数据结构】二叉树--堆排序

目录 一 降序(建小堆) 二 升序 (建大堆) ​三 优化(以升序为例) 四 TOP-K问题 一 降序(建小堆) void Swap(int* x, int* y) {int tmp *x;*x *y;*y tmp; }//降序 建小堆 void AdjustUp(int* a, int child) {int parent (child - 1) / 2;while (child > 0){if (a[chil…

Ubuntu 22.04.3 LTS单机私有化部署sealos

推荐使用奇数台 Master 节点和若干 Node 节点操作系统 :Ubuntu 22.04 LTS内核版本 :5.4 及以上配置推荐 :CPU 4 核 , 内存 8GB, 存储空间 100GB 以上最小配置 :CPU 2 核 , 内存 4GB, 存储空间 60GB 这里采用的Ubuntu 22.04.3 LTS 版本&#xff0c;Ubuntu 20.04.4 LTS这个版本…

Eclipse插件安装版本不兼容问题解决方案——Papyrus插件为例

项目场景: Eclipse Papyrus安装后,没有新建Papyrus工程选项,也没有新建Papyrus Model的选项。 打开Papyrus Model会报错 问题描述 同样的,安装其他插件也是。可能某个插件之前安装是好用的,结果Eclipse的版本更新了,就再也安装不好用了 原因分析: 根本原因是因为包之…

Xcode 15下,包含个推的项目运行时崩溃的处理办法

升级到Xcode15后&#xff0c;部分包含个推的项目在iOS17以下的系统版本运行时&#xff0c;会出现崩溃&#xff0c;由于崩溃在个推Framework内部&#xff0c;无法定位到具体代码&#xff0c;经过和个推官方沟通&#xff0c;确认问题是项目支持的最低版本问题。 需要将项目的最低…

十七、【渐变工具组】

文章目录 渐变工具油漆桶工具 渐变工具 渐变样式有5种&#xff0c;分别是线性渐变&#xff0c;径向渐变&#xff0c;角度渐变&#xff0c;对称渐变&#xff0c;菱形渐变 另外渐变工具的颜色可以进行编辑&#xff0c;需要先打开渐变编辑工具&#xff1a; 如何使用渐变编辑工…

与HTTP相关的各种概念

网络世界 网络世界中最重要的一个名词就是互联网&#xff08;Internet&#xff09;,它以TCP/IP协议族为基础&#xff0c;构建成了一望无际的信息传输网络。而我们通常所说的“上网”&#xff0c;主要就是访问互联网的一个子集——万维网&#xff08;World Wide Web&#xff09…

如何使用CSS和JavaScript实施暗模式?

近年来&#xff0c;暗模式作为用户界面选项备受追捧。它提供了更暗的背景和更亮的文本&#xff0c;不仅可以减轻眼睛疲劳&#xff0c;还可以节省电池续航时间&#xff0c;尤其是在OLED屏幕上。 不妨了解如何结合使用CSS和JavaScript为网站和Web应用程序添加暗模式选项。 了解暗…

JWT的原理及实际应用

前言&#xff1a; 定义&#xff1a;JSON Web Token&#xff08;缩写 JWT&#xff09;是目前最流行的跨域认证解决方案 JWT官网 由于HTTP协议是无状态的&#xff0c;这意味着如果我们想判定一个接口是否被认证后访问&#xff0c;就需要借助cookie或者session会话机制进行判定&…