基于MeanShift的目标跟踪算法及实现(自编函数利用Python实现)

基于MeanShift的目标跟踪算法及实现(自编函数利用Python实现),第1张

 参考博客

cc​​​​​​​(9条消息) 基于MeanShift的目标跟踪算法及实现_taotao1233的博客-CSDN博客_meanshift目标跟踪算法https://blog.csdn.net/jinshengtao/article/details/30258833https://blog.csdn.net/jinshengtao/article/details/30258833(9条消息) MeanShift(均值漂移)MATLAB程序详解_战死为止的博客-CSDN博客_均值漂移matlab代码https://blog.csdn.net/qq_34122861/article/details/89556503        本人写程序和open-cv都是新人,看了上面的文章后发现没有python版本的,就按照一摸一样的思路仿写了python的代码,但是是打开笔记本自带摄像头进行MeanShift目标跟踪。希望给萌新一些参考,由于我也是新手,这是我写的第一个比较长的代码,所以会有很多冗余甚至错误,欢迎大家指正。如果看不懂可以参考上面的博客。

代码
import math
import numpy as np
import cv2


def get_tr(img):
    # 定义需要返回的参数
    mouse_params = {'x': None, 'width': None, 'height': None,
                    'y': None, 'temp': None}
    cv2.namedWindow('image')
    # 鼠标框选 *** 作函数
    cv2.setMouseCallback('image', on_mouse, mouse_params)
    cv2.imshow('image', img)
    cv2.waitKey(0)
    return [mouse_params['x'], mouse_params['y'], mouse_params['width'],
            mouse_params['height']], mouse_params['temp']


def on_mouse(event, x, y, flags, param):
    global img, point1
    img2 = img.copy()
    if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击
        point1 = (x, y)
        cv2.circle(img2, point1, 10, (0, 255, 0), 5)
        cv2.imshow('image', img2)
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳
        cv2.rectangle(img2, point1, (x, y), (255, 0, 0), 5)
        cv2.imshow('image', img2)
    elif event == cv2.EVENT_LBUTTONUP:  # 左键释放
        point2 = (x, y)
        cv2.rectangle(img2, point1, point2, (0, 0, 255), 5)
        cv2.imshow('image', img2)
        # 返回框选矩形左上角点的坐标、矩形宽度、高度以及矩形包含的图像
        param['x'] = min(point1[0], point2[0])
        param['y'] = min(point1[1], point2[1])
        param['width'] = abs(point1[0] - point2[0])
        param['height'] = abs(point1[1] - point2[1])
        param['temp'] = img[param['y']:param['y']+param['height'],
            param['x']:param['x']+param['width']]


def main():
    global img
    cap = cv2.VideoCapture(0)
    # 获取视频第一帧
    ret, frame = cap.read()
    img = frame
    # 框选目标并返回相应信息:rect为四个信息,temp为框选出来的图像
    rect, temp = get_tr(img)
    (a, b, c) = temp.shape
    y = [a/2, b/2]

    # 计算目标图像的权值矩阵
    m_wei = np.zeros((a,b))
    for i in range(a):
        for j in range(b):
            z = (i-y[0])**2 + (j-y[1])**2
            m_wei[i, j] = 1 - z/(y[0]**2 + y[1]**2)

    # 计算目标权值直方图
    C = 1/sum(sum(m_wei))
    hist1 = np.zeros(16**3)
    for i in range(a):
        for j in range(b):
            q_b = math.floor(float(temp[i, j, 0]) / 16)
            q_g = math.floor(float(temp[i, j, 1]) / 16)
            q_r = math.floor(float(temp[i, j, 2]) / 16)
            q_temp1 = q_r*256 + q_g*16 + q_b
            hist1[int(q_temp1)] = hist1[int(q_temp1)] + m_wei[i, j]
    hist1 = hist1*C

    # 接着读取视频并进行目标跟踪
    while(1):
        ret, frame = cap.read()

        if ret == True:
            Img = frame
            num = 0
            Y = [1, 1]

            # mean shift迭代
            while (np.sqrt(Y[0]**2+Y[1]**2) > 0.5) & (num < 20):
                num = num+1

                # 计算候选区域直方图
                temp2 = Img[int(rect[1]):int(rect[1]+rect[3]), int(rect[0]):int(rect[0]+rect[2])]
                hist2 = np.zeros(16**3)
                q_temp2 = np.zeros((a, b))
                for i in range(a):
                    for j in range(b):
                        q_b = math.floor(float(temp2[i, j, 0]) / 16)
                        q_g = math.floor(float(temp2[i, j, 1]) / 16)
                        q_r = math.floor(float(temp2[i, j, 2]) / 16)
                        q_temp2[i, j] = q_r * 256 + q_g * 16 + q_b
                        hist2[int(q_temp2[i, j])] = hist2[int(q_temp2[i, j])] + m_wei[i, j]
                hist2 = hist2*C

                w = np.zeros(16**3)
                for i in range(16**3):
                    if hist2[i] != 0:
                        w[i] = math.sqrt(hist1[i]/hist2[i])
                    else:
                        w[i] = 0

                sum_w = 0
                sum_xw = [0, 0]
                for i in range(a):
                    for j in range(b):
                        sum_w = sum_w + w[int(q_temp2[i, j])]
                        sum_xw = sum_xw + w[int(q_temp2[i, j])]*np.array([i-y[0], j - y[1]])
                Y = sum_xw/sum_w

                # 位置更新
                rect[0] = rect[0] + Y[1]
                rect[1] = rect[1] + Y[0]

            v0 = int(rect[0])
            v1 = int(rect[1])
            v2 = int(rect[2])
            v3 = int(rect[3])
            pt1 = (v0, v1)
            pt2 = (v0+v2, v1+v3)

            # 画矩形
            IMG = cv2.rectangle(Img, pt1, pt2, (0, 0, 255), 2)
            cv2.imshow('IMG', IMG)
            k = cv2.waitKey(60) & 0xff
            if k == 27:
                break
        else:
            break


if __name__ == '__main__':
    main()
结果

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/717147.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存