yolov8应用实践(辅助函数介绍)


双向队列 deque

跟踪算法中需要记录前后多帧的数据,使用一个双向队列deque,来自于包collection,deque类源码如下:


class deque(MutableSequence[_T], Generic[_T]):
    @property
    def maxlen(self) -> int | None: ...
    @overload
    def __init__(self, *, maxlen: int | None = ...) -> None: ...
    @overload
    def __init__(self, iterable: Iterable[_T], maxlen: int | None = ...) -> None: ...
    def append(self, __x: _T) -> None: ...
    def appendleft(self, __x: _T) -> None: ...
    def copy(self: Self) -> Self: ...
    def count(self, __x: _T) -> int: ...
    def extend(self, __iterable: Iterable[_T]) -> None: ...
    def extendleft(self, __iterable: Iterable[_T]) -> None: ...
    def insert(self, __i: int, __x: _T) -> None: ...
    def index(self, __x: _T, __start: int = ..., __stop: int = ...) -> int: ...
    def pop(self) -> _T: ...  # type: ignore[override]
    def popleft(self) -> _T: ...
    def remove(self, __value: _T) -> None: ...
    def rotate(self, __n: int = ...) -> None: ...
    ...

使用方法如下:

from collections import deque
data_deque = deque(maxlen = 64 )
data_deque.appendleft(xxx)

这样,一个长度为64的双向队列就可以使用了,data_deque的最大长度会维持在64,对于我们一般的模型,如果帧率是30,那么这个队列长度可以保留大概2秒多的数据,相当于有2秒的记忆,在跟踪模型中,这个类很有用

四点相交判定方法 intersect

对于跟踪模型除了需要判定目标是否在某一区域中,有时候还需要判定目标轨迹是否跨越边界线,这时候,需要一个数学算法,根据轨迹点以及边界点连线,判定四点是否相交,方法如下:

def intersect(A,B,C,D):
    return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)

def ccw(A,B,C):
    return (C[1]-A[1]) * (B[0]-A[0]) > (B[1]-A[1]) * (C[0]-A[0])

轨迹方向判定 get_direction

对于轨迹方向,这里只给出两点坐标计算的方向,为了直观,我们以画面上北下南左西右东表示方向,实际可灵活使用,做相应映射即可,方法如下:

def get_direction(point1, point2):
    direction_str = ""

    # calculate y axis direction
    if point1[1] > point2[1]:
        direction_str += "South"
    elif point1[1] < point2[1]:
        direction_str += "North"
    else:
        direction_str += ""

    # calculate x axis direction
    if point1[0] > point2[0]:
        direction_str += "East"
    elif point1[0] < point2[0]:
        direction_str += "West"
    else:
        direction_str += ""

日志模块 logging

在项目中,日志非常重要,logging模块功能完善,可以实现不同级别的日志输出,并且可指定分割,下面简要介绍方法。

step1: 导入模块

import logging
from logging.handlers import TimedRotatingFileHandler

这里我们用到了TimedRotatingFileHandler,此方法专门解决关于时间的日志处理

step2: 初始化

# 分两小块,一是初始化时间分块相关参数,下面的timefilehandler就指定了每隔1小时备份一次,最大备份数量1000个,编码指定为utf8,更加通用
timefilehandler = TimedRotatingFileHandler(
    filename="./logs/sendReport.log",
    when='H',
    interval=1,
    backupCount=1000,
    encoding="utf8"
)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
timefilehandler.suffix = "-%Y-%m-%d_%H_%M_%S.log"
timefilehandler.setFormatter(formatter)
#第二块是初始化logger对象,并指定级别和设定参数
loggerV2 = logging.getLogger('sendLog')
loggerV2.setLevel(logging.INFO)
loggerV2.addHandler(timefilehandler)


#使用
loggerV2.info("{}".format(str(data)))

更多功能请参加官方文档。


文章作者: 无名小卒
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 无名小卒 !
  目录