【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针对多运动的估计问题,提出了分段平滑的方法。
- 基于匹配的方法
基于匹配的光流计算方法包括基于特征和区域的两种。
基于特征的方法不断地对目标主要特征进行定位和跟踪,对目标大的运动和亮度变化具有鲁棒性。存在的问题是光流通常很稀疏,而且特征提取和精确匹配也十分困难。
基于区域的方法先对类似的区域进行定位,然后通过相似区域的位移计算光流。这种方法在视频编码中得到了广泛的应用。然而,它计算的光流仍不稠密。另外,这两种方法估计亚像素精度的光流也有困难,计算量很大。
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方法等。这些方法通过最小化误差函数或优化约束条件来求解像素的运动速度。稠密光流与稀疏光流: 光流法可以得到稠密光流和稀疏光流。稠密光流计算图像中所有像素的运动信息,而稀疏光流只计算选定像素点的运动信息。
总的来说,光流法是一种基于局部运动假设的计算图像运动的方法。然而,它对光照变化和遮挡等情况敏感,因此在实际应用中,通常需要结合其他方法来处理复杂场景。
相关文章:

【OpenCv光流法进行运动目标检测】
opencv系列文章目录 文章目录 opencv系列文章目录前言一、光流法是什么?二、光流法实例1.C的2.C版本3.python版本 总结 前言 随着计算机视觉技术的迅猛发展,运动目标检测在图像处理领域中扮演着至关重要的角色。在现实世界中,我们常常需要追…...

Word论文封面下划线怎么都对不齐
我们常常发现,无论是写论文还是平时填写word封面的信息的时候,下划线老是随着字符的多少的边长变短,我们使用空格键也非常不好对齐,这就给我们造成了很大的烦恼,想想自己也是这样,我一旦输入字符࿰…...

汇编经典程序——将一个字节数据以十六进制形式显示
法一: 由于0-9的ASCII码实际值30h,A-Z的ASCII码实际值37h,故直接加对应的数即可 ;该程序将一个字节数据以十六进制形式显示(直接加对应数值).model small .stack .data hex db 4bh.code .startup;显示高位mov al,hex…...

Remix 开发小技巧(五)
文章目录 类型安全的 Fetcher 钩子一切从资源路由开始RPC 只是使用内置的 URL 获取使用 Zod 验证您的 RPC下一步是自定义提取器钩子 黑暗模式主题切换“最佳用户体验”是什么意思?第一个要求第二个要求第三个要求第四个要求 类型安全的 Fetcher 钩子 RPC 是一种远程…...

hive抽取mysql里的表,如果mysql表没有时间字段如何做增量抽取数据
如果MySQL表中没有时间字段,你可以通过其他方式实现增量抽取数据,以下是一些常见的方式: 使用自增主键:如果MySQL表中有自增主键,你可以记录上一次抽取数据时最大的主键值(即上一次抽取数据的结束位置&…...

20和遍历以及迭代器有关的一些东西
知识点有点散,只能这样记录了 1、这边是和遍历有关的: class Person:def __init__(self):self.result 1def __getitem__(self, item):self.result 1if self.result > 6:raise StopIteration(停止遍历)return self.resultpassp Person() for i in…...

前端工程化(editorconfig+ESLint+Prettier+StyleLint+Husky、Commitlint)
前言 致谢:有来技术大大 通过学习有来技术大大的文章和结合自己的实践,写一篇笔记记录一下 所使用的工具: ide项目风格(editorconfig)代码检查(ESLint)代码风格(Prettier)样式风格(StyleLint)git提交规范(Husky、Commitlint) 一、ide项目…...

UI自动化测试:Selenium+PO模式+Pytest+Allure整合
本人目前工作中未涉及到WebUI自动化测试,但为了提升自己的技术,多学习一点还是没有坏处的,废话不多说了,目前主流的webUI测试框架应该还是selenium,考虑到可维护性、拓展性、复用性等,我们采用PO模式去写我…...

【排序算法】详解冒泡排序及其多种优化稳定性分析
文章目录 算法原理细节分析优化1优化2算法复杂度分析稳定性分析总结 算法原理 冒泡排序(Bubble Sort) 就是从序列中的第一个元素开始,依次对相邻的两个元素进行比较,如果前一个元素大于后一个元素则交换它们的位置。如果前一个元素小于或等于后一个元素…...

使用 Go 和 Wails 构建跨平台桌面应用程序
由于多种原因,Electron 曾经(并且仍然)大受欢迎。首先,其跨平台功能使开发人员能够从单个代码库支持 Linux、Windows 和 macOS。最重要的是,它对于熟悉 Javascript 的开发人员来说有一个精简的学习曲线。 尽管它有其缺…...

花2个月时间学习,面华为测开岗要30k,面试官竟说:你不是在搞笑。。。
背景介绍 计算机专业,代码能力一般,之前有过两段实习以及一个学校项目经历。第一份实习是大二暑期在深圳的一家互联网公司做前端开发,第二份实习由于大三暑假回国的时间比较短(小于两个月),于是找的实习是…...

【Python学习笔记】字符串
1. 字符串定义 可以用双引号 、 单三引号、双三引号,下面的定义都是正确的 "你好" 你好 """你好"""其中三引号可以 直接写内容有多行 的字符串。如下 letter 刘总:您好!您发的货我们已经收到&am…...

【AUTOSAR中断管理】TC3XX中断系统介绍
摘要 这段文本主要介绍了AURIX TC3XX的中断系统(Interrupt Router,简称IR)以及中断注册的过程以及举例说明中断机制。 AURIX TC3XX 中断系统(Interrupt Router)介绍 流程图描述中断路由器(IR)处理服务请求并与服务提供者交互。 中断系统的作用是将service request进行…...

Unity实现摄像机向屏幕中间发射射线射击物体
1.创建一个准星放在屏幕中间 外部找个PNG透明图,拖到Unity文件夹,右上角改成精灵sprite2d 2.添加到UI画布 3.写脚本 首先,我们需要引入一些 "工具",就像我们在玩游戏时要先下载游戏客户端一样。这里的 "工具&quo…...

测试时数据增广(TTA)与mmdetection3d中的实现
1. 测试时数据增广 测试时数据增广(TTA)在测试时使用数据增广技术获取同一数据的多个“变体”,使用同一网络在这些“变体”以及原始数据上进行推断,最后整合所有结果作为该原始数据最终的预测结果。 TTA类似于集成学习,…...

深入探索BP神经网络【简单原理、实际应用和Python示例】
人工神经网络(Artificial Neural Networks)是一种受到生物神经网络启发的机器学习模型,它的应用范围广泛,包括图像识别、语音识别、自然语言处理等领域。其中,BP神经网络(Backpropagation Neural Network&a…...

【LVGL】SquareLine Studio入门基础操作
1.SquareLine Studio基础 在这篇文章中将介绍SquareLine Studio的基础操作、解释如何加载一个项目、布局结构。 启动软件后,可以加载之前的项目、创建项目、加载一个示例。 这里以打开示例audio_mixer为例,可以双击该项目打开或者选中该项目点击右下角的【创建】按…...

【单片机】19-TFT彩屏
一、背景知识--显示器 1.什么是TFT (1)LCD显示器的构成:液晶面板驱动器【电压驱动】控制器【逻辑控制】 (2)液晶面板大致分为:TN,TFT,IPS等 (3)驱动器是跟随…...

高质量!推荐一些免费自学网站
大家好,我是 jonssonyan 说到自学网站,大家第一印象肯定是”菜鸟教程“、”w3school“、B 站大学。这些教程当然非常的好,而且适合入门学习,但是存在一些缺点,第一,知识点比较分散,没有一个整体…...

Linux之open/close/read/write/lseek记录
一、文件权限 这里不做过多描述,只是简单的记录,因为下面的命令会涉及到。linux下一切皆是文件包括文本、硬件设备、管道、数据库、socket等。通过ls -l 命令可以查看到以下信息 drwxrwxrwx 1 root root 0 Oct 10 17:06 open -rwxrwxrwx 1 root roo…...

3D调研-摄像头
参考资料: 来源1:https://leap2.ultraleap.com/leap-motion-controller-2 来源2: Gemini 2 _双目结构光相机_机器人感知-奥比中光官网 来源3: 国内外深度相机大盘点,仅用于学习科普!--机器视觉网 来源4&…...

光耦合器继电器与传统继电器:哪种最适合您的项目?
在电子和电气工程领域,继电器的选择可以显着影响项目的性能和安全性。两种常见类型的继电器是光耦合器继电器和传统机电继电器。每个都有其优点和缺点,因此选择过程对于项目的成功结果至关重要。 光耦合器继电器:基础知识 光耦合器继电器&…...

分享关于职场心态
1.解决问题而不是解释原因 2.秉承工匠思维而不是激情思维 什么是工匠思维? 工匠思维(The craftsman mindset)对待职业生涯的一种方式;是以产出为中心的职业观,关注自己给世界(工作)带来的价值…...

OK3568 UBUNTU 安装使用I2C-TOOLS
1. 安装 sudo apt-get update sudo apt-get install i2c-tools 使用I2Ctools 参考:https://blog.csdn.net/anyuliuxing/article/details/106382827 i2c-tools 是一组用于在Linux系统中进行I2C(Inter-Integrated Circuit)总线设备操作和调试…...

mysql面试题53:一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录 可以按照以下步骤进行: 确保…...

Docker服务更新与发现
一,docker-consul简介 这是一个基于分布式的服务发现和管理工具,它具有快速构建分布式框架,提供服务发现和服务治理等特点。同时consul还提供了可靠的保证,多数据中心和强大的API以满足高可用,分布式环境下的需求。 …...

【2023集创赛】安谋科技杯二等奖作品: 智能体感游戏机
本文为2023年第七届全国大学生集成电路创新创业大赛(“集创赛”)安谋科技杯二等奖作品分享,参加极术社区的【有奖征集】分享你的2023集创赛作品,秀出作品风采,分享2023集创赛作品扩大影响力,更有丰富电子礼…...

如何使用前端包管理器(如npm、Yarn)?
聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 欢迎来到前端入门之旅!感兴趣的可以订阅本专栏哦!这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…...

Codeforces Round 903 (Div. 3) C(矩形旋转之后对应的坐标)
题目链接:Codeforces Round 903 (Div. 3) C 题目: 思想: 旋转之后对应的坐标: (i,j)(n1-j,i)(n1-i,n1-j)(j…...

月薪过万的Java面试
写了一个月,篇幅太长了,都写不下了,被逼无奈,只能拆分 面试题: HashMap底层实现原理,红黑树,B树,B树的结构原理,volatile关键字,CAS(比较与…...