Skip to content
Snippets Groups Projects
Commit 53ae810d authored by Zsedrovits Tamás's avatar Zsedrovits Tamás
Browse files

Added comments, corrected function and variable names and function types.

parent 74f98868
Branches
No related tags found
No related merge requests found
# The default ``config.py``
# flake8: noqa
def set_prefs(prefs):
"""This function is called before opening the project"""
# Specify which files and folders to ignore in the project.
# Changes to ignored resources are not added to the history and
# VCSs. Also they are not returned in `Project.get_files()`.
# Note that ``?`` and ``*`` match all characters but slashes.
# '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
# 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
# '.svn': matches 'pkg/.svn' and all of its children
# 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
# 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
'.hg', '.svn', '_svn', '.git', '.tox']
# Specifies which files should be considered python files. It is
# useful when you have scripts inside your project. Only files
# ending with ``.py`` are considered to be python files by
# default.
# prefs['python_files'] = ['*.py']
# Custom source folders: By default rope searches the project
# for finding source folders (folders that should be searched
# for finding modules). You can add paths to that list. Note
# that rope guesses project source folders correctly most of the
# time; use this if you have any problems.
# The folders should be relative to project root and use '/' for
# separating folders regardless of the platform rope is running on.
# 'src/my_source_folder' for instance.
# prefs.add('source_folders', 'src')
# You can extend python path for looking up modules
# prefs.add('python_path', '~/python/')
# Should rope save object information or not.
prefs['save_objectdb'] = True
prefs['compress_objectdb'] = False
# If `True`, rope analyzes each module when it is being saved.
prefs['automatic_soa'] = True
# The depth of calls to follow in static object analysis
prefs['soa_followed_calls'] = 0
# If `False` when running modules or unit tests "dynamic object
# analysis" is turned off. This makes them much faster.
prefs['perform_doa'] = True
# Rope can check the validity of its object DB when running.
prefs['validate_objectdb'] = True
# How many undos to hold?
prefs['max_history_items'] = 32
# Shows whether to save history across sessions.
prefs['save_history'] = True
prefs['compress_history'] = False
# Set the number spaces used for indenting. According to
# :PEP:`8`, it is best to use 4 spaces. Since most of rope's
# unit-tests use 4 spaces it is more reliable, too.
prefs['indent_size'] = 4
# Builtin and c-extension modules that are allowed to be imported
# and inspected by rope.
prefs['extension_modules'] = []
# Add all standard c-extensions to extension_modules list.
prefs['import_dynload_stdmods'] = True
# If `True` modules with syntax errors are considered to be empty.
# The default value is `False`; When `False` syntax errors raise
# `rope.base.exceptions.ModuleSyntaxError` exception.
prefs['ignore_syntax_errors'] = False
# If `True`, rope ignores unresolvable imports. Otherwise, they
# appear in the importing namespace.
prefs['ignore_bad_imports'] = False
# If `True`, rope will insert new module imports as
# `from <package> import <module>` by default.
prefs['prefer_module_from_imports'] = False
# If `True`, rope will transform a comma list of imports into
# multiple separate import statements when organizing
# imports.
prefs['split_imports'] = False
# If `True`, rope will remove all top-level import statements and
# reinsert them at the top of the module when making changes.
prefs['pull_imports_to_top'] = True
# If `True`, rope will sort imports alphabetically by module name instead
# of alphabetically by import statement, with from imports after normal
# imports.
prefs['sort_imports_alphabetically'] = False
# Location of implementation of
# rope.base.oi.type_hinting.interfaces.ITypeHintingFactory In general
# case, you don't have to change this value, unless you're an rope expert.
# Change this value to inject you own implementations of interfaces
# listed in module rope.base.oi.type_hinting.providers.interfaces
# For example, you can add you own providers for Django Models, or disable
# the search type-hinting in a class hierarchy, etc.
prefs['type_hinting_factory'] = (
'rope.base.oi.type_hinting.factory.default_type_hinting_factory')
def project_opened(project):
"""This function is called after opening the project"""
# Do whatever you like here!
File added
from djitellopy import Tello
""" This file contains a program to control a DJI Tello drone.
It finds specific QR codes on the drone's video and projects an AR image onto the frames.
For QR code recognition it uses Dynamsoft Barcode Reader.
To handle frames it uses OpenCV.
To control the drone and show the video, it uses pygame.
"""
import time
import cv2
import pygame
import numpy as np
import time
import os
import sys
from djitellopy import Tello
from dbr import *
# Speed of the drone
......@@ -13,7 +17,7 @@ S = 60
# A low number also results in input lag, as input information is processed once per frame.
FPS = 120
class FrontEnd(object):
class FrontEnd():
""" Maintains the Tello display and moves it through the keyboard keys.
Press escape key to quit.
The controls are:
......@@ -30,7 +34,7 @@ class FrontEnd(object):
self.im_width = 320
self.im_height = 240
# Creat pygame window
pygame.display.set_caption("Tello video stream")
self.screen = pygame.display.set_mode([self.im_width, self.im_height])
......@@ -55,7 +59,7 @@ class FrontEnd(object):
self.json_file = "settings.json"
self.reader = BarcodeReader()
self.arIms = [cv2.imread('minta1.png', cv2.IMREAD_UNCHANGED), cv2.imread('minta2.png', cv2.IMREAD_UNCHANGED),
self.ar_images = [cv2.imread('minta1.png', cv2.IMREAD_UNCHANGED), cv2.imread('minta2.png', cv2.IMREAD_UNCHANGED),
cv2.imread('minta3.png', cv2.IMREAD_UNCHANGED), cv2.imread('minta4.png', cv2.IMREAD_UNCHANGED)]
# Keeps the detected qr code between frames for a while to lessen the flashing effect
......@@ -90,27 +94,32 @@ class FrontEnd(object):
# store AR images for overlay to decrease flashing
self.warped = []
# The callback function for receiving barcode results
def on_barcode_result(self,data):
""" The callback function for receiving barcode results."""
self.qrcodes = data
self.capture_time = self.get_time
def get_time(self):
@staticmethod
def get_time():
""" The function for reading current time."""
localtime = time.localtime()
capturetime = time.strftime("%Y%m%d%H%M%S", localtime)
return capturetime
def decorate_frame(self,frame):
""" This function adds the warped AR images to the given frame.
Arguments:
frame: frame to project the warped AR images onto
"""
frame = frame.astype(float)
if self.detection_smooth_counter >= 0:
for warped in self.warped:
background = frame
(h,w) = background.shape[:2]
foreground = warped[:,:,:3]
alpha1 = warped[...,-1]
alpha = cv2.merge((alpha1,alpha1,alpha1))
# Display results
# Convert uint8 to float
foreground = foreground.astype(float)
background = background.astype(float)
......@@ -130,7 +139,10 @@ class FrontEnd(object):
return frame
def calculate_warped(self):
if self.qrcodes != None:
""" Calculates transformed images to add to the frames, based on the QR codes.
If no QR codes are found or in the queue the list of warped images is deleted.
"""
if self.qrcodes is not None:
capture_time = self.capture_time
self.warped = []
self.detection_smooth_counter = 60
......@@ -147,72 +159,91 @@ class FrontEnd(object):
points = text_result.localization_result.localization_points
if text_result.barcode_text == '1':
arIm = self.arIms[0]
ar_image = self.ar_images[0]
elif text_result.barcode_text == '2':
arIm = self.arIms[1]
ar_image = self.ar_images[1]
elif text_result.barcode_text == '3':
arIm = self.arIms[2]
ar_image = self.ar_images[2]
elif text_result.barcode_text == '4':
arIm = self.arIms[3]
ar_image = self.ar_images[3]
else:
arIm = np.zeros([1,1,3])
ar_image = np.zeros([1,1,3])
# Calculate transform
dst = self.order_points(points)
convHullSize = np.max(arIm.shape)
destination_points = self.order_points(points)
convex_hull_size = np.max(ar_image.shape)
scale = 4
verticalDisplacement = 0
horizontalDisplacement = -(1.5*convHullSize/scale)
rect = np.array([
[-horizontalDisplacement, -verticalDisplacement],
[-horizontalDisplacement + convHullSize/scale - 1, -verticalDisplacement],
[-horizontalDisplacement + convHullSize/scale - 1, -verticalDisplacement + convHullSize/scale - 1],
[-horizontalDisplacement, -verticalDisplacement + convHullSize/scale - 1]], dtype = "float32")
M = cv2.getPerspectiveTransform(rect, dst)
self.warped.append(cv2.warpPerspective(arIm, M, (self.im_width, self.im_height)))
vertical_displacement = 0
horizontal_displacement = -(1.5*convex_hull_size/scale)
rectangular = np.array([
[-horizontal_displacement, -vertical_displacement],
[-horizontal_displacement + convex_hull_size/scale - 1, -vertical_displacement],
[-horizontal_displacement + convex_hull_size/scale - 1, -vertical_displacement + convex_hull_size/scale - 1],
[-horizontal_displacement, -vertical_displacement + convex_hull_size/scale - 1]], dtype = "float32")
transformation_matrix = cv2.getPerspectiveTransform(rectangular, destination_points)
self.warped.append(cv2.warpPerspective(ar_image, transformation_matrix, (self.im_width, self.im_height)))
if self.capture_time == capture_time:
self.qrcodes = None
else:
self.detection_smooth_counter = self.detection_smooth_counter-1
def ResizeWithAspectRatio(self,image, width=None, height=None, inter=cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
@staticmethod
def resize_with_aspect_ratio( image, width=None, height=None, interpolation_method=cv2.INTER_AREA):
""" This function resizes an image based on the given width or height,
keeping the aspect ratio. The interpolation method can be specified
with the interpolation_method parameter.
Arguments:
image: image to resize
width: image width
height: image height
interpolation_method: method used for interpolation in OpenCV
"""
dimensions = None
(original_height, original_width) = image.shape[:2]
if width is None and height is None:
return image
if width is None:
r = height / float(h)
dim = (int(w * r), height)
ratio = height / float(original_height)
dimensions = (int(original_width * ratio), height)
else:
r = width / float(w)
dim = (width, int(h * r))
return cv2.resize(image, dim, interpolation=inter)
def order_points(self,pts):
ratio = width / float(original_width)
dimensions = (width, int(original_height * ratio))
return cv2.resize(image, dimensions, interpolation=interpolation_method)
@staticmethod
def order_points(points):
""" Orders 2D points of a given rectangular such that
the first entry in the list is the top-left,
the second entry is the top-right,
the third is the bottom-right, and
the fourth is the bottom-left.
Arguments:
points: array or list of 2D points
"""
# if points are in a list, construct an array
pts = np.array(pts, dtype="float32")
points = np.array(points, dtype="float32")
# initialzie a list of coordinates that will be ordered
# such that the first entry in the list is the top-left,
# the second entry is the top-right, the third is the
# bottom-right, and the fourth is the bottom-left
rect = np.zeros((4, 2), dtype = "float32")
ordered_points = np.zeros((4, 2), dtype = "float32")
# the top-left point will have the smallest sum, whereas
# the bottom-right point will have the largest sum
s = pts.sum(axis = 1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
sum_ = points.sum(axis = 1)
ordered_points[0] = points[np.argmin(sum_)]
ordered_points[2] = points[np.argmax(sum_)]
# now, compute the difference between the points, the
# top-right point will have the smallest difference,
# whereas the bottom-left will have the largest difference
diff = np.diff(pts, axis = 1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
diff = np.diff(points, axis = 1)
ordered_points[1] = points[np.argmin(diff)]
ordered_points[3] = points[np.argmax(diff)]
# return the ordered coordinates
return rect
return ordered_points
def run(self):
""" Main thread."""
# Connect to Tello drone and set default speed.
self.tello.connect()
self.tello.set_speed(self.speed)
......@@ -244,11 +275,11 @@ class FrontEnd(object):
self.screen.fill([0, 0, 0])
frame = frame_read.frame
frame = self.ResizeWithAspectRatio(frame, height=self.im_height)
frame = self.resize_with_aspect_ratio(frame, height=self.im_height)
try:
ret = self.reader.append_video_frame(frame)
except:
self.reader.append_video_frame(frame)
except Exception:
pass
self.calculate_warped()
......@@ -321,6 +352,7 @@ class FrontEnd(object):
def main():
""" Main class to create and start the frontend."""
frontend = FrontEnd()
# run frontend
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment