0

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)
2
  • 1
    It's a little tricky to diagnose without seeing all of your code - is it possible you could be using a threaded approach? That could result in one program accessing the camera on multiple threads, causing a failure.
    – goobering
    May 24, 2017 at 11:44
  • @goobering just added the code. How do I know if it is accessing it on multiple threads? Thanks
    – Baba
    May 25, 2017 at 11:00

1 Answer 1

2

Might be a bit late on this, but I had a similar problem. I think your problem lies with you instantiating picamera.PiCamera() again. i.e. inside your with statement you are instantiating a PiCamera() class each time it executes.

Just move the instantiation outside of the while loop and use it from within the loop like this: -

camera = picamera.PiCamera()
while true:
    ...
    camera.vflip =  True
    camera.resolution = (1640,1232)
    etc

This explains why it works first time and not subsequent times.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.