单目标跟踪--KCF算法(核化相关滤波算法)Python实现(超详细)

article/2025/11/11 3:54:42

Tracking-KCF Algorithm

注:本文涉及的算法的代码实践已上传至GitHub,恳求大佬们指点!^ _ ^

1. 目标检测跟踪与算法背景概述

​ 目标跟踪任务在许多的计算机视觉系统中都是极为关键的一个组成部分。对于任意给定的一个初始图像的Patch(Filter滑过的区域),目标跟踪任务的目的在于训练一个分类器来将待跟踪的目标与它所处的环境区分开,为了能够在后续帧中能继续检测到这个目标,分类去需要能够在很多位置上都能进行详尽的评估,同时在滑动的过程中都会提供一个新的图像Patch来帮助提升模型的性能。

​ 在上述任务中,我们将感兴趣的对象——即待追踪的目标称作正样本(positive samples),将目标所在的环境或者背景称作负样本。一幅图像中包含的负样本数量几乎是无限的,在达到合并尽可能多的样本保持较低的计算量之间的平衡上,前人作出了很多尝试。KCF算法中,引入了轮转矩阵(circulant matrices)这一工具来合并大量的样本,实现了一个基于“核岭回归”的跟踪器(tracer),该跟踪器可以认为是一个核化版的线性相关滤波器(Linear Correlation Filter )。

​ Correlation Filter(CF)源于信号处理领域,其用于tracking方面的想法是:相关是衡量两个信号相似值的度量,如果两个信号越相似,那么其相关值就越高。在tracking的应用里,设计一个滤波模板,利用该模板与目标候选区域做相关运算,最大输出响应的位置即为当前帧的目标位置。

​ 用数学语言来表述, x x x表示一幅图像, w \mathcal{w} w表示相应的滤波模板, y y y表示模板与相关候选区域进行相关运算后的相应输出,则有如下关系: y = x ⊗ w y=x\otimes\mathcal{w} y=xw,为减小计算量,可将 x , y , w x,y,\mathcal{w} x,y,w分别转换到其傅里叶空间后计算点积,即 y ^ = x ^ ⋅ w ^ ∗ \hat{y} = \hat{x}· \hat{\mathcal{w}}^* y^=x^w^。相关滤波的任务则是寻找最优的滤波模板 w \mathcal{w} w

​ 目下以相关滤波类的方法和深度学习方法为代表的判别类模型方法效果普遍好于生成模型,其显著特点是分类器的训练过程中运用到了前景与背景信息,分类器的任务专注于区分前景与背景。Kernelized Correlation Filter(KCF)是相关滤波方法中的典型算法,该方法的一般流程是:在跟踪的过程中训练一个目标检测器,使用目标检测器去检测下一帧预测位置是否是目标,然后再使用新检测结果去更新训练集进而更新目标检测器。

2. HOG特征

​ KCF算法中使用了图像的HOG特征替代了传统跟踪器所用的灰度特征。

​ HOG特征全称为Histogram of Oriented Gradients,即方向梯度直方图。作为一种图像的特征描述子(图像的一种表示,通过提取有用的信息并扔掉多余的信息来简化图像),HOG特征将一张大小为 w i d t h × h e i g h t × c h a n n e l s width \times height \times channels width×height×channels的图像转化为一个长度为 n n n的特征向量,例如输入图像大小为 64 × 128 × 3 64 \times 128 \times 3 64×128×3,HOG特征的输出为长度 3780 3780 3780的向量。HOG特征的计算过程如下:

(1)图像预处理

​ 最早提出的HOG特征通过在一张 64 × 128 64 \times 128 64×128的图像上计算得到,预处理的操作要求图片保持1:2的横纵比,原文中提及的 γ \gamma γ矫正已知其增益效果较小,不再考虑。

(2)计算梯度图

​ 首先计算图像的水平方向梯度 g x g_x gx和竖直方向的梯度 g y g_y gy,以如下公式来计算梯度的强度值 g g g和梯度方向 θ \theta θ
g = g x 2 + g y 2 θ = a r c t a n g x g y g=\sqrt{g_x^2+g_y^2}\\ \theta = arctan \frac{g_x}{g_y} g=gx2+gy2 θ=arctangygx
​ 同时梯度方向有如下的性质: θ ∈ [ 0 , π ] \theta \in [0,\pi] θ[0,π]

(3)计算梯度直方图

​ 这一步中,首先将图像分割成多个 8 × 8 8 \times 8 8×8的cell,在这些cell中计算梯度直方图。(2)中计算的每个像素点的位置处包含了2个值: g 和 θ g和\theta gθ,一个cell就保存了128个值,单个像素的梯度信息往往包含了噪声,采用 8 × 8 8 \times 8 8×8的图片块表示后能够是的直方图对噪声不敏感。

​ 由(2)的性质,将0-180度分成9个区间:0,20,40,…160,之后统计每个像素点所在的区间——将这个区间命名为bin,采取的原则是对每个像素点处的 g g g值,按 θ \theta θ的比例将 g g g分配给相邻的bin,如下图所示。

​ 最终统计得到如下图所示的直方图:

(4)对 16 × 16 16 \times 16 16×16大小的Block进行标准化

​ 标准化(Normalization)也称归一化,即将每个向量的分量除以向量的模长。Block选取示意图如下:

(5)得到HOG向量

​ 将(4)中计算的单个Block的向量连接起来得到整个图片块的最终的特征向量,其中可以由这样的认识:每个16×16块由36×1向量表示。

​ OpenCV中封装了提取HOG特征的类HOGDescriptor,实现过程中只需构造一个hog对象来实现,见于HOG.py文件中的构造方法:

    def __init__(self, winSize):self.winSize = winSizeself.blockSize = (8, 8)self.blockStride = (4, 4)self.cellSize = (4, 4)self.nbins = 9self.hog = cv2.HOGDescriptor(winSize,self.blockSize, self.blockStride,self.cellSize, self.nbins)

3. 傅里叶变换

3.1 傅里叶变换概念简述

傅里叶变换(Fourier transform,FT)是一种线性积分变换,用于函数(应用上称作“信号”)在时域和频域之间的变换,在物理学和工程学中有许多应用,其作用是将函数分解为不同特征的正弦函数的和,如同化学分析来分析一个化合物的元素成分。对于一个函数,也可对其进行分析,来确定组成它的基本(正弦函数)成分。

​ 经过傅里叶变换生成的函数 f ^ \hat {f} f^称作原函数 f f f的傅里叶变换,应用意义上称作频谱。在特定情况下,傅里叶变换是可逆的,即将 f ^ \hat{f} f^通过逆变换可以得到其原函数 f f f。通常情况下, f f f是一个实函数,而 f ^ \hat{f} f^ 则是一个复数值函数,其函数值作为复数可同时表示振幅和相位。高斯函数是傅里叶变换的本征函数(也称固有函数,即对已定义的函数空间中任意一个非零函数 f f f 进行变换仍然是函数 f f f或者其标量倍数的函数。更加精确的描述就是 A f = λ f \mathcal{A}f = \lambda f Af=λf其中 λ \lambda λ是标量,它是对应的特征值),即若一个函数(或分布)在真实空间中是一个高斯函数,则在傅里叶空间中它还是一个高斯函数,如下图所示:

​ 维基百科中对连续可积函数 f f f的傅里叶变换给出的定义形式如下:
f ^ ( ξ ) = ∫ − ∞ ∞ f ( x ) e − 2 π i x ξ d x , ξ 为 定 义 在 频 域 上 的 任 意 实 数 \hat{f}(\xi)=\int _{-\infty}^{\infty}f(x)e^{-2 \pi ix\xi}dx, \xi为定义在频域上的任意实数 f^(ξ)=f(x)e2πixξdxξ
​ 同时在适当的条件下, f ^ \hat{f} f^的逆傅里叶变换可得到 f f f
f ( x ) = ∫ − ∞ ∞ f ^ ( ξ ) e − 2 π i x ξ d ξ , x 为 定 义 在 时 域 上 的 任 意 实 数 f(x)=\int _{-\infty}^{\infty}\hat{f}(\xi)e^{-2 \pi ix\xi}d\xi, x为定义在时域上的任意实数 f(x)=f^(ξ)e2πixξdξx

3.2 傅氏空间与离散傅里叶矩阵

​ 傅里叶变换的奇妙之处就在于,将真实空间中复杂的波形通过“分解”之后可以得到若干简单的正弦波,这个“分解”操作是为傅里叶变换,从而“傅里叶空间”也可理解为“频率空间”,如下图所示:

离散傅里叶变换矩阵则是将离散傅里叶变换以矩阵乘法来表示的一种表达形式,其一般形式为:
F = 1 n [ 1 1 . . . 1 1 1 w . . . w n − 2 w n − 1 1 w 2 . . . w 2 ( n − 2 ) w 2 ( n − 1 ) . . . . . . . . . . . . . . . 1 w n − 1 . . . w ( n − 1 ) ( n − 2 ) w ( n − 1 ) 2 ] F=\frac{1}{\sqrt{n}}\begin{bmatrix} 1&1&...&1&1\\ 1&\mathcal{w}&...&\mathcal{w}^{n-2}&\mathcal{w}^{n-1}\\ 1&\mathcal{w}^2&...&\mathcal{w}^{2(n-2)}&\mathcal{w}^{2(n-1)}\\ {...}&{...}&{...}&{...}&{...}&\\ \\ 1&\mathcal{w}^{n-1}&...&\mathcal{w}^{(n-1)(n-2)}&\mathcal{w}^{(n-1)^2}\end{bmatrix} F=n 1111...11ww2...wn1...............1wn2w2(n2)...w(n1)(n2)1wn1w2(n1)...w(n1)2

4.快速核相关计算

​ 在part1中提及,实现快速相关计算的方法为:将模板、图像以及相应输出转换到傅里叶空间做点积运算。同时,KCF中创新性地使用了 循环转换模型(cyclic shift model),即前文提及的循环矩阵来解决了计算量的问题,将计算复杂度由 O ( n 2 ) \mathcal{O}(n^2) O(n2)降为了 O ( n l o n g n ) \mathcal{O}(nlong\mathcal {n}) O(nlongn)

​ 具体来说,由如下定理:循环矩阵都能够在傅氏空间中使用离散傅里叶矩阵进行对角化,即 X = F d i a g ( x ^ ) F H X = Fdiag(\hat{x})F^H X=Fdiag(x^)FH

​ 对于多项式 K ( X , X ′ ) = ( X T X ′ + a ) b \mathcal{K}(X,X')=(X^TX'+a)^b K(X,X)=(XTX+a)b,可有如下的表示形式: K X X ′ = ( F − 1 ( x ^ ∗ ⊙ x ′ ^ ) + a ) b \mathcal{K}^{XX'} = (\mathcal{F^{-1}}(\hat{x}^* \odot\hat{x'})+a)^b KXX=(F1(x^x^)+a)b,相关的证明过程参见原文,其中的 F − 1 \mathcal{F^{-1}} F1代表离散傅里叶逆变换(IDFT), x ^ ∗ 与 x ′ ^ \hat{x}^* 与\hat{x'} x^x^代表各自在傅里叶空间中的映射。

​ 径向基函数可以认为是 ∣ ∣ x i − x j ∣ ∣ 2 ||x_i-x_j||^2 xixj2的函数,对于一些核函数h,径向基核如有如下的形式:
k ( X , X ′ ) = h ( ∣ ∣ x i − x j ∣ ∣ 2 ) \mathcal{k}(X,X')=h(||x_i-x_j||^2) k(X,X)=h(xixj2)
​ 于是在高斯核中,径向基函数的形式为: K x x ′ = e x p ( − 1 σ 2 ( ∣ ∣ x i ∣ ∣ 2 + ∣ ∣ x j ∣ ∣ 2 ) − 2 ( F − 1 ( x ^ ∗ ⊙ x ′ ^ ) ) T ) K^{xx'}=exp(-\frac{1}{\sigma^2}(||x_i||^2+||x_j||^2)-2(\mathcal{F}^{-1}(\hat{x}^* \odot\hat{x'}))^T) Kxx=exp(σ21(xi2+xj2)2(F1(x^x^))T),其中关于循环矩阵对角化及其推导的内容参见原文。这一部分计算的实现过程如下:

    def kernel_correlation(self, x1, x2, sigma):"""核化的相关滤波操作:param x1::param x2::param sigma:   :return:"""# 转换到傅里叶空间fx1 = fft2(x1)fx2 = fft2(x2)# 相乘并返回共轭复数tmp = conj(fx1) * fx2# 离散傅里叶逆变换转换回真实空间idft_rbf = ifft2(np.sum(tmp, axis=0))# 将零频率分量移到频谱中心。idft_rbf = fftshift(idft_rbf)d = np.sum(x1 ** 2) + np.sum(x2 ** 2) - 2.0 * idft_rbf# 径向基函数k = np.exp(-1 / sigma ** 2 * np.abs(d) / d.size)return k

5. 响应值的计算与分类器训练

​ 训练的过程即是在核空间中做岭回归。具体来说,线性不可分的样本,经过非线性映射函数 ϕ ( x ) \phi (x) ϕ(x)后可变为线性可分的样本,此时所处的新空间即时核空间,此时的任务是:在核空间中使用岭回归寻找一个分类器 f ( x i ) = w T ϕ ( x i ) f(x_i)=\mathcal{w}^T \phi(x_i) f(xi)=wTϕ(xi),目标在于寻找最优的 w \mathcal{w} w,根据梯度取零可以表示出 w \mathcal{w} w的向量表达式,详细推导过程参见原文。将 w \mathcal{w} w表示为如下形式后,可得到其对偶问题 w = ∑ i α i ϕ ( x i ) \mathcal{w}=\sum_i\alpha_i\phi(x_i) w=iαiϕ(xi),对偶表达为
α = m i n α ∣ ∣ ϕ ( X ) ϕ ( X ) T α − y ∣ ∣ 2 + λ ∣ ∣ ϕ ( X ) T α ∣ ∣ \alpha = min_{\alpha}||\phi(X)\phi(X)^T\alpha-y||^2+\lambda||\phi(X)^T\alpha|| α=minαϕ(X)ϕ(X)Tαy2+λϕ(X)Tα
同样令其梯度为零可求得其表达式: α ∗ = ( ϕ ( X ) ϕ ( x ) T + λ I ) − 1 y \alpha ^* = (\phi(X)\phi(x)^T+\lambda I)^{-1}y α=(ϕ(X)ϕ(x)T+λI)1y,由于并不清楚非线性映射函数 ϕ ( X ) \phi(X) ϕ(X)的具体形式,并且只关心刻画在核空间的核矩阵 ( ϕ ( X ) ϕ ( x ) T (\phi(X)\phi(x)^T (ϕ(X)ϕ(x)T,故令 K K K表示这个核矩阵。

​ KCF算法始终未离开一个工具——循环矩阵,借助循环矩阵的傅里叶对角化来简化计算,核矩阵虽然得到了表示但是仍旧不知道其具体数值、形式,接下来的任务就变成了将 K K K对角化——希望找到一个核函数能使得对应的核矩阵是循环矩阵。原文中给出了如下的定理:

  • Given circulant data C (x), the corresponding kernel matrix K is circulant if the kernel function satisfifies

    K ( x , x ′ ) = K ( M x , M x ′ ) K(x,x') = K(Mx, Mx') K(x,x)=K(Mx,Mx), for any permutation matrixM

​ 即:第一个样本和第二个样本都是由生成样本循环移位产生的,可以不是同一个样本。从而,在train函数中核矩阵的计算,以及 α \alpha α的计算方式有如下表示:

    def train(self, x, y, sigma, lambdar):"""原文所给参考train函数:param x::param y::param sigma::param lambdar::return:"""k = self.kernel_correlation(x, x, sigma)return fft2(y) / (fft2(k) + lambdar)

​ 在计算得到 α \alpha α之后,即可借助 α \alpha α来计算响应值:

    def detect(self, x, z, sigma):"""原文所给参考detect函数:param x::param z: x的HOG特征:param sigma: 高斯参数:return:"""k = self.kernel_correlation(x, z, sigma)# 傅里叶逆变换的实部,对应响应的值return np.real(ifft2(self.alphaf * fft2(k)))

​ 之后即可根据响应值来更新检测的目标,详细代码参见update()函数。

6. 运行结果

详见于result文件夹。

Reference

  1. High-Speed Tracking with Kernelized Correlation Filters: https://arxiv.org/pdf/1404.7584
  2. Histogram of Oriented Gradients explained using OpenCV (learnopencv.com) : https://learnopencv.com/histogram-of-oriented-gradients/
  3. 傅里叶变换 - 维基百科:https://zh.wikipedia.org/wiki/傅里叶变换
  4. 从真实空间到傅立叶空间 - 知乎: https://zhuanlan.zhihu.com/p/37061414
  5. KCF目标跟踪方法分析与总结 - 一只有恒心的小菜鸟 - 博客园 : https://www.cnblogs.com/YiXiaoZhou/p/5925019.html
  6. GitHub代码仓库: https://github.com/chuanqi305/KCF

Appendix:库函数说明以及原文相关说明

1. HOG.py

项目1对应内容
函数名cv2.HOGDescriptor.compute()
功能描述计算给定图像的HOG特征描述子
参数img: 待计算的图像Patch
winStride: 窗口滑动的步长
**padding **: Padding
返回值拼接好的n*1维HOG特征向量

2. KCF.py

项目1对应内容
函数名numpy.conj()
功能描述帮助用户对任何复数进行共轭
参数x[array_like]: 输入值
返回值numpy.ndarray: x的复共轭

3. runKCF.py

项目1对应内容
函数名cv2.VideoCapture(video_path or device index)
功能描述实例化一个VideoCapture对象
参数video_path:以.mp4/.avi结束的string类型 ,代表视频所在路径
or device index:指定camare的序号,值为0或-1
返回值VideoCapture对象
项目2对应内容
函数名cv2.VideoCapture.read()
功能描述逐帧读取视频,返回值分两部分:是否正确读取以及每一帧的图像
参数
返回值bool ret:是否正确读取&&是否读取到视频末尾
np.ndarray frame:每一帧的图像,是一个三维矩阵
项目3对应内容
函数名cv2.selectROI(windowName, img, showCrosshair=None, fromCenter=None)
功能描述在一幅图像中对特定图像区域以矩形框的形式进行截取
参数windowName:选择的区域被显示在的窗口的名字
img:要在什么图片上选择ROI
showCrosshair:是否在矩形框里画十字线.
fromCenter:是否是从矩形框的中心开始画
返回值tuple (min_x, min_y, w, h),依次表示:
矩形框中最小的x值
矩形框中最小的y值
矩形框的宽
矩形框的高
项目4对应内容
函数名cv2.rectangle(image, start_point, end_point, color, thickness)
功能描述在一幅图像上绘制一个矩形
参数image:待绘制矩阵的图像
start_point:矩形的起始坐标,tuple类型
end_point:矩阵的结束坐标,tuple类型
color:绘制边框线的颜色
thickness:边框线的粗细
返回值np.ndarray:image
项目5对应内容
函数名cv2.VideoCapture.isOpen()
功能描述判断摄像头是否初始化成功
参数
返回值bool res:True or False
项目6对应内容
函数名argparse.ArgumentParser()
功能描述创建一个命令行参数解释器
参数无(本例中)
返回值一个ArgumentParser对象
项目7对应内容
函数名argparse.ArgumentParser.parse_args()
功能描述给ArgumentParser对象中的参数赋值
参数无(本例中)
返回值argparse.Namespace 参数名等

4. 原文参考源码与超参数

参考源码:


http://chatgpt.dhexx.cn/article/Peo7E4Gg.shtml

相关文章

目标跟踪算法KCF原理详解

一直以来没有很想写这个,以为这个东西比较简单,还算是比较容易理解的一个算法,但是在知乎上回答过一个问题之后就有朋友私信我一些关于细节的东西,我一直以为关于细节的东西大家可以自己去理解,大家都是想快速了解这个…

KCF算法原理笔记

KCF算法全称是Kernelized Correlation Filters,是在2014年由Joao F. Henriques, Rui Caseiro, Pedro Martins, and Jorge Batista提出来的跟踪算法,这个算法不论是在跟踪效果还是跟踪速度上都有十分亮眼的表现。该算法主要使用循环矩阵对样本进行采集&am…

目标跟踪算法——KCF入门详解

一直以来没有很想写这个,以为这个东西比较简单,还算是比较容易理解的一个算法,但是在知乎上回答过一个问题之后就有朋友私信我一些关于细节的东西,我一直以为关于细节的东西大家可以自己去理解,大家都是想快速了解这个…

【KCF算法解析】High-Speed Tracking with Kernelized Correlation Filters笔记

前段时间研究了一下KCF算法,单单看论文有很多看不懂的地方。查阅参考了,很多博客和其他材料才算了解了文章的大题思路,现将个人的理解在此记录,作为笔记。 主要内容 0.1 目标跟踪的背景介绍 0.2 学习该算法需先了解的预备知识 …

前端项目如何做测试?

前端项目也叫web端项目(通俗讲就是网页上的功能)是我们能够在屏幕上看到并产生交互的体验。 前端项目如何做测试? 要讲清楚这个问题,先需要你对测试流程现有一个全局的了解,先上一张测试流程图: 接下来下…

gt2e支持升级鸿蒙,鸿蒙测试版下月发布,Mate40或率先升级

鸿蒙系统终于要来了,Mate 40或成为率先升级的机型,12月中下旬将推出开发者测试版本,网友评论称终于等到你,国产操作系统终于要来了。 前一阵子余承东说鸿蒙系统将不会在今年推出,当时这个消息说实话让很多人感到失望&a…

gt2e鸿蒙系统,华为Watch GT2e评测:轻松开启年轻人一手掌控的百变运动潮酷生活...

【TechWeb】4月23日,华为nova7发布会上,华为Watch GT系列家族新成员——华为Watch GT 2e手表也正式发布。这款手表主要面向95后Z世代年轻人群体,定位运动潮流内核,潮流的外观造型和丰富的运动功能上吸引了不少年轻人关注的目光,同时也吸引了小编尝鲜的好奇之心。 潮酷外观…

vue_test_unit_e2e常见问题npm run unit单元测试和npm run e2e集成测试问题

vue项目要进行unit和e2e常见问题 localStorage is not available for opaque origins console.error node_modules\vue\dist\vue.runtime.common.dev.js 通常根据vue init webpack myproject 生成的项目,选择了unit和e2e模块后,都会有些问题。 1.首先是…

谈谈端到端测试(End-to-End Testing)

谈谈端到端测试(End-to-End Testing) 当今的软件系统是复杂的,并且与许多子系统相互关联。如果任何子系统出现故障,整个软件系统都可能崩溃。这是一个主要的风险,可以通过端到端测试来避免。 端到端测试是一种技术&a…

“汽车人”眼中的网络安全---关于AUTOSAR E2E及测试开发实践

1.前言 上篇文章“聊聊网络安全的5W1H”对网络安全知识体系和技术脉络做了深入浅出的介绍,提到AUTOSAR所定义的网络和通信安全相关的技术,本期我们将介绍其中的E2E策略(严格来说属于Safety的范围),并分享在项目中的测…

【E2E】E2E通信保护协议学习1

文章目录 前言一、E2E简介和功能介绍1.E2E简介2.一些名词简写及其对应含义 二、一些功能规格1.通讯保护概述2.配置文档概述 总结 前言 在软件测试工作中,E2E是功能的一部分。 非E2E专业工程师,如果有哪里写的不对,请大家多多指正。 一、E2E简…

使用Nightwatch进行E2E测试

本文在线预览 E2E测试 不同于行为驱动测试(BDD)和单元测试独立运行并使用模拟/存根,端到端测试将试着尽可能从用户的视角,对真实系统的访问行为进行仿真。对Web应用来说,这意味着需要打开浏览器、加载页面、运行Java…

cypress进行e2e测试之理论

cypress 进行 e2e 测试之理论 cypress 是目前 e2e 很火的一个测试组件,内部绑定了 macha、chai、chai-jquery 之类的断言,为了让代码代码 更有说服力,减少提交测试错误,进行 e2e 测试显然是非常有必要的。 官网 GitHub 借鉴官网一句话来说…

自动化测试(二)01-前端测试分为单元测试、集成测试和E2E测试 测试工具对比-适合TDD或 BDD、断言、异步测试 测试工具的类型

自动化测试(二)01-前端测试分为单元测试、集成测试和E2E测试 & 测试工具对比-适合TDD或 BDD、断言、异步测试 & 测试工具的类型 前端自动化测试 测试是一个庞大的主题,包括各种分类的测试,诸如黑盒测试/白盒测试、单元测…

web前端测试——e2e测试

开发环境:安装有node的macbook(windows没测) 第一步: 创建自己需要测试的项目,如在桌面创建一个test目录作为我们的项目根目录。 打开sublim text ,并将项目拖到sublim text中,方便管理。 第…

E2E 端到端测试学习 - E2E 介绍、Cypress 案例基本使用

E2E 测试介绍 E2E E2E(end to end)端到端测试是最直观可以理解的测试类型。在前端应用程序中,端到端测试可以从用户的视角通过真实浏览器自动检查应用程序是否正常工作。 E2E 把整个系统当作一个黑盒,测试人员模拟真实用户在浏…

Unity射线与UI碰撞检测

问题产生背景:我们有的时候,需要实现射线与3D UI之间的碰撞,当射线碰撞到3D UI之后(将Canvas设置为World Space),调整到合适的位置。使用LineRender表示射线的直观显示,使用一把枪结合第一人称控…

unity中射线碰撞检测总结

这阵子通过看视频,看书对unity中射线碰撞检测,有了一些了解,这里我把它总结一下写下来,希望能帮助到你们,也希望通过各位大神来指正不足之处; 射线碰撞检测,就是由某一物体发射出一道射线&#…

Unity 射线与碰撞范围检测【踩坑记录】

射线检测 射线检测在2D和3D的区别比较大 一定要加上对应的Collider组件 对应的函数只检测对应的Collider,Physics.Raycast是不会检测到Collider 2D的(这个让我有一次debug了好久才发现) 对应API如下 Physics.Raycast(Vector3 origin,Vec…

Unity 碰撞位置

获取碰撞位置的方法1:使用 Collider.ClosestPoint Returns a point on the collider that is closest to a given location. 返回碰撞器上最接近给定位置的点。 下方是子弹打到物体上,生成撞击火星的代码: // 碰撞体的检测 private void O…