So I have been using opencv pretty sucessfully over the last week to do the grunt work or tracking motion but I have come upon a very wierd snag over the last two days. While trying to send multiple char's over the serial port something snags after a random amount of time normally over 15 seconds. Its is random and I have no idea whats causing it at first I thought mabye I wasn't resetting a table in the arduino and it's memory was running out and my program was just waiting for the serial to come back but then I looked at cpu usage on my laptop. It goes from 26-30% at .6gb to 100% when it snags. Another wierd thing about when it snags is both the TX and RX led's light up on the arduino so I am assuming they are sending and recieving serial? My laptop isn't reporting anything happening over serial though? That and if I press the reset button on the arduino the led's just stay on even after I kill the program on my laptop. I have to physically unplug the arduino before that stops. While it is doing the LED thing I can't re-upload the arduino either so I am assuming something is going on serially. I have been hunting around online and I think I am doing everything right but I am little confused. If someone could go over my code and help out it would be amazing. I am using python on an ubuntu 14.04 os.
Python Code.
import cv
import serial
import time
import threading
import sys
class Target:
def __init__(self):
self.capture = cv.CaptureFromCAM(0)
cv.NamedWindow("Target", 1)
def run(self):
# Capture first frame to get size
frame = cv.QueryFrame(self.capture)
frame_size = cv.GetSize(frame)
grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1)
moving_average = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 3)
difference = None
ser = serial.Serial("/dev/ttyACM0", 9600)
connected = 0
while connected == 0:
ser.write("c") #Seeing if the arduino is open to com yet
if ser.read() == 4: #Arduino saying it is open to com
connected = 1
time.sleep(1)
while connected == 1:
# Capture frame from webcam
color_image = cv.QueryFrame(self.capture)
# Smooth to get rid of false positives
cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0)
if not difference:
# Initialize
difference = cv.CloneImage(color_image)
temp = cv.CloneImage(color_image)
cv.ConvertScale(color_image, moving_average, 1.0, 0.0)
else:
cv.RunningAvg(color_image, moving_average, 0.020, None)
# Convert the scale of the moving average.
cv.ConvertScale(moving_average, temp, 1.0, 0.0)
# Minus the current frame from the moving average.
cv.AbsDiff(color_image, temp, difference)
# Convert the image to grayscale.
cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY)
# Convert the image to black and white.
cv.Threshold(grey_image, grey_image, 70, 255, cv.CV_THRESH_BINARY)
# Dilate and erode to get object blobs
cv.Dilate(grey_image, grey_image, None, 18)
cv.Erode(grey_image, grey_image, None, 10)
# Calculate movements
storage = cv.CreateMemStorage(0)
contour = cv.FindContours(grey_image, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)
points = []
while contour:
# Draw rectangles
bound_rect = cv.BoundingRect(list(contour))
contour = contour.h_next()
pt1 = (bound_rect[0], bound_rect[1])
pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3])
points.append(pt1)
points.append(pt2)
cv.Rectangle(color_image, pt1, pt2, cv.CV_RGB(255,0,0), 1)
num_points = len(points)
if num_points:
# Draw bullseye in midpoint of all movements
x = y = 0
for point in points:
x += point[0]
y += point[1]
x /= num_points
y /= num_points
center_point = (x, y)
cv.Circle(color_image, center_point, 40, cv.CV_RGB(255, 255, 255), 1)
cv.Circle(color_image, center_point, 30, cv.CV_RGB(255, 100, 0), 1)
cv.Circle(color_image, center_point, 20, cv.CV_RGB(255, 255, 255), 1)
cv.Circle(color_image, center_point, 10, cv.CV_RGB(255, 100, 0), 5)
#############serial communication###########
ser.write("n") #checking if arduino is ready for new cordinates
read = ser.read()
if read == '3': #arduino saying it's ready for new cordinates
ser.write(str(center_point[0]))
time.sleep(.01)
ser.write(str(center_point[1]))
ser.read(timeout =.5)
print(center_point[1])
print(ser.readline(len(str(center_point[1]))+3))
# Display frame to user
cv.ShowImage("Target", color_image)
# Listen for ESC or ENTER key
c = cv.WaitKey(7) % 0x100
if c == 27 or c == 10:
break
if __name__=="__main__":
t = Target()
t.run()
Arduino Code
char myChar;
String content = "";
char character;
void setup()
{
pinMode(5, OUTPUT);
Serial.begin(9600);
}
void loop()
{
//if (Serial.available())
//{
//myChar = Serial.read();
//if (myChar == 'c'
//{
// Serial.write(4);
//}
//else if (myChar == '2')
//{
// Serial.write(3);
//}
//oldData = newData; // overwrite last input
//newData = myChar.toInt(); // fetching the new data
//Data = newData + oldData; // keeping count of the data
//}
while(Serial.available()) {
character = Serial.read();
content.concat(character);
}
// myChar = Serial.read();
if (character == 'c') // first varible saying to connect
{
Serial.write('4'); // just saying it's connected
}
else if (character == 'n') // need to change to motor control varible
{
Serial.write('3'); // flow varible to accept new value
}
if (content != "") {
Serial.println(content);
//delay();
character = 0;
content = 0; //this is a new line it adds about 1 minute longer before the the program becomes unresponsive
}
}
Upon further reveiw of the serial monitor the Arduino sketch program has it appears the character n is being printed with twice the amount of n's as the time before so at 5600 times a second it umm gets very large very quickly and the processor is trying to catch up. I am not really sure how to fix this?