• camshift实现目标跟踪


    注:物体跟踪的类不在opencv-python库里,而是附加额外功能的opencv-contrib-python
    安装:

    pip install opencv-contrib-python==4.6.0.66 -i https://pypi.tuna.tsinghua.edu.cn/simple/

    camshift 利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大 小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的中心位置

    实现步骤:
    1 初始化搜索窗
    2 反向投影:将图像转化为受光照影响较小的HSV模型。对H分量作直方图代表不同H值出现概率,得到颜色概率查找表。把图像每个像素值用颜色出现概率替换得到颜色概率分布图
    3 运行meanshift算法得到搜索窗新的大小和位置。meanshift通过迭代找到概率分别极值定位目标
    4 重复2,3步骤跟踪图像

    跟踪超类:
    图像跟踪图像都将继承该跟踪超类。该类实现鼠标框出要跟踪图像范围,显示图像,显示CPS和RES值。

    import cv2
    import numpy as np 
    import time
    
    class TrackerBase(object):
        def __init__(self, window_name):
            self.window_name = window_name
            self.frame = None
            self.frame_width = None
            self.frame_height = None
            self.frame_size = None
            self.drag_start = None
            self.selection = None 
            self.track_box = None
            self.detect_box = None
            self.display_box = None
            self.marker_image = None
            self.processed_image = None
            self.display_image = None 
            self.target_center_x = None
        
        def onMouse(self, event, x, y, flags, params): 
            if self.frame is None:
                return
            if event == cv2.EVENT_LBUTTONDOWN and not self.drag_start:
                self.track_box = None 
                self.detect_box = None
                self.drag_start = (x, y) 
            if event == cv2.EVENT_LBUTTONUP: 
                self.drag_start = None
                self.detect_box = self.selection
            if self.drag_start: 
                xmin = max(0, min(x, self.drag_start[0]))
                ymin = max(0, min(y, self.drag_start[1]))
                xmax = min(self.frame_width, max(x, self.drag_start[0])) 
                ymax = min(self.frame_height, max(y, self.drag_start[1])) 
                self.selection = (xmin, ymin, xmax-xmin, ymax-ymin)
                
        def display_selection(self):
            if self.drag_start and self.is_rect_nonzero(self.selection):
                x, y, w, h = self.selection
                cv2.rectangle(self.marker_image, (x, y), (x + w, y + h), (0, 255, 255), 2)
                
        def is_rect_nonzero(self, rect):
            try:
                (_,_,w,h) = rect 
                return ((w>0)and(h>0)) 
            except: 
                try:
                    ((_,_),(w,h),a) = rect 
                    return (w > 0) and (h > 0) 
                except:
                    return False
        def rgb_image_callback(self, data):
            frame = data
            if self.frame is None: 
                self.frame = frame.copy()
                self.marker_image = np.zeros_like(frame)
                self.frame_size = (frame.shape[1], frame.shape[0])
                self.frame_width, self.frame_height = self.frame_size 
                cv2.imshow(self.window_name, self.frame) 
                cv2.setMouseCallback(self.window_name,self.onMouse)
                cv2.waitKey(3) 
            else:
                self.frame = frame.copy() 
                self.marker_image = np.zeros_like(frame) 
                processed_image = self.process_image(frame) 
                self.processed_image = processed_image.copy() 
                self.display_selection()
                self.display_image = cv2.bitwise_or(self.processed_image, self.marker_image)
                
                if self.track_box is not None and self.is_rect_nonzero(self.track_box): 
                    tx, ty, tw, th = self.track_box 
                    cv2.rectangle(self.display_image, (tx, ty), (tx+tw, ty+th), (0, 0, 0), 2)
                elif self.detect_box is not None and self.is_rect_nonzero(self.detect_box):
                    dx, dy, dw, dh = self.detect_box 
                    cv2.rectangle(self.display_image, (dx, dy), (dx+dw, dy+dh), (255, 50, 50), 2)
                
                cv2.imshow(self.window_name, self.display_image) 
                cv2.waitKey(3)
                
        
        def process_image(self, frame):
            return frame
        
    if __name__=="__main__": 
        cap = cv2.VideoCapture(0)
        trackerbase = TrackerBase('base')
        while True: 
            ret, frame = cap.read()
            x, y = frame.shape[0:2] 
            small_frame = cv2.resize(frame, (int(y/2), int(x/2)))
            trackerbase.rgb_image_callback(small_frame)
            if cv2.waitKey(1) & 0xFF == ord('q'): 
                break
        cap.release() 
        cv2.destroyAllWindows()
    
    • 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
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97

    1 def onMouse(self, event, x, y, flags, params):
    onMouse类为鼠标事件默认回调函数,在后面cv2.setMouseCallback(self.window_name,self.onMouse)使用到

    参数:event:鼠标动作
    x,y:鼠标产生该事件时x和y坐标
    flags:cv2_EVENT_FLAG_* (MouseEventFlags)类型的变量
    param:自定义的传递给 setMouseCallback 函数调用的参数

    点击左键时把x,y保存在变量drag_start作为鼠标初始位置,在鼠标移动中会随时把新的x,y传入回调函数,更新selection的值。在左键抬起时保存所选框为detect_box

    鼠标回调函数更多内容可参考:http://t.csdn.cn/DuSMv

    2 def display_selection(self):
    用矩形框出选定区域

    3 def is_rect_nonzero(self, rect):
    判断矩形大小是否为0

    4 def rgb_image_callback(self, data):
    核心函数,有以下功能:
    1 如没有frame时复制data(即传入的图像),将一些参数和传入图像保持一致,并显示图像。这里调用鼠标回调函数获取边框

    2 在有图像时,运行图像处理程序self.process_image(该程序在子类里重写),显示矩形框。显示track_box和detect_box

    5 def process_image(self, frame):
    该程序目前只是返回原图,子类要重写该程序实现跟踪核心功能

    camshift算法实现:

    import cv2
    import numpy as np 
    from tracker_base import TrackerBase
    
    class Camshift(TrackerBase):
        def __init__(self, window_name): 
            super(Camshift, self).__init__(window_name) 
            self.detect_box = None 
            self.track_box = None
            
        def process_image(self, frame):
            try: 
                if self.detect_box is None:
                    return frame
                src = frame.copy()
                if self.track_box is None or not self.is_rect_nonzero(self.track_box): 
                    self.track_box = self.detect_box
                    x,y,w,h = self.track_box
                    self.roi = cv2.cvtColor(frame[y:y+h, x:x+w], cv2.COLOR_BGR2HSV)
                    roi_hist = cv2.calcHist([self.roi], [0], None, [16], [0, 180])
                    self.roi_hist = cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
                    self.term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
                else:
                    hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
                    back_project = cv2.calcBackProject([hsv],[0],self.roi_hist,[0,180],1)
                    ret, self.track_box = cv2.CamShift(back_project, self.track_box, self.term_crit)
                    pts = cv2.boxPoints(ret)
                    pts = np.int0(pts)
                    cv2.polylines(frame,[pts],True,255,1)
            except:
                pass
            return frame
    
    if __name__ == '__main__':
        cap = cv2.VideoCapture(0) 
        camshift = Camshift('camshift')
        while True:
            ret, frame = cap.read()
            x, y = frame.shape[0:2]
            small_frame = cv2.resize(frame, (int(y/2), int(x/2)))
            camshift.rgb_image_callback(small_frame) 
            if cv2.waitKey(1) & 0xFF == ord('q'): 
                break
        cap.release() 
        cv2.destroyAllWindows()
    
    • 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
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    1

     try: 
                if self.detect_box is None:
                    return frame
    
    • 1
    • 2
    • 3

    如没有标定跟踪区域直接返回原图

    2

     if self.track_box is None or not self.is_rect_nonzero(self.track_box): 
                    self.track_box = self.detect_box
                    x,y,w,h = self.track_box
                    self.roi = cv2.cvtColor(frame[y:y+h, x:x+w], cv2.COLOR_BGR2HSV)
                    roi_hist = cv2.calcHist([self.roi], [0], None, [16], [0, 180])
                    self.roi_hist = cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)
                    self.term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    track_box不存在时把track_box重置为detect_box(即划定的跟踪区域),并计算detect_box里颜色概率直方图,这一部分用于初始化

    3

    hsv = cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)
                    back_project = cv2.calcBackProject([hsv],[0],self.roi_hist,[0,180],1)
                    ret, self.track_box = cv2.CamShift(back_project, self.track_box, self.term_crit)
                    pts = cv2.boxPoints(ret)
                    pts = np.int0(pts)
                    cv2.polylines(frame,[pts],True,255,1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    调用Camshift库对图像进行识别

  • 相关阅读:
    MacBook当作Win电脑副屏
    Spire.PDF for .NET 9.8.5 Crack
    Temporal介绍
    windows任务栏卡死,重启也没用
    python Gui编程工具详解:beeware
    Web前端大作业——基于HTML+CSS+JavaScript仿英雄联盟LOL游戏网站
    一个公式让你35岁以后能越过越好!大神修炼心法
    HTTP/2是什么?和HTTP/1.1有什么不同?和SPDY有什么不同?
    前端-naive ui如何渲染表格中的开关switch、单选框checkbox、按钮
    CC攻击演示
  • 原文地址:https://blog.csdn.net/Raine_Yang/article/details/126248885