当前位置 博文首页 > 文章内容

    万万VV:Python-OpenCv实现出入口计数并显示

    作者:21344 栏目:未分类 时间:2021-11-25 22:30:51

    前言

    这是我们数字图像处理课完成的一个实验项目,参考了网上的一些代码,针对我们老师给的需要统计人数的视频进行了一些修改。

    源代码下载

    一、背景剔除并二值化

    高斯模糊:

    gray = cv2.GaussianBlur(frame, (31, 31), 0)

    作用:视频因为自然震动、光照变化或者摄像头本身等原因产生的噪声,对噪声进行平滑为了避免在运动和跟踪时将其检测出来。

    背景剔除

    fgbg = cv2.createBackgroundSubtractorKNN()

    生成蒙版

    fgmask = fgbg.apply(gray)

    二值化:

    ret,imBin= cv2.threshold(fgmask,200,255,cv2.THRESH_BINARY)

    Opening (erode->dilate)

    mask = cv2.morphologyEx(imBin, cv2.MORPH_OPEN, kerne3)

    开操作(腐蚀->膨胀)消除噪声

    mask =  cv2.morphologyEx(mask , cv2.MORPH_CLOSE, kerne3)

    Closing (dilate -> erode)

    膨胀--最好能使形状比较均匀, 将破碎的区域连接起来

    用于形态学处理的核:

    调整参数效果会有所改变

    kernel = np.ones((3,3),np.uint8)

    kerne2 = np.ones((5,5),np.uint8)

    kerne3 = np.ones((11,11),np.uint8)

    二、目标跟踪

    找到边界:

    _, contours0, hierarchy = cv2.findContours(mask2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    对每个矩形框:

    边框:rect = cv2.boundingRect(cnt)

    计算面积:area=cv2.contourArea(cnt)

    计算重心:

    M=cv2.moments(cnt)

    cx=int(M['m10']/M['m00'])

    cy=int(M['m01']/M['m00'])

    长宽:x, y, w, h = cv2.boundingRect(cnt)

    对每个跟踪目标建立MyPerson类:

    存储每个矩形框的重心坐标,状态

     

    def __init__(self, i, xi, yi, max_age):
            self.i = i
            self.x = xi
            self.y = yi
            self.tracks = []
            self.R = randint(0,255)
            self.G = randint(0,255)
            self.B = randint(0,255)
            self.done = False
            self.state = '0'
            self.age = 0
            self.max_age = max_age
            self.dir = None

    将所有识别到的人存储在数组中:

    class MultiPerson:
        def __init__(self, persons, xi, yi):
            self.persons = persons
            self.x = xi
            self.y = yi
            self.tracks = []
            self.R = randint(0,255)
            self.G = randint(0,255)
            self.B = randint(0,255)
            self.done = False

    三、计数算法

    跟踪记录:

    先在已有的persons中找到距离最近的,判断其属于同一个人,并更新位置数据

    判断方向

    画了两条线,一条出口,一条入口,以及limit线(白色):

    白线的作用是将已经超过白线范围且记过数的目标人从数组中清除掉,清除内存,加快遍历查找速度

    进入:

    self.tracks[-1][1] < mid_end and self.tracks[-2][1] >= mid_end

    最后一个矩形框的重心坐标小于倒数第二个,且最后一个坐标在入口线的上方,前一个坐标在入口线的下方

    出去:

    self.tracks[-1][1] > mid_start and self.tracks[-2][1] <= mid_start

    最后一个矩形框的重心坐标大于倒数第二个,且最后一个坐标在出口线的下方,前一个坐标在出口线的上方

    记录状态:

    如果已经记过数则记下状态,之后不再重复计数,提高准确率。

    清除人:

    已经记过数且超出limit,则将其从内存清除

    并排行走改进:

    1、对与挨着一起走的人,无法将其完全分开,先记录一个人的宽度,判断其大于一个人的宽度,则用宽度除以每个人的宽度w.

    2、修改前面使用的形态学的核,将参数设为长方形或者椭圆形,这样识别单人会更加准确,也可以解决两人并排走的问题。

    三、结果分析

     

    进入

    出去

    实际人数

    18/19

    18

    程序计数

    18

    21

    准确率

    100%

    83.3%

    四、存在的问题

    漏识别:

    对于衣服颜色和背景差不多的人会在某些位置无法识别,影响计数

    原因:

    图像处理后将其分的太碎导致矩形框面积太小不被识别为跟踪对象,需要进一步调整参数

    错误计数

    当人数过多时或受周围环境影响,识别的矩形框形状变化频繁,导致重心抖动,过线计数时会多记或者出入记反:

    保存输出视频

    Cv2.VideoWriter(filename, fourcc, fps, frameSize[, isColor]) 

    fourcc = cv2.VideoWriter_fourcc(*'XVID')

    第一个参数是要保存的文件的路径

    fourcc 指定编码器

    fps 要保存的视频的帧率

    frameSize 要保存的文件的画面尺寸

    isColor 指示是黑白画面还是彩色的画面

    编码的含义为:CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec

    cs