追踪器识别的目标ID在每一帧不连续/希望流式追踪识别
启用persist
参数后,追踪器会在不同帧之间保留目标状态。
1
| model.track(source=image, tracker="botsort.yaml", show=False,persist=True,verbose=False)
|
其他参数
- show:是否显示追踪结果
- verbose:是否打印详细信息
追踪器因目标丢失导致ID在时间上不连续
- 尝试换用
botsort
追踪器:该追踪器的算法更先进,有更加非线性的轨迹预测
- 尝试开启
ReID
功能:ReID可以在目标丢失后重新识别目标(基于外观相似性&轨迹预测),从而保持ID的连续性。
- 为追踪器进行经验调参
重置追踪器状态
当你要使用同一个追踪器串行地处理多个视频时,你可能希望在更换视频源时重置追踪器的状态:
1 2 3 4
| model = YOLO('yolov8n.pt')
model.predictor.trackers[0].reset()
|
获取追踪器的可视化结果:
1 2 3
| annotated_frame = frame.copy() for result in results: annotated_frame = result.plot(img=annotated_frame)
|
这样之后,就可以用opencv对其进行进一步操作了。
将向量图片转换为jpeg格式
实测转换为jpeg的开销比png小得多。质量设为60可以较好地平衡文件质量与大小的关系,可以满足实时传输。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def numpy_array_to_img_bytes(arr): arr = arr.astype(np.uint8) image = Image.fromarray(arr) buffer = io.BytesIO() image.save(buffer, format='JPEG', quality=60) img_bytes = buffer.getvalue() buffer.close() return img_bytes
|
透视校正
如果摄像头与目标平面之间有透视关系,需要进行透视矫正。以下代码将一个图像中的四边形区域映射到矩形区域。
原理见:透视变换数学原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| def perspectiveMap(rectangleApex: list, width: float, height: float, originalPoint: Tuple[float, float]) -> Tuple[float, float]: """ 将源图像中的点通过透视变换映射到目标长方形坐标系 :param rectangleApex: 源图像中的4个顶点坐标,格式为[[x1,y1], [x2,y2], [x3,y3], [x4,y4]] :param width: 目标长方形的宽度 :param height: 目标长方形的高度 :param originalPoint: 源图像中需要映射的点坐标 (x, y) :return: 映射到目标长方形坐标系后的坐标 (u, v) """ pts2 = np.float32([[0, 0], [width, 0], [width, height], [0, height]]) pts1 = np.float32(rectangleApex) A = [] for i in range(4): x, y = pts1[i] u, v = pts2[i] A.append([x, y, 1, 0, 0, 0, -u * x, -u * y, -u]) A.append([0, 0, 0, x, y, 1, -v * x, -v * y, -v]) A = np.array(A) U, S, Vt = np.linalg.svd(A) H = Vt[-1].reshape(3, 3) x, y = originalPoint denom = H[2, 0] * x + H[2, 1] * y + H[2, 2] u = (H[0, 0] * x + H[0, 1] * y + H[0, 2]) / denom v = (H[1, 0] * x + H[1, 1] * y + H[1, 2]) / denom return (u, v)
|
透视变换数学原理
利用透视变换将YOLOv8的检测结果进行矫正
1. 透视变换与线性方程组构建
在透视变换里,源图像点 (x,y) 与目标图像点 (u,v) 满足以下关系(在齐次坐标下):
⎣⎢⎡ωuωvω⎦⎥⎤=⎣⎢⎡h11h21h31h12h22h32h13h23h33⎦⎥⎤⎣⎢⎡xy1⎦⎥⎤
消去 ω 后得到:
{u=h31x+h32y+h33h11x+h12y+h13v=h31x+h32y+h33h21x+h22y+h23
设源图像的 4 个顶点坐标为 (xi,yi),目标图像的 4 个顶点坐标为 (ui,vi),i=1,2,3,4。将其代入并展开,得到线性方程组 Ah=0,其中:
A=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡x10x20x30x40y10y20y30y40101010100x10x20x30x40y10y20y30y401010101−u1x1−v1x1−u2x2−v2x2−u3x3−v3x3−u4x4−v4x4−u1y1−v1y1−u2y2−v2y2−u3y3−v3y3−u4y4−v4y4−u1−v1−u2−v2−u3−v3−u4−v4⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
h=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡h11h12h13h21h22h23h31h32h33⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤
2. 对矩阵 A 进行奇异值分解
对矩阵 A 进行奇异值分解,得到:
A=UΣVT
其中:
- U 是一个 8×8 的正交矩阵,满足 UTU=I8。
- Σ 是一个 8×9 的对角矩阵,主对角线元素为奇异值 σ1≥σ2≥⋯≥σ8≥0,其余元素为 0,即
Σ=⎣⎢⎢⎢⎢⎡σ10⋮00σ2⋮0⋯⋯⋱⋯00⋮σ800⋮0⋯⋯⋯⋯00⋮000⋮000⋮0⎦⎥⎥⎥⎥⎤
- V 是一个 9×9 的正交矩阵,满足 VTV=I9。
3. 求解 h
将 A=UΣVT 代入 Ah=0,由于 U 是正交矩阵,左乘 UT 可得:
ΣVTh=0
设 z=VTh,则方程变为 Σz=0,即:
⎣⎢⎢⎢⎢⎡σ10⋮00σ2⋮0⋯⋯⋱⋯00⋮σ800⋮0⋯⋯⋯⋯00⋮000⋮000⋮0⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎢⎢⎢⎡z1z2⋮z8z9⎦⎥⎥⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡00⋮0⎦⎥⎥⎥⎥⎤
这等价于:
⎩⎪⎪⎪⎪⎪⎨⎪⎪⎪⎪⎪⎧σ1z1=0σ2z2=0⋮σ8z8=0
通常情况下,若矩阵 A 满秩,σ1≥σ2≥⋯≥σ8>0,为使方程成立,z1=z2=⋯=z8=0。不妨令 z9=1,则 z=[0,0,⋯,0,1]T。
因为 z=VTh 且 V 是正交矩阵,所以 h=Vz。根据矩阵乘法规则,h 就是 V 的最后一列,即:
h=V⎣⎢⎢⎢⎢⎢⎢⎡00⋮01⎦⎥⎥⎥⎥⎥⎥⎤
4. 得到透视变换矩阵 H
将 h 重塑为 3×3 的矩阵,就得到了透视变换矩阵 H:
H=⎣⎢⎡h11h21h31h12h22h32h13h23h33⎦⎥⎤
综上所述,通过上述一系列数学步骤,利用奇异值分解成功求解出了透视变换矩阵 H。
参考
https://github.com/ultralytics/ultralytics/issues/4945