def _exponential_timeout_generator(initial, maximum, multiplier, deadline): """A generator that yields exponential timeout values. Args: initial (float): The initial timeout. maximum (float): The maximum timeout. multiplier (float): The multiplier applied to the timeout. deadline (float): The overall deadline across all invocations. Yields: float: A timeout value. """ if deadline is not None: deadline_datetime = ( datetime_helpers.utcnow() + datetime.timedelta(seconds=deadline)) else: deadline_datetime = datetime.datetime.max timeout = initial while True: now = datetime_helpers.utcnow() yield min( # The calculated timeout based on invocations. timeout, # The set maximum timeout. maximum, # The remaining time before the deadline is reached. float((deadline_datetime - now).seconds)) timeout = timeout * multiplier
def _exponential_timeout_generator(initial, maximum, multiplier, deadline): """A generator that yields exponential timeout values. Args: initial (float): The initial timeout. maximum (float): The maximum timeout. multiplier (float): The multiplier applied to the timeout. deadline (float): The overall deadline across all invocations. Yields: float: A timeout value. """ if deadline is not None: deadline_datetime = datetime_helpers.utcnow() + datetime.timedelta( seconds=deadline) else: deadline_datetime = datetime.datetime.max timeout = initial while True: now = datetime_helpers.utcnow() yield min( # The calculated timeout based on invocations. timeout, # The set maximum timeout. maximum, # The remaining time before the deadline is reached. float((deadline_datetime - now).seconds), ) timeout = timeout * multiplier
def retry_target(target, predicate, sleep_generator, deadline, on_error=None): """Call a function and retry if it fails. This is the lowest-level retry helper. Generally, you'll use the higher-level retry helper :class:`Retry`. Args: target(Callable): The function to call and retry. This must be a nullary function - apply arguments with `functools.partial`. predicate (Callable[Exception]): A callable used to determine if an exception raised by the target should be considered retryable. It should return True to retry or False otherwise. sleep_generator (Iterable[float]): An infinite iterator that determines how long to sleep between retries. deadline (float): How long to keep retrying the target. on_error (Callable): A function to call while processing a retryable exception. Any error raised by this function will *not* be caught. Returns: Any: the return value of the target function. Raises: google.api_core.RetryError: If the deadline is exceeded while retrying. ValueError: If the sleep generator stops yielding values. Exception: If the target raises a method that isn't retryable. """ if deadline is not None: deadline_datetime = (datetime_helpers.utcnow() + datetime.timedelta(seconds=deadline)) else: deadline_datetime = None last_exc = None for sleep in sleep_generator: try: return target() # pylint: disable=broad-except # This function explicitly must deal with broad exceptions. except Exception as exc: if not predicate(exc): raise last_exc = exc if on_error is not None: on_error(exc) now = datetime_helpers.utcnow() if deadline_datetime is not None and deadline_datetime < now: six.raise_from( exceptions.RetryError( 'Deadline of {:.1f}s exceeded while calling {}'.format( deadline, target), last_exc), last_exc) _LOGGER.debug('Retrying due to {}, sleeping {:.1f}s ...'.format( last_exc, sleep)) time.sleep(sleep) raise ValueError('Sleep generator stopped yielding sleep values.')
def lookup_known_face(face_encoding): global facedata_collection, accuracy """ See if this is a face we already have in our face list """ metadata = None # If our known face list is empty, just return nothing since we can't possibly have seen this face. if len(known_face_encodings) == 0: return metadata # Calculate the face distance between the unknown face and every face on in our known face list # This will return a floating point number between 0.0 and 1.0 for each known face. The smaller the number, # the more similar that face was to the unknown face. face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) # Get the known face that had the lowest distance (i.e. most similar) from the unknown face. best_match_index = np.argmin(face_distances) # If the face with the lowest distance had a distance under 0.6, we consider it a face match. # 0.6 comes from how the face recognition model was trained. It was trained to make sure pictures # of the same person always were less than 0.6 away from each other. # Here, we are loosening the threshold a little bit to 0.65 because it is unlikely that two very similar # people will come up to the door at the same time. if face_distances[best_match_index] < accuracy: # If we have a match, look up the metadata we've saved for it (like the first time we saw it, etc) metadata = known_face_metadata[best_match_index] # Update the metadata for the face so we can keep track of how recently we have seen this face. metadata["lastSeen"] = datetime_helpers.utcnow() metadata["seenCount"] += 1 # We'll also keep a total "seen count" that tracks how many times this person has come to the door. # But we can say that if we have seen this person within the last 5 minutes, it is still the same # visit, not a new visit. But if they go away for awhile and come back, that is a new visit. if datetime_helpers.utcnow( ) - metadata["firstSeenThisInteraction"].replace( tzinfo=None) > timedelta(minutes=2): metadata["firstSeenThisInteraction"] = datetime_helpers.utcnow() metadata["seenCount"] += 1 tempDoc = facedata_collection.document(metadata["userId"]) tempDoc.update({ "seenCount": metadata["seenCount"], "lastSeen": metadata["lastSeen"], "seenFrames": metadata["seenFrames"], "firstSeenThisInteraction": metadata["firstSeenThisInteraction"], }) del tempDoc return metadata
def new_face_added(collection_snapshot, changes, read_time): global bucket, facedata_collection, trainface_collection, trainface_notifier for change in changes: if change.type.name == 'ADDED': error = "unknown" temp_doc = change.document.to_dict() try: error = "Dict key" temp_file_name = temp_doc["imageUri"]+".jpg" # wait for file to be available in storage blob = bucket.get_blob(temp_doc["imageUri"]) while blob == None: blob = bucket.get_blob(temp_doc["imageUri"]) continue else: print("Loaded from resource") error = "Image not found " blob.download_to_filename(temp_file_name) frame = cv2.imread(temp_file_name) # cv2 specifics rgb_small_frame = frame[:, :, ::-1] face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) # Check if only once face is present if len(face_locations) is 1 and len(face_encodings) is 1: error = "Dict creation " facedata_document_template = { "editedOn" : datetime_helpers.utcnow(), "faceEncoding" : face_encodings[0].tostring(), "firstSeen" : datetime_helpers.utcnow(), "firstSeenThisInteraction" : datetime_helpers.utcnow(), "imageUri" : temp_doc["imageUri"], "label" : temp_doc["label"], "lastSeen" : datetime_helpers.utcnow(), "seenCount" : 0, "seenFrames" : 0, "userId": change.document.id } error = "Document exsists : Cloud document creation " facedata_collection.add(facedata_document_template, temp_doc["userId"]) print("1 face added") else: blob.delete() trainface_collection.document(change.document.id).delete() os.remove(temp_file_name) print("Done") except : print("{} error while processing {}".format(error, change.document.id)) print(change.document.to_dict()) continue else : pass print("Last updated at {}\n".format(read_time))
def survillence(): global camera, offline while offline: currentTime = datetime_helpers.utcnow() _, frame = camera.read() if _: threading.Thread(target=face_recog, args=(frame, currentTime), daemon=True).start()
def register_new_face(face_encoding, face_image): global db, bucket, facedata_collection document = facedata_collection.document() """ Add a new person to our list of known faces """ # Add the face encoding to the list of known faces known_face_encodings.append(face_encoding) # Add a matching dictionary entry to our metadata list. # We can use this to keep track of how many times a person has visited, when we last saw them, etc. permFileName = document.id + "_faceImage.jpg" cv2.imwrite(permFileName, face_image) blob = bucket.blob(permFileName) blob.upload_from_filename(permFileName) temp_facedata_document = copy.deepcopy(face_data_template) temp_facedata_document["editedOn"] = datetime_helpers.utcnow() temp_facedata_document["firstSeen"] = datetime_helpers.utcnow() temp_facedata_document["faceEncoding"] = face_encoding.tostring() temp_facedata_document[ "firstSeenThisInteraction"] = datetime_helpers.utcnow() temp_facedata_document["imageUri"] = permFileName temp_facedata_document["label"] = "Unknown" temp_facedata_document["lastSeen"] = datetime_helpers.utcnow() temp_facedata_document["seenCount"] = 1 temp_facedata_document["seenFrames"] = 1 temp_facedata_document["userId"] = document.id known_face_metadata.append(temp_facedata_document) document.create(temp_facedata_document) # os.remove(permFileName) save_known_faces() if debug: print("New Face added") return document.id
def register_new_face(face_encoding, face_image): global db, bucket, facedata_collection document = facedata_collection.document() """ Add a new person to our list of known faces """ # Add the face encoding to the list of known faces known_face_encodings.append(face_encoding) # Add a matching dictionary entry to our metadata list. # We can use this to keep track of how many times a person has visited, when we last saw them, etc. known_face_metadata.append( { "first_seen": datetime_helpers.utcnow(), "last_seen": datetime_helpers.utcnow(), "first_seen_this_interaction": datetime_helpers.utcnow(), "seen_count": 1, "seen_frames": 1, "face_image": face_image, "name": "Unknown", "uuid": document.id, } ) permFileName = document.id + "_faceImage.jpg" cv2.imwrite(permFileName, face_image) blob = bucket.blob(permFileName) blob.upload_from_filename(permFileName) facedata_document_template = { "FaceEncodingString": face_encoding.tostring(), "FirstSeen": datetime_helpers.utcnow(), "ImageURI": blob.media_link, "FirstSeenThisInteraction": datetime_helpers.utcnow(), "LastSeen": datetime_helpers.utcnow(), "UserSetLabels": ["Unknown"], "SeenCount": 1, "SeenFrames": 1, } document.create(facedata_document_template) os.remove(permFileName) save_known_faces() if debug: print("New Face added")
def on_need_data(self, src, lenght): global offline if self.cap.isOpened(): currentTime = datetime_helpers.utcnow() ret, frame = self.cap.read() if ret: # Resize frame of video to 1/4 size for faster face recognition processing frame = face_recog(frame, currentTime) data = frame.tostring() buf = Gst.Buffer.new_allocate(None, len(data), None) buf.fill(0, data) buf.duration = self.duration timestamp = self.number_frames * self.duration buf.pts = buf.dts = int(timestamp) buf.offset = timestamp self.number_frames += 1 retval = src.emit("push-buffer", buf) if retval != Gst.FlowReturn.OK and retval == Gst.FlowReturn.FLUSHING: offline = True sur_thread = threading.Thread(target=survillence) sur_thread.start() if debug: print("Going offline, streaming stopped")
"UserSetLables": [], } # This document alone has to be fetched with the UID cameralist_document_template = {"CameraName": [], "CameraURL": []} # Bucket to store image files image_bucket = storage.Client() bucket = image_bucket.get_bucket(projectName + ".appspot.com") document = facedata_collection.document() print(document.id) camera = cv2.VideoCapture(0) _, image = camera.read() if _: currentTime = datetime_helpers.utcnow() # reformat it asap permFileName = (parser["APP_CONFIG"].get("CameraName") + "_" + str(currentTime).replace(" ", "_").replace(":", "_") + ".jpg") cv2.imwrite(permFileName, image) blob = bucket.blob(permFileName) blob.upload_from_filename(permFileName) tempIntruderLogDocument = intruder_collection.document( parser["APP_CONFIG"].get("CameraName") + " " + str(currentTime)) # this uri requires authentication to get a public url make the blob public and get the url # blob.make_public() log_document_template["ImageURL"] = blob.media_link log_document_template["Labels"] = ["test", "test2"] log_document_template["Timestamp"] = currentTime log_document_template["UserID"] = parser["APP_CONFIG"].get(
def retry_target(target, predicate, sleep_generator, deadline, on_error=None): """Call a function and retry if it fails. This is the lowest-level retry helper. Generally, you'll use the higher-level retry helper :class:`Retry`. Args: target(Callable): The function to call and retry. This must be a nullary function - apply arguments with `functools.partial`. predicate (Callable[Exception]): A callable used to determine if an exception raised by the target should be considered retryable. It should return True to retry or False otherwise. sleep_generator (Iterable[float]): An infinite iterator that determines how long to sleep between retries. deadline (float): How long to keep retrying the target. on_error (Callable): A function to call while processing a retryable exception. Any error raised by this function will *not* be caught. Returns: Any: the return value of the target function. Raises: google.api_core.RetryError: If the deadline is exceeded while retrying. ValueError: If the sleep generator stops yielding values. Exception: If the target raises a method that isn't retryable. """ if deadline is not None: deadline_datetime = ( datetime_helpers.utcnow() + datetime.timedelta(seconds=deadline)) else: deadline_datetime = None last_exc = None for sleep in sleep_generator: try: return target() # pylint: disable=broad-except # This function explicitly must deal with broad exceptions. except Exception as exc: if not predicate(exc): raise last_exc = exc if on_error is not None: on_error(exc) now = datetime_helpers.utcnow() if deadline_datetime is not None and deadline_datetime < now: six.raise_from( exceptions.RetryError( 'Deadline of {:.1f}s exceeded while calling {}'.format( deadline, target), last_exc), last_exc) _LOGGER.debug('Retrying due to {}, sleeping {:.1f}s ...'.format( last_exc, sleep)) time.sleep(sleep) raise ValueError('Sleep generator stopped yielding sleep values.')
def test_utcnow(): result = datetime_helpers.utcnow() assert isinstance(result, datetime.datetime)
async def retry_target(target, predicate, sleep_generator, deadline, on_error=None): """Call a function and retry if it fails. This is the lowest-level retry helper. Generally, you'll use the higher-level retry helper :class:`Retry`. Args: target(Callable): The function to call and retry. This must be a nullary function - apply arguments with `functools.partial`. predicate (Callable[Exception]): A callable used to determine if an exception raised by the target should be considered retryable. It should return True to retry or False otherwise. sleep_generator (Iterable[float]): An infinite iterator that determines how long to sleep between retries. deadline (float): How long to keep retrying the target. The last sleep period is shortened as necessary, so that the last retry runs at ``deadline`` (and not considerably beyond it). on_error (Callable[Exception]): A function to call while processing a retryable exception. Any error raised by this function will *not* be caught. Returns: Any: the return value of the target function. Raises: google.api_core.RetryError: If the deadline is exceeded while retrying. ValueError: If the sleep generator stops yielding values. Exception: If the target raises a method that isn't retryable. """ deadline_dt = ((datetime_helpers.utcnow() + datetime.timedelta(seconds=deadline)) if deadline else None) last_exc = None for sleep in sleep_generator: try: if not deadline_dt: return await target() else: return await asyncio.wait_for( target(), timeout=(deadline_dt - datetime_helpers.utcnow()).total_seconds(), ) # pylint: disable=broad-except # This function explicitly must deal with broad exceptions. except Exception as exc: if not predicate(exc) and not isinstance(exc, asyncio.TimeoutError): raise last_exc = exc if on_error is not None: on_error(exc) now = datetime_helpers.utcnow() if deadline_dt: if deadline_dt <= now: # Chains the raising RetryError with the root cause error, # which helps observability and debugability. raise exceptions.RetryError( "Deadline of {:.1f}s exceeded while calling {}".format( deadline, target), last_exc, ) from last_exc else: time_to_deadline = (deadline_dt - now).total_seconds() sleep = min(time_to_deadline, sleep) _LOGGER.debug("Retrying due to {}, sleeping {:.1f}s ...".format( last_exc, sleep)) await asyncio.sleep(sleep) raise ValueError("Sleep generator stopped yielding sleep values.")
def face_recog(frame, currentTime=None): global known_face_encodings, known_face_metadata, thread_counter, debug, \ log_document_template, db, bucket, devId, frequency, parser, intruder_collection, \ model_options, model_mode temp_log_document = copy.deepcopy(log_document_template) permFileName = (devId + "_" + str(currentTime).replace(" ", "_").replace(":", "_") + ".jpg") small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses) rgb_small_frame = small_frame[:, :, ::-1] # Find all the face locations and face encodings in the current frame of video face_locations = face_recognition.face_locations( rgb_small_frame, model=model_options[model_mode]) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) # Loop through each detected face and see if it is one we have seen before # If so, we'll give it a label that we'll draw on top of the video. face_labels = [] doc_id_path = "" for face_location, face_encoding in zip(face_locations, face_encodings): # See if this face is in our list of known faces. metadata = lookup_known_face(face_encoding) # If we found the face, label the face with some useful information. if metadata is not None: face_label = metadata["label"] doc_id_path = "/" + parser["CLOUD_CONFIG"].get( "FAD") + "/" + metadata["userId"] # If this is a brand new face, add it to our list of known faces else: face_label = "New visitor!" # Grab the image of the the face from the current frame of video top, right, bottom, left = face_location face_image = small_frame[top:bottom, left:right] face_image = cv2.resize(face_image, (150, 150)) # Add the new face to our known face data doc_id_path = ("/" + parser["CLOUD_CONFIG"].get("FAD") + "/" + register_new_face(face_encoding, face_image)) face_labels.append(face_label) temp_log_document["peopleDetected"].append(doc_id_path) # Draw a box around each face and label each face for (top, right, bottom, left), face_label in zip(face_locations, face_labels): # Scale back up face locations since the frame we detected in was scaled to 1/4 size top *= 4 right *= 4 bottom *= 4 left *= 4 # Draw a box around the face cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) # Draw a label with a name below the face cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) cv2.putText( frame, face_label, (left + 6, bottom - 6), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 255, 255), 1, ) thread_counter += 1 if len(temp_log_document["peopleDetected"] ) and frequency // 2 < thread_counter < frequency: thread_counter = frequency if thread_counter % frequency == 0: if debug: print() print("Total threads completed :", thread_counter) thread_counter = 0 if logging: cv2.imwrite(permFileName, frame) blob = bucket.blob(permFileName) blob.upload_from_filename(permFileName) tempIntruderLogDocument = intruder_collection.document( devId + " " + str(currentTime)) temp_log_document["timestamp"] = datetime_helpers.utcnow() temp_log_document["imageUri"] = permFileName temp_log_document["location"] = "/" + parser["CLOUD_CONFIG"].get( "CAM") + "/" + devId tempIntruderLogDocument.create(temp_log_document) del temp_log_document del tempIntruderLogDocument os.remove(permFileName) return frame
def test_utcnow(): result = datetime_helpers.utcnow() assert isinstance(result, datetime.datetime)
def face_recog(frame, currentTime=None): global known_face_encodings, known_face_metadata, thread_counter, debug, db, bucket, devId, frequency log_document_template = { "ImageURL": None, "Labels": [], "Timestamp": currentTime, "UserID": None, } permFileName = ( devId + "_" + str(currentTime).replace(" ", "_").replace(":", "_") + ".jpg" ) small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses) rgb_small_frame = small_frame[:, :, ::-1] # Find all the face locations and face encodings in the current frame of video face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) # Loop through each detected face and see if it is one we have seen before # If so, we'll give it a label that we'll draw on top of the video. face_labels = [] for face_location, face_encoding in zip(face_locations, face_encodings): # See if this face is in our list of known faces. metadata = lookup_known_face(face_encoding) # If we found the face, label the face with some useful information. if metadata is not None: time_at_door = datetime_helpers.utcnow() - metadata[ "first_seen_this_interaction" ].replace(tzinfo=None) face_label = f"At door {int(time_at_door.total_seconds())}s" face_label = metadata["name"] # If this is a brand new face, add it to our list of known faces else: face_label = "New visitor!" # Grab the image of the the face from the current frame of video top, right, bottom, left = face_location face_image = small_frame[top:bottom, left:right] face_image = cv2.resize(face_image, (150, 150)) # Add the new face to our known face data register_new_face(face_encoding, face_image) face_labels.append(face_label) log_document_template["Labels"].append(face_label) # Draw a box around each face and label each face for (top, right, bottom, left), face_label in zip(face_locations, face_labels): # Scale back up face locations since the frame we detected in was scaled to 1/4 size top *= 4 right *= 4 bottom *= 4 left *= 4 # Draw a box around the face cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) # Draw a label with a name below the face cv2.rectangle( frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED ) cv2.putText( frame, face_label, (left + 6, bottom - 6), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255, 255, 255), 1, ) thread_counter += 1 if thread_counter % frequency == 0: thread_counter = 0 if debug: print("Total threads completed :", thread_counter) if logging: cv2.imwrite(permFileName, frame) blob = bucket.blob(permFileName) blob.upload_from_filename(permFileName) intruder_collection = db.collection(parser["CLOUD_CONFIG"].get("LOG")) tempIntruderLogDocument = intruder_collection.document( devId + " " + str(currentTime) ) log_document_template["ImageURL"] = blob.media_link log_document_template["UserID"] = devId tempIntruderLogDocument.create(log_document_template) os.remove(permFileName) del log_document_template del tempIntruderLogDocument del intruder_collection return frame