星瞳实验室APP,快速收到回复
  • 我们只解决官方正版的OpenMV的问题(STM32),其他的分支有很多兼容问题,我们无法解决。
  • 如果有产品硬件故障问题,比如无法开机,论坛很难解决。可以直接找售后维修
  • 发帖子之前,请确认看过所有的视频教程,https://singtown.com/learn/ 和所有的上手教程http://book.openmv.cc/
  • 每一个新的提问,单独发一个新帖子
  • 帖子需要目的,你要做什么?
  • 如果涉及代码,需要报错提示全部代码文本,请注意不要贴代码图片
  • 必看:玩转星瞳论坛了解一下图片上传,代码格式等问题。
  • 官网追踪其他物体的云台教程视频是否有问题?



    • import sensor, image, time
      
      from pid import PID
      from pyb import Servo
      
      pan_servo=Servo(1)
      tilt_servo=Servo(2)
      
      pan_pid = PID(p=0.07, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID
      tilt_pid = PID(p=0.05, i=0, imax=90) #脱机运行或者禁用图像传输,使用这个PID
      #pan_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID
      #tilt_pid = PID(p=0.1, i=0, imax=90)#在线调试使用这个PID
      
      sensor.reset() # 初始化元件
      sensor.set_contrast(1)#自动调节对比度
      sensor.set_gainceiling(16)#自动增益
      sensor.set_pixformat(sensor.RGB565) # 使用RGB656彩图模式
      sensor.set_framesize(sensor.QVGA) # 使用QVGA大小
      sensor.set_vflip(True)#画面垂直翻转
      sensor.skip_frames(10) # 跳过一些帧,使元器件稳定,设置生效
      sensor.set_auto_whitebal(True) # 自动白平衡
      clock = time.clock() # 初始化时钟
      face_cascade = image.HaarCascade("frontalface", stages=25)#图像处理中使用人脸识别
      
      '''定义寻找最大块函数'''
      def find_max(blobs):
          max_size=0
          for blob in blobs:
              if blob[2]*blob[3] > max_size:#如果面积大于上一个色块面积
                  max_blob=blob
                  max_size = blob[2]*blob[3]
          return max_blob#返回色块对象
      
      
      while(True):
          clock.tick() # 开始追踪运行时间
          img = sensor.snapshot() # Take a picture and return the image.
          blobs =img.find_features(face_cascade, threshold=0.75, scale=1.35)
          #在帧中寻找人脸
          if blobs:
              max_blob = find_max(blobs)
              pan_error = max_blob[0]+max_blob[2]/2-img.width()/2
              tilt_error = max_blob[1]+max_blob[3]/2-img.height()/2
      
              print("pan_error: ", pan_error)
      
              img.draw_rectangle(max_blob)
              img.draw_cross(int(max_blob[0]+max_blob[2]/2), int(max_blob[1]+max_blob[3]/2))
      
              pan_output=pan_pid.get_pid(pan_error,1)/2
              tilt_output=tilt_pid.get_pid(tilt_error,1)
              print("pan_output",pan_output)
              pan_servo.angle(pan_servo.angle()+pan_output)
              tilt_servo.angle(tilt_servo.angle()-tilt_output)
      
      from pyb import millis
      from math import pi, isnan
       
      class PID:
          _kp = _ki = _kd = _integrator = _imax = 0
          _last_error = _last_derivative = _last_t = 0
          _RC = 1/(2 * pi * 20)
          def __init__(self, p=0, i=0, d=0, imax=0):
              self._kp = float(p)
              self._ki = float(i)
              self._kd = float(d)
              self._imax = abs(imax)
              self._last_derivative = float('nan')
       
          def get_pid(self, error, scaler):
              tnow = millis()
              dt = tnow - self._last_t
              output = 0
              if self._last_t == 0 or dt > 1000:
                  dt = 0
                  self.reset_I()
              self._last_t = tnow
              delta_time = float(dt) / float(1000)
              output += error * self._kp
              if abs(self._kd) > 0 and dt > 0:
                  if isnan(self._last_derivative):
                      derivative = 0
                      self._last_derivative = 0
                  else:
                      derivative = (error - self._last_error) / delta_time
                  derivative = self._last_derivative + \
                                           ((delta_time / (self._RC + delta_time)) * \
                                              (derivative - self._last_derivative))
                  self._last_error = error
                  self._last_derivative = derivative
                  output += self._kd * derivative
              output *= scaler
              if abs(self._ki) > 0 and dt > 0:
                  self._integrator += (error * self._ki) * scaler * delta_time
                  if self._integrator < -self._imax: self._integrator = -self._imax
                  elif self._integrator > self._imax: self._integrator = self._imax
                  output += self._integrator
              return output
          def reset_I(self):
              self._integrator = 0
              self._last_derivative = float('nan')
      
      

      以上为参照官网视频改的代码,设置了垂直翻转。所有文件均按官网方法存至sd卡,其中pid的代码没有改过。但是运行以后发现水平移动无问题,但垂直方向云台会往相反的方向移动,麻烦看一下是什么原因



    • 没有问题。

      教程里的代码都是写好的,除了要根据自己要追踪的颜色修改颜色阈值之外,不需要设置其他的,直接用就可以。不需要自行设置翻转。

      https://book.openmv.cc/project/pan-tilt.html



    • @yuan 已经确认官方给的教程有误,设置垂直翻转后,垂直舵机应该加上误差值,而不是减去。



    • 官网的教程,直接用就可以了,不需要不需要不需要设置垂直翻转。

      当然,你如果想自己再多设置一遍翻转,需要你更改后面的代码。



    • @yuan 你们自己的视频教程让设置的垂直翻转。
      现在又不让设置垂直翻转,那请问倒着的人脸能识别???
      很多视频教程又水,错误又多,不知道教复制粘贴的视频教程有什么用,还误导新手。
      PID自己从网上抄的也不写注释,还乱改,明明位置式PID,偏偏喜欢抄个速度PID的壳