Skip to content

Commit

Permalink
Complete creating auto documentation from docstrings
Browse files Browse the repository at this point in the history
  • Loading branch information
eroniki committed Feb 13, 2019
1 parent 36db925 commit 5ed22ba
Show file tree
Hide file tree
Showing 8 changed files with 347 additions and 12 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,17 @@ The main controller of the code lay in __main.py__ file. This python script crea
The basic User Interface is created by using Flask, a web development tool for Python.

All the necessary tools and classes were implemeted in this class, which reside in __app.py__ module.

The documentation of the computer_vision class is automatically generated from the docstrings of the classes and the functions in it.
The documentation is located [here](docs/app.md).
## Utility Class
The documentation of the utility class is automatically generated from the docstrings of the classes and the functions in it.
The documentation is located [here](docs/utils.md).
## Experiment Class

The documentation of the experiment class is automatically generated from the docstrings of the classes and the functions in it.
The documentation is located [here](docs/experiment.md).
## Computer Vision Class

The documentation of the computer_vision class is automatically generated from the docstrings of the classes and the functions in it.
The documentation is located [here](docs/computer_vision.md).
## Pose Detection Class

## Camera Class
Expand Down
53 changes: 50 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
"""
This module contains a class to create the REST API.
The flask_app class contains all the functions and utilities needed to provide
the REST API.
"""
import numpy as np
import cv2
import json
Expand All @@ -21,7 +27,12 @@


class flask_app(object):
"""docstring for flask_app."""
"""
This module contains a class to create the REST API.
The flask_app class contains all the functions and utilities needed to provide
the REST API.
"""

def __init__(self, key):
super(flask_app, self).__init__()
Expand Down Expand Up @@ -52,14 +63,17 @@ def __init__(self, key):
self.create_endpoints()

def load_users(self):
"""Load users for authorization purposes from the json file."""
return self.um.read_json("users.json")

def load_rooms(self):
"""Load rooms for authorization purposes from the json file."""
devices_data = self.um.read_json("devices.json")
rooms = self.um.parse_rooms(devices_data)
return rooms

def create_endpoints(self):
"""Create API endpoints."""
self.app.add_url_rule("/",
"index",
self.index)
Expand Down Expand Up @@ -184,14 +198,17 @@ def create_endpoints(self):
self.app.view_functions['triangulate'] = self.triangulate

def index(self):
"""Render the homepage."""
return render_template('index.html')

@flask_login.login_required
def video(self, room_name):
"""Render the video page."""
return render_template('video.html', user=room_name)

@flask_login.login_required
def video_feed(self, room_name):
"""Run the cameras in a room."""
if room_name.lower() == "cears":
room_id = 1
elif room_name.lower() == "computer_lab":
Expand All @@ -206,6 +223,7 @@ def video_feed(self, room_name):

@flask_login.login_required
def test_camera(self, camera):
"""Test the camera and return the image."""
dev = list()
for room in self.rooms:
for device in room["devices"]:
Expand All @@ -214,6 +232,7 @@ def test_camera(self, camera):
mimetype='multipart/x-mixed-replace; boundary=frame')

def gen(self, camera):
"""Camera generator for the actual tests."""
img_id = 0
while True:
frame = camera.get_all_frames(img_id)
Expand All @@ -222,7 +241,7 @@ def gen(self, camera):
img_id += 1

def gen_testcamera(self, camera):
"""Video streaming generator function."""
"""Camera generator for the test_camera endpoint."""
cap = cv2.VideoCapture(camera)
retval, frame = cap.read()
cap.release()
Expand All @@ -235,6 +254,7 @@ def gen_testcamera(self, camera):

@flask_login.login_required
def label_experiment(self, exp_id):
"""Create/Update the label of an experiment."""
exp = experiment.experiment(new_experiment=False, ts=str(exp_id))
label = request.form.get('label')
exp.update_metadata(change_label=True, label=label)
Expand All @@ -243,6 +263,7 @@ def label_experiment(self, exp_id):

@flask_login.login_required
def check_experiment(self, id):
"""Provide details of an experiment."""
exp = experiment.experiment(new_experiment=False, ts=id)

start_time = time.time()
Expand Down Expand Up @@ -286,9 +307,9 @@ def check_experiment(self, id):
"pose_detection_processed_images": pd_images}
return render_template('experiment.html', user=user)

# TODO: Implement this
@flask_login.login_required
def clone_experiment(self, id):
"""Clone experiment to the cloud."""
archive_name = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"backup", str(id)+".zip")
cmd = ["rclone", "copy", archive_name, "Team_BUILD:/backup"]
Expand All @@ -297,6 +318,7 @@ def clone_experiment(self, id):

@flask_login.login_required
def list_experiments(self):
"""List all the experiments."""
subfolders = self.um.list_subfolders("data/*/")
experiment_folders = self.um.list_experiments(subfolders)
experiments = list()
Expand All @@ -322,13 +344,15 @@ def list_experiments(self):

@flask_login.login_required
def delete_experiment(self, exp_id):
"""Delete an experiment with the given id."""
folder = self.um.experiment_path(exp_id)
self.um.delete_folder(folder)

return "OK"

@flask_login.login_required
def delete_archive(self, exp_id):
"""Delete the zip file."""
archive_name = os.path.join(os.path.dirname(os.path.realpath(__file__)),
"backup", str(exp_id)+".zip")
self.um.delete_file(archive_name)
Expand All @@ -337,6 +361,7 @@ def delete_archive(self, exp_id):

@flask_login.login_required
def compress_experiment(self, exp_id):
"""Compress the whole data corresponding to an experiment."""
exp_folder = self.um.experiment_path(str(exp_id))[:-1]
exp_folder = os.path.join(os.path.dirname(
os.path.realpath(__file__)), exp_folder)
Expand All @@ -352,6 +377,7 @@ def compress_experiment(self, exp_id):

@flask_login.login_required
def status_room(self, room_name):
"""Check the status of a room."""
if room_name.lower() == "cears":
room_id = 1
elif room_name.lower() == "computer_lab":
Expand All @@ -373,6 +399,7 @@ def status_room(self, room_name):

@flask_login.login_required
def status_all_rooms(self):
"""Check the status of all rooms."""
statements = str()
for room_id in range(2):
devices = self.rooms[room_id]["devices"]
Expand All @@ -391,6 +418,7 @@ def status_all_rooms(self):
return statements

def login(self):
"""Login to the system."""
if flask.request.method == 'GET':
return '''
<form action='login' method='POST'>
Expand Down Expand Up @@ -420,14 +448,17 @@ def login(self):
return 'Bad login'

def logout(self):
"""Logout from the system."""
flask_login.logout_user()
return 'Logged out'

@flask_login.login_required
def protected():
"""Show logged username."""
return 'Logged in as: ' + flask_login.current_user.id

def user_loader(self, email):
"""Check if the user in the user.json file."""
if email not in self.users:
return

Expand All @@ -436,6 +467,7 @@ def user_loader(self, email):
return user

def request_loader(self, request):
"""Handle each request."""
email = request.form.get('email')
if email not in self.users:
return
Expand All @@ -450,9 +482,11 @@ def request_loader(self, request):
return user

def unauthorized_handler(self):
"""If the user is unauthorized, direct him/her to the login page."""
return flask.redirect("/login")

def pose_img(self, exp_id, camera_id, img_id):
"""Employ pose detection on a single image."""
pd = pose_detection()
exp = experiment.experiment(new_experiment=False, ts=exp_id)
room_name = exp.metadata["room"]
Expand All @@ -477,6 +511,10 @@ def pose_img(self, exp_id, camera_id, img_id):
return response

def pose_cam(self, exp_id, camera_id):
"""
Employ pose_detection on the all images with a given experiment and
the camera id.
"""
pd = pose_detection()
exp = experiment.experiment(new_experiment=False, ts=exp_id)
room_name = exp.metadata["room"]
Expand Down Expand Up @@ -525,6 +563,10 @@ def pose_cam(self, exp_id, camera_id):
return "{n} number of images were processed!".format(n=n-1)

def pose_exp(self, exp_id):
"""
Given an experiment id to employ pose_detection on the whole images
collected from all the cameras.
"""
pd = pose_detection()
exp = experiment.experiment(new_experiment=False, ts=exp_id)
ncamera = exp.metadata["number_of_cameras"]
Expand All @@ -542,21 +584,25 @@ def pose_exp(self, exp_id):
return statement

def match_people(self, exp_id):
"""Match people based on feature matching algorithm."""
n = 99999

return "{n} number of images were processed!".format(n=n)

def make_thumbnails(self, exp_id):
"""Create a thumbnail from an image, which contains only one person."""
n = 99999

return "{n} number of images were processed!".format(n=n)

def triangulate(self, exp_id):
"""Triangulate people's locations."""
n = 99999

return "{n} number of images were processed!".format(n=n)

def log(self):
"""Return the system logs. 10 lines."""
lines = tailer.tail(open('logs/status.log'), 10)

statement = ""
Expand All @@ -566,6 +612,7 @@ def log(self):
return statement

def log_n(self, n):
"""Return n number of lines from the system logs."""
lines = tailer.tail(open('logs/status.log'), n)

statement = ""
Expand Down
7 changes: 7 additions & 0 deletions build_doc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pydocmd simple utils.utils.misc+ > docs/utils.md
pydocmd simple camera.VideoCamera++ > docs/camera.md
pydocmd simple experiment.experiment++ > docs/experiment.md
pydocmd simple computer_vision.computer_vision++ > docs/computer_vision.md
pydocmd simple app.flask_app++ > docs/app.md


18 changes: 17 additions & 1 deletion computer_vision.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
"""
This module contains a class for primitive computer vision operations.
The computer_vision class contains all the functions and utilities needed for
the provide primitive computer vision operations.
"""
import cv2
import numpy as np


class computer_vision(object):
"""docstring for computer_vision."""
"""
This module contains a class for primitive computer vision operations.
The computer_vision class contains all the functions and utilities needed
for the provide primitive computer vision operations.
"""

def __init__(self):
super(computer_vision, self).__init__()

@staticmethod
def triangulate(P1, P2, points1, point2):
"""Triangulate corresponding points with given projection matrices."""
return cv2.triangulatePoints(P1, P2, points1, points2)

@staticmethod
def extract_features(img, thr=0.005):
"""Extract features from an image, return keypoints and descriptors."""
if img.ndims == 3:
img = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)

Expand All @@ -23,6 +36,7 @@ def extract_features(img, thr=0.005):

@staticmethod
def match_meaturs(desc1, desc2):
"""Match extracted descriptors, return good matching ones."""
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
matches = bf.knnMatch(desc1, desc2, k=2) # typo fixed

Expand All @@ -36,6 +50,7 @@ def match_meaturs(desc1, desc2):

@staticmethod
def extract_thumbnail(img, joints):
"""Extract a thumbnail from an image, containing only one person."""
x_min, y_min = np.min(joints, axis=0)
x_max, y_max = np.max(joints, axis=0)
[h, w, _] = img.shape
Expand All @@ -54,4 +69,5 @@ def extract_thumbnail(img, joints):

@staticmethod
def undistort_points(points, K, dist):
"""Undistort points to eliminate the lens distortion."""
return cv2.undistortPoints(points, K, dist)

0 comments on commit 5ed22ba

Please sign in to comment.