I'm running a program which records a 5 second video and analyses it every 30 seconds. The program runs for a while but after like an hour or so it fails saying
● clocktwist.service - My Pendulum Cavity Twist Logger Service
Loaded: loaded (/lib/systemd/system/clocktwist.service; enabled)
Active: failed (Result: exit-code) since Wed 2017-05-24 01:59:01 UTC; 6h ago
Process: 1576 ExecStart=/usr/bin/python /home/pi/trinity_twist.py > /home/pi/twist.log 2>&1 (code=exited, status=1/FAILURE)
Main PID: 1576 (code=exited, status=1/FAILURE)
May 24 01:59:01 raspberrypi python[1576]: self.renderer.connect(source)
May 24 01:59:01 raspberrypi python[1576]: File "/usr/lib/python2.7/dist- packages/picamera/mmalobj.py", line 1467, in connect
May 24 01:59:01 raspberrypi python[1576]: self._connection = MMALConnection(source, self.inputs[0])
May 24 01:59:01 raspberrypi python[1576]: File "/usr/lib/python2.7/dist-packages/picamera/mmalobj.py", line 1280, in __init__
May 24 01:59:01 raspberrypi python[1576]: prefix="Failed to enable connection")
May 24 01:59:01 raspberrypi python[1576]: File "/usr/lib/python2.7/dist-packages/picamera/exc.py", line 157, in mmal_check
May 24 01:59:01 raspberrypi python[1576]: raise PiCameraMMALError(status, prefix)
May 24 01:59:01 raspberrypi python[1576]: picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources (other than memory)
The code is a bit lengthy so I'd rather not post the full thing. A snippet of the part using the piCamera code
with picamera.PiCamera() as camera:
camera.resolution=(1640,1232)
camera.framerate= 30
camera.start_recording("{}".format(video_name_h264))
camera.wait_recording(record_length)
camera.stop_recording()
I don't think it's the problem though since it works as expected until the MMALError occurs. I have used sudo apt-get update but I can't say if it's fixed it until the error occurs. I've read that error usually occurs when two or more processes attempt to use the camera simultaneously but I don't think that's the case for me as it's the only program I have using PiCamera on reboot. However, is there a way to check if another program is using the camera?
Is there a reason why it works initially then fails? When I restart it, it seems to work just fine again.
I'm a bit of a newbie so I was thinking of using Try and Except to restart it when the error occurs. How do I go about it and how do I raise the MMAL error to test if I've coded it correctly?
CODE
#Python 3.2.3 (default, Mar 1 2013, 11:53:50)
#[GCC 4.6.3] on linux2
#Type "copyright", "credits" or "license()" for more information.
import os
from subprocess import call
import datetime
import time
import traceback
import sys
import picamera
import numpy as np
import imageio
import matplotlib as mpl
mpl.use('Agg')
from PIL import Image
from matplotlib import pyplot as plt
from matplotlib import patches as patch
from time import sleep
import cv2
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def send_error_email(body,subject):
fromaddr = "**********@gmail.com"
toaddr = "*********@gmail.com"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = subject
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo
server.starttls()
server.login(fromaddr, "*******")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
def clean_image (image):
image =cv2.GaussianBlur(image,(9,9),0)
thresh = cv2.threshold(image, 220, 255, cv2.THRESH_BINARY)[1]#200 initially
#thresh = cv2.erode(thresh, None, iterations=1)
#thresh = cv2.dilate(thresh, None, iterations=2)
im_clean = thresh
return im_clean
def find_first_blob_coords(contours,imCopy):
global blob_found
contour_areas = [cv2.contourArea(contour) for contour in contours]
max_index = np.argmax(contour_areas)
max_contour=contours[max_index]
contour_moment = cv2.moments(max_contour)
if contour_moment['m00']!=0:
cx = (contour_moment['m10']/contour_moment['m00'])
cy = (contour_moment['m01']/contour_moment['m00'])
blob_found=True
else:
cx=0
cy=0
blob_found=False
return cx, cy, blob_found
def find_blob_coords (frame,index,video_name):
global cx, cy, blob_found, radius, height, width
#Load Image, Resize and Convert To Grayscale
im = frame
image_name="{}-index{}cleaned.png".format(video_name,index)
#im_name="{}-index{}.png".format(video_name,index)
#im =cv2.resize(im,None,fx=0.5, fy=0.5, interpolation = cv2.INTER_AREA)
height, width, channels = im.shape
im =cv2.cvtColor(im, cv2.COLOR_RGB2GRAY )
#cv2.imwrite(im_name,im)
while blob_found==True:
#If Blob found in Previous Frame
#Set Region of Interest (roi) to look for blob in frame
xmin = int(max(0,cx-40))
ymin = int(max(0,cy-40))
xmax = int(min(width, cx +40))
ymax = int(min(height, cy+40))
roi = im[ymin:ymax,
xmin:xmax]
#roi=im
thresh = clean_image (roi)
imCopy = cv2.cvtColor(thresh, cv2.COLOR_GRAY2RGB)
contours, hierarchy= cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE)
if len(contours)!=0:
cropped_cx, cropped_cy, blob_found= find_first_blob_coords(contours, imCopy)
cx = cropped_cx+ xmin
cy = cropped_cy+ ymin
if blob_found==True:
return np.array([index,cx,cy])
else:
#cv2.imwrite(image_name,roi)#Change im to roi for troubleshooting
blob_found=False
print "no blob found in cropped frame #{}".format(index)
return []
if blob_found==False:
#If Blob not found in Previous Frame
#searches whole image rather than ROI
thresh = clean_image (im)
imCopy = cv2.cvtColor(thresh, cv2.COLOR_GRAY2RGB )
contours, hierarchy= cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_NONE)
if len(contours)!=0:
cx, cy, blob_found= find_first_blob_coords(contours, imCopy)
#cv2.imwrite(image_name,imCopy)
if blob_found==True:
return np.array([index,cx,cy])
else:
#cv2.imwrite(image_name,im)
blob_found=False
print "no blob found in frame #{}".format(index)
return []
def plot_trajectory(x_coords, y_coords):
global index, height, width
plt.figure()
#plt.axis((0,width,0,height))
plt.scatter(x_coords.astype(np.float), -(y_coords.astype(np.float)))
numberOfBlobsDetected=x_coords.size
plt.title("Laser Trajectory-{}/{}blobs found".format(numberOfBlobsDetected
,index))
plt.xlabel("x_coords")
plt.ylabel("y_coords")
plt.savefig("{}-trajectory.png".format(video_name))
def trajectory_analysis(results):
frame_no=results[1:,0]
#time= frame_no/5
x_coords=results[1:,1]
y_coords=results[1:,2]
plot_trajectory(x_coords, y_coords)
plt.close('all')
fig, axarr = plt.subplots(2, sharex=True)
axarr[0].plot(frame_no, x_coords)
axarr[0].set_title("Trajectory Coordinates vs Frame Number")
axarr[0].set_xlabel("Frame Number")
axarr[0].set_ylabel("x coordinate")
axarr[1].set_xlabel("Frame Number")
axarr[1].set_ylabel("y coordinate")
axarr[1].plot(frame_no, y_coords)
fig.savefig("{}_analysis.png".format(video_name))
xmax=max(x_coords.astype(np.float))
xmin=min(x_coords.astype(np.float))
print "xmax:{}".format(xmax)
print "xmin:{}".format(xmin)
print "dx :{}".format(xmax-xmin)
## print "ymax:{}".format(max(y_coords))
## print "ymin:{}".format(min(y_coords))
## print "dy :{}".format(max(y_coords)-min(y_coords))
index_b=0
previous_twist=0
while True:
index=0
index_found=0
try:
tic= time.time()
record_length=5
start_time=datetime.datetime.now()
start_time_formatted=start_time.strftime("%Y-%m-%d")
year_month=start_time.strftime("%Y/%m/")
path="/home/pi/Twist/"
new_path="{}{}".format(path,year_month)
txt_name="{}{}.txt".format(new_path,start_time_formatted)
#Makes directory if it doesn't exist
if not os.path.exists(new_path):
os.makedirs(new_path)
f=open("{}".format(txt_name), "a+")
print("\n start of analysis")
#Initialise Variables to be used by functions
blob_found=False
cx=cy=radius=index=height=width=0
#Names image to be saved with timestamp so it is unique
time_now=datetime.datetime.now()
time_formatted=time_now.strftime("%Y-%m-%d_%H-%M-%S")
##time_formatted="testing"
video_name= "/home/pi/camera/{}".format(time_formatted)
video_name_h264= "{}.h264".format(video_name)
video_name_mp4= "{}.mp4".format(video_name)
video_name_txt= "{}.txt".format(video_name)
#Camera takes picture and saves its name as the time stamp
print("taking video")
time_recorded= time.time()
with picamera.PiCamera() as camera:
camera.vflip = True
camera.resolution=(1640,1232)
camera.framerate= 30
camera.start_recording("{}".format(video_name_h264))
camera.wait_recording(record_length)
camera.stop_recording()
#convert h264 to mp4 using gpac wrapper so it can be watched on PC/Mac
call("MP4Box -fps 30 -add {} {}".format(video_name_h264,video_name_mp4),shell=True)
#Loads Video
vid = cv2.VideoCapture(video_name_mp4)
#results=np.array(["index","x-coord","y-coord"])
#Check if Video was Loaded Properly
if not vid.isOpened():
print "can't open video"
#Iterates through each video frame and finds blob
while(vid.isOpened()):
index=index+ 1
ret, frame= vid.read()
frames=int(vid.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
if ret==True:
#frame=frame[400:900,500:1100]
index_results=find_blob_coords(frame,index,video_name)
if index_results!=[]:
index_found=index_found+1
if index_found==1:
results=index_results
else:
#print index_results
results=np.vstack((results, index_results))
if index==frames-1:
print "last frame"
break
#print"results {}".format(results)
x_coords=results[:,1]
xmax=max(x_coords.astype(np.float))
xmin=min(x_coords.astype(np.float))
twist=(xmax-xmin)*0.119
time_recorded=time_recorded+record_length/2
f.write("{} {} \n".format(tic,twist))
f.close #saves file
f=open("{}".format(txt_name), "a+")
os.remove("{}".format(video_name_mp4))
print"mp4 deleted"
if abs(twist-previous_twist)>2:
trajectory_analysis(results)
else:
os.remove("{}".format(video_name_h264))
print"h264 deleted"
previous_twist=twist
time_now=time.time()
programtime=time_now-tic
print "sleeping"
while (int(time.time())-int(tic))<30:
sleep(0.001)
index_b= index_b+1
## print index_b
## if index_b==2:
## raise picamera.PiCameraMMALError(picamera.mmal.MMAL_ENOSPC)
except picamera.exc.PiCameraError,err:
print "something went wrong"
traceback.print_exc(file=sys.stdout)
traceback_message=traceback.format_exc()
picamera.PiCamera().close()
error_message=str(err)
body="{}\n\n{}".format(traceback_message,error_message)
subject="Camera Error Alert"
send_error_email(body,subject)
except ValueError,e:
print"Value Error"
traceback.print_exc(file=sys.stdout)
traceback_message=traceback.format_exc()
picamera.PiCamera().close()
error_message=str(err)
body="{}\n\n{}".format(traceback_message,error_message)
subject="Value Error Alert"
send_error_email(body,subject)