樹莓派,opencv,Picamera2利用舵機云臺追蹤特定顏色對象

一、需要準備的硬件

  1. Raspiberry 4b
  2. 兩個SG90 180度舵機(注意舵機的角度,最好是180度且帶限位的,切勿選360度舵機)
  3. 二自由度舵機云臺(如下圖)
  4. Raspiberry CSI 攝像頭
    組裝后的效果:
    在這里插入圖片描述

二、項目目標

追蹤特定顏色的物體:
當物體移動時,攝像頭通過控制兩個伺服電機(分別是偏航和俯仰)把該物體放到視界的中心位置,我在這里追蹤的是一支紅色的鉛筆。

三、具體步驟

3.1 獲得被追蹤對象的顏色參數

  1. 提前準備一張圖片(如下圖),可以直接用樹莓派的CSI攝像頭拍攝并保存,具體方法可以在我之前的文章里找到
    原始圖片

  2. 利用下面的代碼并通過調整滑塊(Trackbar)獲得紅色鉛筆的HSV顏色參數,為接下來的顏色追蹤做準備

***color_detection.py***
import cv2
path='test_full.jpg'
cv2.namedWindow("TrackBar")def nothing(x):pass
#創建滑塊控件
cv2.createTrackbar("Hue Min","TrackBar",0,179,nothing)
cv2.createTrackbar("Hue Max","TrackBar",179,179,nothing)
cv2.createTrackbar("Sat Min","TrackBar",0,255,nothing)
cv2.createTrackbar("Sat Max","TrackBar",255,255,nothing)
cv2.createTrackbar("Val Min","TrackBar",0,255,nothing)
cv2.createTrackbar("Val Max","TrackBar",255,255,nothing)while True:#讀取目標圖片image=cv2.imread(path)image=cv2.resize(image,(640,480))imgHSV=cv2.cvtColor(image,cv2.COLOR_BGR2HSV)hueLow=cv2.getTrackbarPos("Hue Min","TrackBar")hueHigh=cv2.getTrackbarPos("Hue Max","TrackBar")satLow=cv2.getTrackbarPos("Sat Min","TrackBar")satHigh=cv2.getTrackbarPos("Sat Max","TrackBar")valLow=cv2.getTrackbarPos("Val Min","TrackBar")valHigh=cv2.getTrackbarPos("Val Max","TrackBar")print(hueLow,hueHigh,satLow,satHigh,valLow,valHigh)#創建掩膜mask=cv2.inRange(imgHSV,(hueLow,satLow,valLow),(hueHigh,satHigh,valHigh))image=cv2.bitwise_and(image,image,mask=mask)#顯示圖像cv2.imshow('Origial',image)cv2.imshow('HSV',imgHSV)#按q鍵退出if cv2.waitKey(1)==ord('q'):break
cv2.destroyAllWindows() 
  1. 運行color_detection.py,并調整滑塊(TrackBar)如下圖,當然你的被追蹤物體的顏色不同,參數也必然不同。
    滑塊調整
    這時你會發現,紅色鉛筆被顯示出來,其它部分被掩膜遮擋,記下Hue Min, Hui Max, Sat Min, Sat Max, Val Min, Val Max這六個數值在接下來的代碼中會用到。
    在這里插入圖片描述

3.2 目標追蹤代碼

  1. 輸入color_detection.py里得到的六個參數到相應位置,注釋里已經注明。
***color_tracking.py***
import cv2
from picamera2 import Picamera2
import time
import numpy as np
from servo import Servo
picam2 = Picamera2()#偏航伺服電機連接上GPIO19腳,俯仰伺服電機信號線連接到GPIO16腳上
pan=Servo(pin=19)
tilt=Servo(pin=16)panAngle=0
tiltAngle=0pan.set_angle(panAngle)
tilt.set_angle(tiltAngle)#初始化pi camera
dispW=1280
dispH=720
picam2.preview_configuration.main.size = (dispW,dispH)
picam2.preview_configuration.main.format = "RGB888"
picam2.preview_configuration.controls.FrameRate=30
picam2.preview_configuration.align()
picam2.configure("preview")
picam2.start()
fps=0
pos=(30,60)
font=cv2.FONT_HERSHEY_SIMPLEX
height=1.5
weight=3
myColor=(0,0,255)def nothing(x):passcv2.namedWindow('myTracker')
#輸入color_detection.py里得到的六個參數到xxx位置,比如cv2.createTrackbar('Hue Low','myTracker',xxx,179,nothing)
cv2.createTrackbar('Hue Low','myTracker',56,179,nothing)
cv2.createTrackbar('Hue High','myTracker',179,179,nothing)
cv2.createTrackbar('Sat Low','myTracker',165,255,nothing)
cv2.createTrackbar('Sat High','myTracker',255,255,nothing)
cv2.createTrackbar('Val Low','myTracker',77,255,nothing)
cv2.createTrackbar('Val High','myTracker',255,255,nothing)while True:tStart=time.time()#獲取取攝像頭圖片frame= picam2.capture_array()frame=cv2.flip(frame,1)frameHSV=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)cv2.putText(frame,str(int(fps))+' FPS',pos,font,height,myColor,weight)hueLow=cv2.getTrackbarPos('Hue Low','myTracker')satLow=cv2.getTrackbarPos('Sat Low','myTracker')valLow=cv2.getTrackbarPos('Val Low','myTracker')hueHigh=cv2.getTrackbarPos('Hue High','myTracker')satHigh=cv2.getTrackbarPos('Sat High','myTracker')valHigh=cv2.getTrackbarPos('Val High','myTracker')lowerBound=np.array([hueLow,satLow,valLow])upperBound=np.array([hueHigh,satHigh,valHigh])myMask=cv2.inRange(frameHSV,lowerBound,upperBound)myMaskSmall=cv2.resize(myMask,(int(dispW/2),int(dispH/2)))myObject=cv2.bitwise_and(frame,frame, mask=myMask)myObjectSmall=cv2.resize(myObject,(int(dispW/2),int(dispH/2)))contours,junk=cv2.findContours(myMask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)if len(contours)>0:contours=sorted(contours,key=lambda x:cv2.contourArea(x),reverse=True)#cv2.drawContours(frame,contours,-1,(255,0,0),3)contour=contours[0]x,y,w,h=cv2.boundingRect(contour)cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),3)#偏航電機糾偏X軸方向上的偏差,大于30度,偏航角度減小,小于-30度,偏航角度增加errorX=dispW/2-(x+w/2)if errorX>30:panAngle=panAngle-1if panAngle<-90:panAngle=-90pan.set_angle(panAngle)if errorX<-30:panAngle=panAngle+1if panAngle>90:panAngle=90pan.set_angle(panAngle)#俯仰電機糾偏Y軸方向上的偏差,大于30度,俯仰角度減小,小于-30度,俯仰角度增加errorY=dispH/2-(y+h/2)if errorY>30:tiltAngle=tiltAngle-1if tiltAngle<-90:tiltAngle=-90tilt.set_angle(tiltAngle)if errorY<-30:tiltAngle=tiltAngle+1if tiltAngle>90:tiltAngle=90tilt.set_angle(tiltAngle)cv2.imshow('Camera',frame)cv2.imshow('Mask',myMaskSmall)cv2.imshow('My Object',myObjectSmall)#按q鍵退出if cv2.waitKey(1)==ord('q'):pan.stop()tilt.stop()picam2.stop()breaktEnd=time.time()loopTime=tEnd-tStartfps=.9*fps + .1*(1/loopTime)
cv2.destroyAllWindows()
  1. 上述代碼中的from servo import Servo導入servo,這個庫是沒有的,我們要手動創建這個庫,在object_tracking.py所在的目錄下新建servo.py文件,復制下面的代碼到文件中
#!/usr/bin/env python3
import pigpio
from time import sleep
# Start the pigpiod daemon
import subprocess
result = None
status = 1
for x in range(3):p = subprocess.Popen('sudo pigpiod', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)result = p.stdout.read().decode('utf-8')status = p.poll()if status == 0:breaksleep(0.2)
if status != 0:print(status, result)
'''
> Use the DMA PWM of the pigpio library to drive the servo
> Map the servo angle (0 ~ 180 degree) to (-90 ~ 90 degree)'''class Servo():MAX_PW = 1250  # 0.5/20*100MIN_PW = 250 # 2.5/20*100_freq = 50 # 50 Hz, 20msdef __init__(self, pin, min_angle=-90, max_angle=90):self.pi = pigpio.pi()self.pin = pin self.pi.set_PWM_frequency(self.pin, self._freq)self.pi.set_PWM_range(self.pin, 10000)      self.angle = 0self.max_angle = max_angleself.min_angle = min_angleself.pi.set_PWM_dutycycle(self.pin, 0)def set_angle(self, angle):if angle > self.max_angle:angle = self.max_angleelif angle < self.min_angle:angle = self.min_angleself.angle = angleduty = self.map(angle, -90, 90, 250, 1250)self.pi.set_PWM_dutycycle(self.pin, duty)def get_angle(self):return self.angledef stop(self):self.pi.set_PWM_dutycycle(self.pin, 0)self.pi.stop()# will be called automatically when the object is deleted# def __del__(self):#     passdef map(self, x, in_min, in_max, out_min, out_max):return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_minif __name__ =='__main__':from vilib import Vilib# Vilib.camera_start(vflip=True,hflip=True) # Vilib.display(local=True,web=True)pan = Servo(pin=13, max_angle=90, min_angle=-90)tilt = Servo(pin=12, max_angle=30, min_angle=-90)panAngle = 0tiltAngle = 0pan.set_angle(panAngle)tilt.set_angle(tiltAngle)sleep(1)while True:for angle in range(0, 90, 1):pan.set_angle(angle)tilt.set_angle(angle)sleep(.01)sleep(.5)for angle in range(90, -90, -1):pan.set_angle(angle)tilt.set_angle(angle)sleep(.01)sleep(.5)for angle in range(-90, 0, 1):pan.set_angle(angle)tilt.set_angle(angle)sleep(.01)sleep(.5)
  1. 運行object_tracking.py,移動紅色鉛筆,攝像頭就會自動追蹤該對象
    在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/215153.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/215153.shtml
英文地址,請注明出處:http://en.pswp.cn/news/215153.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣labuladong一刷day30天二叉樹

力扣labuladong一刷day30天二叉樹 文章目錄 力扣labuladong一刷day30天二叉樹一、654. 最大二叉樹二、105. 從前序與中序遍歷序列構造二叉樹三、106. 從中序與后序遍歷序列構造二叉樹四、889. 根據前序和后序遍歷構造二叉樹 一、654. 最大二叉樹 題目鏈接&#xff1a;https://…

智慧機房與3D機房動環監控系統的應用

智慧機房是什么&#xff1f; 智慧機房是集采集信息、實時監控、數據分析、統一管理、故障告警等功能于一體的全方位、立體化的智能環境監控系統&#xff0c;構建物聯網、大數據和云計算背景下現代企業的“數據心臟”。它能為機房管理者呈現細致入微的關鍵性數據&#xff0c;優…

電子學會C/C++編程等級考試2022年06月(五級)真題解析

C/C++等級考試(1~8級)全部真題?點這里 第1題:逃離迷宮 你在一個地下迷宮中找到了寶藏,但是也觸發了迷宮機關,導致迷宮將在T分鐘后坍塌,為此你需要在T分鐘內逃離迷宮,你想知道你能不能逃離迷宮。迷宮是一個邊長為m的正方形,其中"S"表示你所在的位置,"…

<url-pattern>/</url-pattern>與<url-pattern>/*</url-pattern>的區別

<url-pattern>/</url-pattern> servlet的url-pattern設置為/時&#xff0c; 它僅替換servlet容器的默認內置servlet&#xff0c;用于處理所有與其他注冊的servlet不匹配的請求。直白點說就是&#xff0c;所有靜態資源&#xff08;js&#xff0c;css&#xff0c;ima…

HCIA-H12-811題目解析(9)

1、【單選題】下面選項中&#xff0c;能使一臺IP地址為10.0.0.1的主機訪問Interne的必要技術是&#xff1f; 2、【單選題】 FTP協議控制平面使用的端口號為&#xff1f; 3、【單選題】 使用FTP進行文件傳輸時&#xff0c;會建立多少個TCP連接&#xff1f; 4、【單選題】完成…

ubuntu apache2配置反向代理

1.Ubuntu安裝apache sudo apt-get update sudo apt-get install apache2 2.apache2反向代理配置 sudo vim /etc/apache2/sites-available/000-default.conf 添加內容如下&#xff1a; <VirtualHost *:80># The ServerName directive sets the request scheme, host…

目標檢測YOLO實戰應用案例100講-基于深度學習的SAR圖像艦船目標檢測(續)

目錄 4基于自注意力機制的YOLO-v3算法的SAR圖像目標檢測 4.1 YOLO系列發展現狀 4.2自注意力機制

做數據分析為何要學統計學(10)——如何進行時間序列分析

時間序列是由隨時間變化的值構成&#xff0c;如產品銷量、氣溫數據等等。通過對時間序列展開分析&#xff0c;能夠回答如下問題&#xff1a; &#xff08;1&#xff09;被研究對象的活動特征是否有周期性&#xff08;也稱季節性&#xff09;&#xff08;2&#xff09;被研究對…

學生成績管理系統詳細設計書

1. 引言 本學生成績管理系統旨在滿足學校對學生成績進行高效、精準、便捷管理的需求。通過系統化的管理方式&#xff0c;改善現有成績管理方式的不足&#xff0c;提高工作效率&#xff0c;同時保證學生成績信息的準確性和安全性。本詳細設計文檔將為系統的實現提供全面的指導和…

UE4/UE5 修改/還原場景所有Actor的材質

使用藍圖方法&#xff1a; 1.修改場景所有Actor 材質&#xff1a; Wirframe&#xff1a;一個材質類 MatList&#xff1a;獲取到的所有模型的全部材質 的列表 TempAllClass&#xff1a;場景中所有獲取的 Actor 的列表 功能方法如下&#xff1a; 藍圖代碼可復制在&#xff1a…

Unity之OpenXR+XR Interaction Toolkit接入微軟VR設備Windows Mixed Reality

前言 Windows Mixed Reality 是 Microsoft 用于增強和虛擬現實體驗的VR設備,如下圖所示: 在國內,它的使用率很低,一把都是國外使用,所以適配起來是相當費勁。 這臺VR設備只能用于串流Windows,啟動后,會自動連接Window的Mixed Reality程序,然后打開微軟的增強現實門戶…

1.2 輕量級數據交互格式–JSON

對于接口來說,數據交互大部分都是使用的JSON格式,我們這里說的數據,就是我們上一章里講解HTTP協議的時候,HTTP協議結構里的實體,也就是放在body里。body里存放需要傳輸的數據,數據是JSON格式,然后通過HTTP協議來傳輸給接口,接口再以同樣的方式給我們返回。理解了這一層…

網絡基礎(五):網絡層協議介紹

目錄 一、網絡層 1、網絡層的概念 2、網絡層功能 3、IP數據包格式 二、ICMP協議 1、ICMP的作用和功能 2、ping命令的使用 2.1ping命令的通用格式 2.2ping命令的常用參數 2.3TypeCode&#xff1a;查看不同功能的ICMP報文 2.4ping出現問題 3、Tracert 4、沖突域 5、…

LSU介紹

LSU&#xff08;Load Store Unit&#xff09;是一個專門的執行單元&#xff0c;負責執行所有的加載&#xff08;load&#xff09;和存儲&#xff08;store&#xff09;指令等&#xff0c;生成load和store操作的虛擬地址&#xff0c;并從內存中加載數據或將數據從寄存器中存儲回…

關于前端原生技術-Jsonp的理解與簡述

【版權聲明】未經博主同意&#xff0c;謝絕轉載&#xff01;&#xff08;請尊重原創&#xff0c;博主保留追究權&#xff09; https://blog.csdn.net/m0_69908381/article/details/134777717 出自【進步*于辰的博客】 在學習了Jsoup這個知識點之后&#xff0c;發覺js的這一特點…

基于appium的常用元素定位方法

一、元素定位工具   app應用的元素使用的是控件定位&#xff0c;不同于web網頁&#xff0c;web網頁定位元素通常使用的是F12工具&#xff0c;那么在app當中我們則要借助其它的工具來輔助定位。 1.uiautomatorviewer.bat   uiautomatorviewer.bat工具在安裝完ADT工具之后&a…

【Docker】進階之路:(十一)Docker存儲

【Docker】進階之路&#xff1a;&#xff08;十一&#xff09;Docker存儲 Docker存儲簡介storage driverdata volumevolumebind mounttmpfs mount Docker提供了4種存儲方式&#xff1a;默認存儲、volume(數據卷)、bind mounts(綁定掛載)、tmpfsmount(僅在Linux環境中提供)。其中…

Jemeter,提取響應體中的數據:正則表達式、Json提取器

一、正則表達式 1、線程組--創建線程組&#xff1b; 2、線程組--添加--取樣器--HTTP請求&#xff1b; 3、Http請求--添加--后置處理器--正則表達式提取器&#xff1b; 4、線程組--添加--監聽器--查看結果樹&#xff1b; 5、線程組--添加--取樣器--調試取樣器。 響應體數據…

docker mysql8 設置不區分大小寫

docker安裝Mysql8.0的坑之lower_case_table_names_docker mysql lower_case_table_names-CSDN博客https://blog.csdn.net/p793049488/article/details/108365929 docker run ‐di ‐‐nametensquare_mysql ‐p 33306:3306 ‐e MYSQL_ROOT_PASSWORD123456 mysql

運籌學經典問題(一):指派問題

問題描述 有 N N N個任務&#xff0c;需要 N N N個人去完成&#xff0c;每個人完成不同工作的效率不同&#xff08;或者資源、收益等等&#xff09;&#xff0c;需要怎么分配使得整體的效率最高&#xff08;成本最低等等&#xff09;呢&#xff1f;這就是經典的指派問題啦&…