<jupyter_start><jupyter_text>Import modules<jupyter_code>#camera modules
import picamera as pc
from picamera.array import PiRGBArray

#thread management
from multiprocessing import Queue
from threading import Thread,Lock
from collections import deque

#image manipulation
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

#general modules
import time,datetime
import pickle
import sys

#saving images and vision analysis
import io
import os
from PIL import Image

#uploading to google cloud storage
from gcloud import storage
from oauth2client.service_account import ServiceAccountCredentials<jupyter_output><empty_output><jupyter_text>Initialize Picamera and Capture Frames from Video Stream<jupyter_code>class Video_Camera(Thread):
    
    """ Initializes PiCamera and captures frames from the video stream.
    
    Functions:
        __init__(self,fps,width,height,vflip,hflip,mins): Initializes
        the camera and video stream using parameters including
            fps (int): The amount of Frames captured Per Second by camera
            width (int): Width of image to be captured in pixels
            height (int): Height of image to be captured in pixels
            vflip (boolean): Used to flip the image vertically
            hflip (boolean): Used to flip the image horizontally
            mins (int): Number of minutes of video to store in memory. 
            Used to minimize memory footprint.
        initialize_camera(self): Starts camera class
        initialize_video_stream(self): Starts color (RGB) video stream
        apply_camera_day_settings(self): Alters camera properties to day settings
        apply_camera_night_settings(self): Alters camera properties to night settings
        run(self): Starts thread, Initializes PiCamera and captures frames 
        from the video stream
   
    Args:
        msg (Thread): A thread is an execution context, which is the 
        information a CPU needs to execute a stream of instructions.
    """
    
    def __init__(self,fps,width,height,vflip,hflip,mins):
        self.fps=fps
        self.width=width
        self.height=height
        self.vflip=vflip
        self.hflip=hflip
        self.mins=mins
        #Deque storage data structures
        #Set max length of X minutes to prevent memory errors
        self.input_deque=deque(maxlen=fps*mins*60) 
        #start the thread, deamon and kill switch
        super(Video_Camera, self).__init__()
        self.daemon = True
        self.kill_all_threads= False
        print (self, 'created')
        #Initialize camera and video stream
        self.initialize_camera()
        self.initialize_video_stream()
        self.person_present=False
        print ('Camera and video stream initialized')
        
    def initialize_camera(self):
        self.camera = pc.PiCamera(
            resolution=(self.width,self.height), 
            framerate=int(self.fps))
        #Set camera properties
        self.camera.vflip = self.vflip
        self.camera.hflip = self.hflip
        self.apply_camera_day_settings()
        
    def initialize_video_stream(self):
        self.rawCapture = pc.array.PiRGBArray(self.camera, size=self.camera.resolution) 
        self.stream = self.camera.capture_continuous(self.rawCapture,
             format="bgr", 
             use_video_port=True)
    
    def apply_camera_day_settings(self):
        self.camera.exposure_mode = 'auto'
        self.camera.contrast=0
        self.camera.brightness=50
        self.camera.exposure_compensation=0

    def apply_camera_night_settings(self):
        self.camera.exposure_mode = 'auto'
        self.camera.contrast=20
        self.camera.brightness=90
        self.camera.exposure_compensation=6
            
            
    def run(self):
        #This method is run when the command start() is given to the thread
        print ('Video stream is now being captured')
        for f in self.stream:
            
            #add frame with timestamp to input queue
            self.input_deque.append({
                'time':time.time(),
                'frame_raw':f.array})
            
            #remove the frame from the stream 
            self.rawCapture.truncate(0)
            
            if self.kill_all_threads==True:
                print (self, 'terminated')
                break<jupyter_output><empty_output><jupyter_text>FPS must be over 1, and an integer<jupyter_code>#Initialize Video_Camera Thread
video_camera = Video_Camera(fps=2,
                            width=384,
                            height=224,
                            vflip=True,
                            hflip=False,
                            mins=1)
#Begin capturing raw video and store data in the input_queue
video_camera.start()
class Frame_Writer(Thread):
    """ 
    Running process to write to cloud storage
    """
    def __init__(self, Video_Camera, project, bucket_name, base_filename, local_filename):
        self.Video_Camera=Video_Camera
        self.project=project
        self.bucket_name=bucket_name
        self.base_filename=base_filename
        self.local_filename=local_filename
        # for writing to could storage
        client = storage.Client(self.project)
        self.bucket = client.get_bucket(self.bucket_name)
        # thread init
        super(Frame_Writer, self).__init__()
        self.daemon = True
        self.kill_all_threads= False
        print (self, 'created')
    
    def write_to_storage(self,output_name,processed_image):
        # declare end name in the bucket
        blob = self.bucket.blob(self.base_filename+output_name)
        # upload from the image itself
        im = Image.fromarray(processed_image)
        imageBuffer = io.BytesIO()
        im.save(imageBuffer, 'JPEG')
        imageBuffer.seek(0)
        blob.upload_from_file(file_obj=imageBuffer,size=imageBuffer.getbuffer().nbytes)
        # close out this memory
        imageBuffer.close()
    
    def run(self):
        while self.kill_all_threads!=True:
            #This method is run when the command start() is given to the thread
            raw_image = None
            count = 0
            # sample from the left (oldest) side of the deque by removing it
            try:
                oldest_deque_entry = self.Video_Camera.input_deque.popleft()
                raw_frame = oldest_deque_entry['frame_raw']
                processed_image = np.flipud(raw_frame[:, :, ::-1]) 
                # push into cloud storage
                output_name=time.strftime('%Y_%m_%d-%H_%M_%S',time.localtime(oldest_deque_entry['time']))
                self.write_to_storage(output_name,processed_image)
                print ('Processed image sent to storage: %S',output_name)
                print ('Current time: %s',time.strftime('%Y_%m_%d-%H_%M_%S',time.localtime(time.time())))
            except IndexError:
                print ('No images available to consume from the queue')
                #sleep if there is nothing to pull
                time.sleep((self.Video_Camera.fps)/2.0)
        
        
#Initialize Frame_Writer Thread
frame_writer = Frame_Writer(
    Video_Camera=video_camera,
    project='loyal-order-204316',
    bucket_name='pi_images_iotworldhackathon',
    base_filename='pi_test_v0_',
    local_filename='temp_image.jpg')
#Begin capturing raw video and store data in the input_queue
frame_writer.start()<jupyter_output><empty_output><jupyter_text>Debugging Functions<jupyter_code>def visualize_recent_frame(video_camera):
    try:
        # sample from the right side of the deque by removing it
        newest_deque_entry=video_camera.input_deque.pop()
        # add this frame back to the deque
        video_camera.input_deque.append(newest_deque_entry)
        #process the frame
        raw_frame=newest_deque_entry['frame_raw']
        processed_frame=(np.flipud(raw_frame[:, :, ::-1]))
        plt.imshow(processed_frame)
    except IndexError:
        print("Cannot pop from an empty deque - let deque fill first")<jupyter_output><empty_output><jupyter_text>Visualize most recent frame (If available on input queue)<jupyter_code>visualize_recent_frame(video_camera)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07607108081791626, 'fraction_numerical': 0.004259980525803311, 'mean_word_length': 2.5803921568627453, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '510110', 'license': 'MIT', 'n_tokens_mistral': 2363, 'n_tokens_neox': 2270, 'n_words': 607, 'path': 'notebooks/PiCamera - Video Processing To Cloud Storage.ipynb', 'repo_name': 'mrubash1/ml_pipeline_tutorial', 'size': '8216'}