jetbot12 之 人手目标跟踪(hand tracking)

有了目标检测 再结合 云台舵机 PID 算法可以实现简单的 目标跟踪:

注: PID 算法源码是机器人开发板厂家提供, 以下是简单原理介绍:

P - 线性控制量 , I - 积分参数 , D - 微分参数

自动控制系统的经典算法, 要让舵机到达目标位置Y ,   首要是要给系统一个线性作用力,控制量和移动距离体现为比例系数P。 当然这个作用力的结果会有偏差。

积分参数对于产生的偏差起到滞后的纠正作用。

微分参数通过偏差的变化速度提前预估未来的偏差以起到尽早纠正偏差的作用。能加快系统响应。

PID有严谨的理论推导,和标准的 控制算法, 对于给定的动力系统, P , I , D 参数要通过调较来获得。

 

可以看看百度里的介绍:

https://baike.baidu.com/item/PID%E7%AE%97%E6%B3%95/4660106?fr=aladdin

 

这里的目标跟踪是不严格的, 只是通过简单的检测定位算法 来控制镜头云台转动到目标的中心,起到简单的跟踪效果。 出现多个人手时会产生跟踪的叛变。。

 

jetbot hand detect and tracking

 

目标检测使用了 yolov5s 训练的 人脸 、带口罩人脸、人手  三种分类目标的模型。 并且转了 tensorRT 在 jetson nano 下运行,可以到 640x360@20fps需要的可以私信我。

代码实现:

#!/usr/bin/python3
# -*- coding:utf-8 -*-
import sys 

sys.path.append('/workspace/hugo_py')

import cv2 
import numpy as np
import time
from camera import JetCamera
import traceback
import TRTYolov5 as fd
import PID 

cap_w = 640 
cap_h = 360 
cap_fps = 30

# 云台 PID 控制
target_valuex=2100
target_valuey=2048

xservo_pid = PID.PositionalPID(1.9, 0.3, 0.35)
yservo_pid = PID.PositionalPID(1.5, 0.2, 0.3)

# 云台控制总线
from servoserial import ServoSerial
servo_device = ServoSerial()


def ptz_reset():
    global target_valuex, target_valuey
    target_valuex = 2100
    target_valuey = 2048
    servo_device.Servo_serial_double_control(1, target_valuex, 2,  target_valuey)

    time.sleep(0.1)





def main():
    global target_valuex, target_valuey, xservo_pid, yservo_pid
    ptz_reset()

    cam = JetCamera(cap_w, cap_h, cap_fps)

    engine = fd.create('../build/yolov5s.engine')

   out_win = "foo"
    cv2.namedWindow(out_win, cv2.WINDOW_NORMAL)
    cv2.setWindowProperty(out_win, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)


    cam.open()

    cnt = 0
    sum_time = 0
    while True:
        try:
            ret, frame = cam.read()
            #print("camera read one frame ")
            if not ret:
                break

            t0 = time.time()
            ret = fd.detect(engine, frame, 0.4)
            res = eval(ret)
            t1 = time.time()

            sum_time += t1 - t0
            cnt += 1

            if cnt % 150 == 0:
                print("frame cnt [%d]   detect delay = %.1fms" % (cnt, (sum_time) * 1000/ cnt ))
                sum_time = 0
                cnt = 0

            print(res)
            if   res['num_det'] > 0:
                for ret in res['objects']:
                    cls_id, x1, y1, x2, y2 = ret
                    color = {0:(0, 0, 255), 1:(255, 0, 0), 2:(0, 255, 0)}[cls_id]

                    cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3)

                    if 2 == cls_id:
                        x_s, y_s, w_s, h_s = x1 * 300 / cap_w, y1 * 300 / cap_h, (x2 - x1) * 300 / cap_w , (y2 - y1 ) * 300 / cap_h


                        xservo_pid.SystemOutput = x_s + w_s / 2
                        xservo_pid.SetStepSignal(150)
                        xservo_pid.SetInertiaTime(0.01, 0.006)
                        target_valuex = int(2100 + xservo_pid.SystemOutput)

                        yservo_pid.SystemOutput = y_s + h_s / 2
                        yservo_pid.SetStepSignal(150)
                        yservo_pid.SetInertiaTime(0.01, 0.006)

                        target_valuey = int(2048 + yservo_pid.SystemOutput)


                        servo_device.Servo_serial_double_control(1, target_valuex, 2 , target_valuey)

            #    r = ret[2]
            #    #print("ret = %s, %s" % (ret, r))
            #    #cv2.rectangle(frame, (int(r[0]), int(r[1])), (int(r[2]), int(r[3])), (255, 255, 0))

            cv2.imshow(out_win, frame)
            cv2.waitKey(1)
        except:
            traceback.print_exc()
            break

    cam.close()


if __name__ == '__main__':
    main()

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

walletiger

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值