- 今天在github上找了一天终于找到了一个关于opencv和pid控制的程序,运气不错,竟然这么快找到了分享给大家:
这是python文件
detectBall.py
Python的串口通信(pyserial)使用方法:
详解:
https://www.cnblogs.com/dongxiaodong/p/9992083.html
import cv2
import numpy as np
import imutils
from collections import deque
import serial #导入串口通信模块
import time
import struct
#定义“绿色”的下限和上限
#在HSV色彩空间球
colorLower = (15*180/240, 140 , 150)#HSV
colorUpper = (40*180/240, 255 , 255)#HSV
ser = serial.Serial("com9", 9600)
time.sleep(2)
# 从网络摄像头捕获视频
camera = cv2.VideoCapture(0)
while(True):
##s= time.time()
#逐帧捕获
ret, frame = camera.read()
#帧= cv2.flip(帧,1)
#调整框架大小,模糊它,并将其转换为HSV
frame = imutils.resize(frame, width=600)
##height, width = frame.shape[:2]
#过滤器
frame = cv2.GaussianBlur(frame, (11, 11), 0)
frame = cv2.medianBlur(frame,5)
#从RGB到HSV
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv, colorLower, colorUpper)
mask = cv2.erode(mask, None, iterations=2)
mask = cv2.dilate(mask, None, iterations=2)
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
#中心=无
#仅在找到至少一个轮廓时才进行
if len(cnts) > 0:
#找到面具中最大的轮廓,然后使用
#它计算最小的封闭圆和
#重心
c = max(cnts, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(c)
M = cv2.moments(c)
center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
#仅在半径满足最小尺寸时才进行
if radius > 10:
#画出框架上的圆圈和质心,
#然后更新跟踪点列表
cv2.circle(frame, (int(x), int(y)), int(radius),(0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
## print(“x =”,int(x),“y =”,int(y))
#框架宽度= 600和高度= 450
#映射到0-180
dx=int(x/600*180)
dy=int(y/450*180)
print ("x=",int(dx),"y=",int(dy))
ser.write(struct.pack('>BB',dx,dy));
#显示结果帧
cv2.imshow('frame1',hsv)
cv2.imshow('frame2',mask)
cv2.imshow('Result',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
##e= time.time()
##print (s-e)
#完成所有操作后,释放捕获
ser.close()
camera.release()
cv2.destroyAllWindows()
下面这是plate.ino的代码:
#include <PID_v1.h>
#include <Servo.h>
Servo servoX;
Servo servoY;
double inputX, inputY, outputX, outputY;
double setPointX=(300/600*90);
double setPointY=(225/450*90) ;
PID myPID(&inputX, &outputX, &setPointX, 1, 0.2, 0.4, DIRECT);
PID myPID2(&inputY, &outputY, &setPointY, 1, 0.3, 0.1, DIRECT);
void setup()
{
Serial.begin(9600);
pinMode(13,OUTPUT);
servoX.attach(5);
servoY.attach(6);
myPID.SetMode(AUTOMATIC);
myPID2.SetMode(AUTOMATIC);
}
void loop()
{
if (Serial.available() >= 2){
inputX = Serial.read();
inputY = Serial.read();
myPID.Compute();
myPID2.Compute();
servoX.write(inputX);
servoY.write(inputY);
digitalWrite(13,HIGH);
delay(inputX*4);
digitalWrite(13,LOW);
delay(inputY*4);
}
}