Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion config/cameratraps.yml

This file was deleted.

6 changes: 4 additions & 2 deletions config/fetch_and_alert.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ checkpoint_frequency: -1
#log_dir - path to logs (must create this folder first)
log_dir: /home/johnsmith/cougarvision/logs/
#classes - path to the class list for the classifier model
classes: /home/johnsmith/cougarvision/labels/sw_classes.txt
class_list: /home/johnsmith/cougarvision/labels/sw_classes.txt
#the emails that will receive email alerts, can be multiple emails
consumer_emails: [<insert emails>]
# the amiul (s) you with to receive the developmemt email alert- contains confidence value of detection
dev_emails: [<insert emails>]
#threshold confidence score
confidence: 0.7
confidence_threshold: 0.7
#cpu threads
threads: 8
# Web Scraping
Expand Down Expand Up @@ -44,3 +44,5 @@ admin: admin@email.com
token: '<insert token>'
#authorization bearer token retreived from same earthranger interactive api example requests
authorization: 'Bearer <insert authorization>'
#folder for data
camera_traps_path: /home/ctl/CameraTraps
126 changes: 0 additions & 126 deletions cougarvision_utils/ImageCropGenerator.py

This file was deleted.

27 changes: 17 additions & 10 deletions cougarvision_utils/cropping.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@
]


def draw_bounding_box_on_image(image,
ymin,
xmin,
ymax,
xmax,
def draw_bounding_box_on_image(detection,
clss=None,
thickness=4,
expansion=0,
Expand Down Expand Up @@ -86,13 +82,24 @@ def draw_bounding_box_on_image(image,
else:
color = COLORS[int(clss) % len(COLORS)]

draw = ImageDraw.Draw(image)
im_width, im_height = image.size
label = detection['prediction']
# uncomment this line to use conf value for dev email alert
prob = str(detection['conf'])

img = Image.open(detection['file'])

x_min = detection['bbox_x']
y_min = detection['bbox_y']
x_max = detection['bbox_x'] + detection['bbox_width']
y_max = detection['bbox_y'] + detection['bbox_height']

draw = ImageDraw.Draw(img)
im_width, im_height = img.size
if use_normalized_coordinates:
(left, right, top, bottom) = (xmin * im_width, xmax * im_width,
ymin * im_height, ymax * im_height)
(left, right, top, bottom) = (x_min * im_width, x_max * im_width,
y_min * im_height, y_max * im_height)
else:
(left, right, top, bottom) = (xmin, xmax, ymin, ymax)
(left, right, top, bottom) = (x_min, x_max, y_min, y_max)

if expansion > 0:
left -= expansion
Expand Down
113 changes: 45 additions & 68 deletions cougarvision_utils/detect_img.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,17 @@
post_event_er.py, and attach_image_er.py as well as some functions
that must be imported from animl.
'''

from io import BytesIO
from datetime import datetime as dt
import re
import sys
import yaml
from PIL import Image
from animl import parse_results, classify, split

import animl
from sageranger import is_target, attach_image, post_event
from animl.detectMD import detect_MD_batch

from cougarvision_utils.cropping import draw_bounding_box_on_image
#from cougarvision_utils.cropping import draw_bounding_box_on_image
from cougarvision_utils.alert import smtp_setup, send_alert


with open("config/cameratraps.yml", 'r') as stream:
CAM_CONFIG = yaml.safe_load(stream)
sys.path.append(CAM_CONFIG['camera_traps_path'])


def detect(images, config, c_model, d_model):
'''
This function takes in a dataframe of images and runs a detector model,
Expand All @@ -41,85 +32,63 @@ def detect(images, config, c_model, d_model):
config: the unpacked config values from fetch_and_alert.yml that contains
necessary parameters the function needs
'''
email_alerts = bool(config['email_alerts'])
er_alerts = bool(config['er_alerts'])
log_dir = config['log_dir']
checkpoint_f = config['checkpoint_frequency']
confidence = config['confidence']
classes = config['classes']

classes = animl.load_class_list(config['class_list'])['class']
targets = config['alert_targets']
username = config['username']
password = config['password']
consumer_emails = config['consumer_emails']
dev_emails = config['dev_emails']
host = 'imap.gmail.com'
token = config['token']
authorization = config['authorization']
confidence_threshold = config['confidence_threshold']

if len(images) > 0:
# extract paths from dataframe
image_paths = images[:, 2]
# Run Detection
results = detect_MD_batch(d_model,
image_paths,
checkpoint_path=None,
confidence_threshold=confidence,
checkpoint_frequency=checkpoint_f,
results=None,
quiet=False,
image_size=None)
results = animl.detect(d_model,
images,
1280, 1280,
checkpoint_path=None,
confidence_threshold=confidence_threshold,
checkpoint_frequency=config['checkpoint_frequency'],
batch_size=4)
# Parse results
data_frame = parse_results.from_MD(results, None, None)
data_frame = animl.parse_detections(results)
# filter out all non animal detections
if not data_frame.empty:
animal_df = split.getAnimals(data_frame)
other_df = split.getEmpty(data_frame)
animal_df = animl.get_animals(data_frame)
# run classifier on animal detections if there are any
if not animal_df.empty:
# create generator for images
predictions = classify.predict_species(animal_df, c_model,
batch=4)
predictions = animl.classify(c_model, animal_df,
resize_height=299, resize_width=299,
batch_size=4)
# Parse results
max_df = parse_results.from_classifier(animal_df,
predictions,
classes,
None)
max_df = animl.single_classification(animal_df, None, predictions, classes,)
# Creates a data frame with all relevant data
cougars = max_df[max_df['prediction'].isin(targets)]
# drops all detections with confidence less than threshold
cougars = cougars[cougars['conf'] >= confidence]
cougars = cougars[cougars['conf'] >= confidence_threshold]
# reset dataframe index
cougars = cougars.reset_index(drop=True)
# create a row in the dataframe containing only the camera name
# flake8: disable-next
cougars['cam_name'] = cougars['file'].apply(lambda x: re.findall(r'[A-Z]\d+', x)[0]) # noqa: E501 # pylint: disable-msg=line-too-long
# Sends alert for each cougar detection
for idx in range(len(cougars.index)):
label = cougars.at[idx, 'prediction']
# uncomment this line to use conf value for dev email alert
prob = str(cougars.at[idx, 'conf'])
label = cougars.at[idx, 'class']
img = Image.open(cougars.at[idx, 'file'])
draw_bounding_box_on_image(img,
cougars.at[idx, 'bbox2'],
cougars.at[idx, 'bbox1'],
cougars.at[idx,
'bbox2'] +
cougars.at[idx,
'bbox4'],
cougars.at[idx,
'bbox1'] +
cougars.at[idx,
'bbox3'],
expansion=0,
use_normalized_coordinates=True)
for i, row in cougars.iterrows():
# draw bounding box on image
#img = draw_bounding_box_on_image(row, expansion=0, use_normalized_coordinates=True)
img = animl.plot_box(row, file_col='file', prediction=True)
# save image
image_bytes = BytesIO()
img.save(image_bytes, format="JPEG")
img_byte = image_bytes.getvalue()
cam_name = cougars.at[idx, 'cam_name']
if label in targets and er_alerts is True:

label = row['prediction']
prob = str(row['conf'])
cam_name = row['cam_name']
# connect to earthranger
if bool(config['er_alerts']):
token = config['token']
authorization = config['authorization']

is_target(cam_name, token, authorization, label)
# Email or Earthranger alerts as dictated in the config yml
if er_alerts is True:

event_id = post_event(label,
cam_name,
token,
Expand All @@ -130,14 +99,22 @@ def detect(images, config, c_model, d_model):
authorization,
label)
print(response)
if email_alerts is True:
# email alerts
if bool(config['email_alerts']):
username = config['username']
password = config['password']
host = 'imap.gmail.com'
consumer_emails = config['consumer_emails']
dev_emails = config['dev_emails']

smtp_server = smtp_setup(username, password, host)
dev = 0
send_alert(label, image_bytes, smtp_server,
username, consumer_emails, dev, prob)
dev = 1
send_alert(label, image_bytes, smtp_server,
username, dev_emails, dev, prob)

# Write Dataframe to csv
date = "%m-%d-%Y_%H:%M:%S"
cougars.to_csv(f'{log_dir}dataframe_{dt.now().strftime(date)}')
3 changes: 1 addition & 2 deletions cougarvision_utils/log_utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import csv
import os.path

import yaml
import logging

with open("config/fetch_and_alert.yml", 'r') as stream:
config = yaml.safe_load(stream)
Expand Down
Loading