我的对象检测opencv代码在大约半分钟内运行良好,然后冻结。当我将应该从照相机中检测到的对象移开时,显示框架的窗口(并且我也假定代码)会冻结,直到将对象重新带回相机的视图中(如果识别出该对象会立即冻结)对象)。
我将串行通信从opencv脚本连接到arduino,该arduino控制用于调整相机方向的电机,以便我检测到的对象移动到相机POV的中心。
我认为这可能是一个处理问题,因此我摆脱了.erode()
和.dilate()
命令,但没有任何改变。在制作颜色遮罩或搜索轮廓时,代码似乎冻结了。
Python代码
import cv2
import numpy
import serial
import time
ser=serial.Serial("COM11", 9600) #open serial port
def nothing(x):
pass
capture=cv2.VideoCapture(0)
while capture.isOpened:
lower_hsv=numpy.array([60, 90, 116]) #hsv values set so that it only sees a certain shade of blue
upper_hsv=numpy.array([125, 251, 255])
ret, frame=capture.read()
blur=cv2.GaussianBlur(frame, (5,5), 0) #blurs the BGR
hsv=cv2.cvtColor(blur,cv2.COLOR_BGR2HSV) #changes blurred BGR to HSV
mask=cv2.inRange(hsv, lower_hsv, upper_hsv)
mask=cv2.erode(mask, None, iterations=2)
mask=cv2.dilate(mask, None, iterations=2)
contours,_=cv2.findContours(mask.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(contours)>0:
for contour in contours:
if cv2.contourArea(contour) < 800:
continue
else:
(x,y), radius=cv2.minEnclosingCircle(contour)
center=(int(x), int(y))
radius=int(radius)
cv2.circle(frame, center, radius, (0, 255, 0), 2)
print(center)
if center[0]<300:
ser.write('L'.encode()) #if ball is to the left, rotate the motor to the left
elif center[0]>340:
ser.write('R'.encode()) #if ball is to the right, rotate motor to the right
elif center[1]<220:
ser.write('D'.encode()) #if the ball is below, rotate the motor down
elif center[1]>260:
ser.write('U'.encode())
else:
print('not sending anything')
result=cv2.bitwise_and(frame, frame, mask=mask)
cv2.imshow('original',frame)
if cv2.waitKey(1)==27:
break
cv2.destroyAllWindows()
capture.release()
Arduino代码
const int motorA_1 = 9;
const int motorA_2 = 10;
const int motorB_1 = 5;
const int motorB_2 = 6;
char inputData;
void setup() {
// put your setup code here, to run once:
pinMode(motorA_1, OUTPUT);
pinMode(motorA_2, OUTPUT);
pinMode(motorB_1, OUTPUT);
pinMode(motorB_2, OUTPUT);
Serial.begin(9600);
Serial.println("<Arduino is ready>");
}
void loop() {
// put your main code here, to run repeatedly:
if (Serial.available()>0){
inputData=Serial.read();
if (inputData == 'R'){
digitalWrite(motorA_1,HIGH);
digitalWrite(motorA_2,LOW);
delay(10);
}
else if(inputData=='L'){
digitalWrite(motorA_1,LOW);
digitalWrite(motorA_2,HIGH);
delay(10);
}
else if(inputData=='U'){
digitalWrite(motorB_1,HIGH);
digitalWrite(motorB_2,LOW);
delay(10);
}
else if(inputData=='D'){
digitalWrite(motorB_1,LOW);
digitalWrite(motorB_2,HIGH);
delay(10);
}
}
else{
doNothing();
}
}
void doNothing(){
Serial.println("doing nothing");
digitalWrite(motorA_1, LOW);
digitalWrite(motorA_2, LOW);
digitalWrite(motorB_1, LOW);
digitalWrite(motorB_2, LOW);
delay(20);
我希望脚本一直运行到我按'esc'键终止它为止,但是如果我运行30秒钟以上,它将崩溃。