ballandhoop package
Application module
- class src.ballandhoop.application.Application(force_hostname: str | None = None, verbose_output: bool = False)
Bases:
objectThe main class to run the software. loads and saves config, loads resources with config parameters. This class is called out of runner.py and calibration.py with different methods.
- Parameters:
force_hostname (str, optional, default=None) – if unset socket.gethostname() will be used to search the for the config
verbose_output (bool, optional, default=False) – optional argument, if True there will be (more) output to the console, none if False
- Variables:
cfg – the config loaded and saved to config.yml (saved also to config.mat)
hostname – the local hostname by either socket.gethostname() or `force_hostname
network – either the server or client instance, using the
NetworkInterfacetimings – a fifo dict, which saved the in time of the frame, old entries are removed after the frame calc
latest_frame_number – remembers which is the newest frame with a result to discard older results
result_lock – manages the thread safe access to the
latest_frame_number
- ball_found_async_callback(result)
The method which is called after the thread-worker run and did not fail
- Parameters:
result (tuple) – the result of the thread worker, can only be one argument, the thread-worker is not able to send a second one
- ball_search_error_callback(e)
This is the callback method which is provided to the thread-worker. It is called if there is an error in one of the thread-workers. Without this method the thread-worker would fail silent. It still does, if verbose flag is not set
- Parameters:
e – The error
- debug(save_vid=None, wb_gains=None)
This method is here to generate fake video material, which can be used with the faker_path config
- Parameters:
save_vid –
wb_gains – if not given, then the gains will be freshly calculated
- get_cfg(*arg)
Helper method to get
- Parameters:
arg (str[]) – there can be unlimited amount of arguments
- load_config_from_disk(file_type: str = 'yml')
Loads the config file from the disk to the attribute
- Parameters:
file_type (str, optional, default='yml') – the file type of the config file, can either be ‘yml’ or ‘mat’
- Returns:
dictionary of the config content
- local_config()
Wrapper Method to get the config for this hostname. The hostname might be forged in the constructor. Do not call this method for getting the config, just for setting it. Use :method get_cfg instead
- Returns:
dictionary of the local config
- print(msg: str)
Prints the message to stdout, if app is running with verbose flag, discards otherwise
- Parameters:
msg – the message string
- run(ball_hsv: dict)
This method runs the main loop method for tracking and network init. Administers the thread-workers and gives them jobs. Each core gets one thread-worker. They will calculate the results of the frames after each other. The thread-workers are especially needed if the application is running under high per frame cpu, which can happen with high fps or high resolution settings.
- Parameters:
ball_hsv (dict) – if this parameter is set, the ball hsv in config is overwritten
- run_calibration(calc_wb_gains: bool, search_hoop: bool, hoop_hsv: dict, search_ball: bool, ball_hsv: dict)
Runs the calibration method.
- Parameters:
calc_wb_gains (bool) – If this flag is set the white calibration is called
search_hoop (bool) – If this flag is set the hoop border points are searched
hoop_hsv (dict) – a dictionary with keys lower and upper
search_ball (bool) –
ball_hsv (dict) –
- save_col_and_add_from_config(type_name: str, input_data: dict)
Saves the given parameters to config and reads config afterwards. If parameters are None, then only the config is read.
- Parameters:
type_name – a top level setting with a hsv child, like ball or hoop
input_data – the dictionary with the upper and lower color as dict keys, with value (H,S,V)
- save_config_to_disk() None
Saves the self.cfg back to config.yml and config.mat files.
Ball module
- class src.ballandhoop.ball.Ball(hoop: Hoop, center: tuple, radius: int)
Bases:
objectThis class is a data structure for the ball element
- Variables:
hoop – the hoop this ball belongs to
center – the tuple of coordinates from the center of the ball
radius – the radius of the ball
- angle()
Calculates the angle the ball has inside the hoop
- Returns:
the angle in float, calculated by his parent hoop
Hoop.angle_in_hoop()
Helper module
- src.ballandhoop.helper.get_bgr_picture(faker_path: str | None = None, wb_gains=None)
Gives a bgr picture from the camera or the image in the faker_path
- Parameters:
faker_path – a path from which the image will be loaded if given, defaults to None
wb_gains (tuple) – if not given, it will be auto-calculated, if a picture is taken
- Returns:
the image from file or from the camera
- Return type:
numpy.array
- src.ballandhoop.helper.get_hsv_picture(faker_path: str | None = None, wb_gains=None)
Same as
get_bgr_picture(), but transformed to HSV colorspace- Returns:
the picture as array in HSV color space
- Return type:
numpy.array
- src.ballandhoop.helper.reset_content_of_dir(dir_name: str)
Small helper method which empties all files and folders inside a given folder
- Parameters:
dir_name – the path to the folder
Hoop module
- class src.ballandhoop.hoop.Hoop(center: list, radius: int, center_dots: list, radius_dots: list, angle_offset=0, fov=(90, 270), **kwargs)
Bases:
objectClass which represents the data holding of the hoop This constructor is usually populated by the config file entries
- Parameters:
center – the center of the hoop
radius – the radius of the hoop
center_dots – a list of the center of the hoop markers for finding the hoop
radius_dots – a list of the radius’ of the hoop markers for finding the hoop
angle_offset – a custom offset of angle, which will be added to each result of
angle_in_hoop()fov – a 2-tuple of angles which will be used as starting and ending angles to cut off the picture mask outside this circle sector
kwargs – just a placeholder so if additional keys are given in config file, there will be no errors, because some config file attributes will be used in the methods
- angle_in_hoop(p: tuple)
Calculates the angle between a given point (e.g. the ball center) inside the hoop. The
angle_offsetis added to the angle.- Parameters:
p (tuple) – the point which angle should be calculated
- Returns:
The angle between (p -
self.center) and (0,self.radius)
- static angle_of_vectors(v1, v2)
Calculates the angle between two vectors :return: the angle between two vectors in degree :rtype: float
- static create_from_image(hsv, image: Image, morph_iterations=0, debug_output_path=None, min_dots_radius=2, **kwargs)
This method should be populated with the entries of the config file. It searches in range of the hsv colors for three or more hoop markers and builds a binary mask out of it. Depending on the morph_iterations amount the found mask will be eroded and dilated multiple times for noice reduction. If the radius of the markers is too small, it will not be used for the hoop calculation. The center of the remaining markers will be calculated and fitted to a circle. This circle radius and center are the center and radius of the returned hoop. If there are to less (remaining) markers, None will be returned instead.
- Parameters:
hsv – the colors to search for. has a upper and lower key which each hold a (H,S,V) color
image (
Image) – the Image to search the hoop markers inmorph_iterations – amount of times the mask will be eroded and dilated. The higher the value, the more noice is removed
debug_output_path – the directory path where the debug pictures will be saved
min_dots_radius – the minimal radius of the markers
kwargs – a catch-all parameter, so if too many arguments are given, python will not throw an error
- Returns:
The hoop if any was found
- Return type:
Hoop| None
- find_ball(frame, hsv, morph_iterations=1, min_radius=5, max_radius=20, dir_path=None, **kwargs)
Tries to find the ball in the given picture. Therefore, the image is filtered with the given HSV colors to a mask. This mask is morphed, depending on the given iterations. There will be a dilatation and an erode afterwards (closure), to close holes in the found ball mask which will be there because of the physical hoop. All found mask points which are outside the given hoop
Field of Vieware removed. It will then loop through the biggest connected areas in the mask (the biggest first). If their radius is inside min_radius and max_radius the found ball will be returned or none if none of the connected areas are fitting the limits.- Parameters:
frame – the array of the frame in HSV color space
hsv – a dictionary with upper and lower and (H,S,V) values, which the frame will be filtered to
morph_iterations – the amount of iterations to morph, defaults to 1
min_radius – the minimal radius a ball is allowed to have, defaults to 5
max_radius – the maximal radius a ball is allowed to have, defaults to 20
dir_path – the directory where debugging pictures will be saved, defaults to None
kwargs – just a catch-all for additional parameters from the config file, will be ignored
- Returns:
the found ball, if any
- Return type:
Ball | None
- find_ball_async(frame_number, frame, ball_config, dir_path=None)
A wrapper function for the async call from the
Applicationforfind_ball().- Parameters:
frame_number – the number of the frame, not used for calculation but important for the
application callbackframe – the frame array in hsv color space
ball_config – the ball config, see
find_ball()for more infodir_path – the directory where debugging pictures will be saved
- Returns:
A tuple of the given frame number and the found ball, if any
- Return type:
(int, Ball|None)
Image module
Warning
Do not use this class too much in mission critical calculations. It is not optimized to work fast. Its just a convinient wrapper, which transform every bgr to hsv and vice versa. This happens afer every image processing step. You have been warned.
- class src.ballandhoop.image.Image(image_bgr=None, image_hsv=None, image_bw=None)
Bases:
objectIf this class is created with a bgr oder hsv array, the other one will be automatically generated
- Parameters:
image_bgr – the bgr frame array
image_hsv – the hsv frame array
image_bw – a monochrome frame array
- apply_blurring(blur_radius=11) Image
Blurs the image
- Parameters:
blur_radius – the blur radius, defaults to 11
- Returns:
The new image instance
- Return type:
- apply_hoop_cutting(hoop: Hoop) Image
WIP - blacks out everything outside the hoop
- Parameters:
hoop –
- Returns:
The new image instance
- Return type:
- apply_undistort(demo=False) Image
Undistort the image with the lens calibration from the chessboard
- Parameters:
demo – flag if the image should be cutted or transformed with black border
- Returns:
The new image instance
- Return type:
- camera_matrix = None
The camera matrix, loaded from the chessboard calibration
- color_split(dir_path, hsv_lower_bound, hsv_upper_bound, return_hsv=False)
This method generates multiple pictures to separate different colored parts of the image. Rotates through the H value with fixed S and V values
- Parameters:
dir_path – the dir path, can have a tailored /, but does not need to
hsv_lower_bound – lower hsv value, H will be rotated
hsv_upper_bound – upper hsv value, H will be rotated
return_hsv – flag if a hsv color space should be saved, or rgb, defaults to False (rgb)
- static create(path: str | None = None, wb_gains=None) Image
Creates an Image instance, either from file or cam
- Parameters:
path – the path, if not given take pic from cam
wb_gains – the wb_gains the cam will use if needed
- Returns:
A new image instance
- Return type:
- dist_matrix = None
The dist matrix, loaded from the chessboard calibration
- plot_angle(ball: Ball) Image
Plots the angle to the image
- Parameters:
ball – the ball
- Returns:
The new image instance
- Return type:
- plot_ball(ball: Ball, color_outline: tuple = (0, 255, 0), color_center: tuple = (0, 255, 0)) Image
Plots the outline and the center of a ball in the image
- Parameters:
ball – The ball to plot
color_outline – the color of the outline, defaults to (0, 255, 0)
color_center – the color of the center, defaults to (0, 255, 0)
- Returns:
The new image instance
- Return type:
- plot_ball_history(pts, color=(0, 0, 255)) Image
Plots the ball history. The tail is getting less thick
- Parameters:
pts – the list of the points
color – the color
- Returns:
The new image instance
- Return type:
- plot_hoop(hoop: Hoop, color: tuple = (255, 0, 0), thickness=2, with_dots=False) Image
Plots a hoop as a circle in the image
- Parameters:
hoop (Hoop) – the hoop to plot
color – the color the circle will be plotted in, defaults to (255, 0, 0)
thickness – the thickness the circle will be plotted in, -1 for full fill, defaults to 2
with_dots (bool) – flag if the dots should be plotted as well
- Returns:
The new image instance
- Return type:
- plot_line(p1: tuple, p2: tuple, color: tuple = (255, 0, 0), thickness: int = 2) Image
Plots a line in the image
- Parameters:
p1 – the first point
p2 – the second point
color – the color, defaults to (255, 0, 0)
thickness – the thickness, defaults to 2
- Returns:
The new image instance
- Return type:
- plot_rectangle(x, y, w, h, color=(255, 0, 0), thickness=3) Image
Plots a rectangle in the image
- Parameters:
x – the x coordinate
y – the y coordinate
w – the width
h – the height
color – the color, defaults to (255, 0, 0)
thickness – the thickness, defaults to 3
- Returns:
- plot_text(text: str, pos: tuple, color: tuple = (255, 0, 0), fontScale=1) Image
Plots text to the image
- Parameters:
text – the text,
pos – the position
color – the color, defaults to (255, 0, 0)
fontScale – the fontscale, defaults to 1
- Returns:
The new image instance
- Return type:
- save(dir_path, filename='image')
Save the image to the given dir with the filename in rgb and hsv
- Parameters:
dir_path – the dir_path, if none, then nothing is saved
filename – the filename, will be suffixed with -hsv.png and -rgb.png
PiHSVArray module
- class src.ballandhoop.piHSVArray.PiHSVArray(*args: Any, **kwargs: Any)
Bases:
PiRGBArrayA wraper class which extends
picamera.array.PiRGBArrayand converts the pixels to HSV color- Parameters:
camera (picamera.PiCamera) – the camera object, see parent constructor
size – the size of the frame, see parent constructor
- Variables:
array – the frame data, inherited
- flush()
This method is called after the data is fully written. It converts to HSV. Note: the picamera has to use bgr, not rgb otherwise this will produce weird results
Videostream module
- class src.ballandhoop.videostream.VideoStream(resolution_no=1, framerate=60, rotation=0, as_hsv=True, wb_gains=None, faker_path=None, **kwargs)
Bases:
objectA wrapper for
picamera.PiCamera, so that config file input can be used- Parameters:
resolution_no – the resolution number which can be picked in sensor mode 7
framerate – the framerate, should be between 60 and 90 in sensor mode 7
rotation – the rotation
as_hsv – if output should be hsv or bgr
wb_gains – the white_balancing gains
faker_path – if this directory is set, the camera will not be used, but the pictures saved there. Can be recorded through debug.py
kwargs – catch-all parameter, so more entries in the config do not throw an error
- __iter__()
Returning the iterator e.g. in a for loop and starting the fps counter :return: self :meta public:
- __next__()
Automatically called to get the next frame e.g. in a for loop with this class as iterator Can rotate the image before returning. Updates the fps counter
- Returns:
frame array
- close()
Stops the FPS counter and closes the resources if needed
- faker_stream_generator(faker_path)
Takes the faker path from the config and delivers the png pictures there as the videostream. Good for debugging to get a reliable input
- resolutions = {0: (160, 128), 1: (320, 240), 2: (640, 480)}
The available resolutions in sensor mode 7.`
- rotations = {1: 0, 2: 1, 3: 2}
The available rotation numbers
WhiteBalancing module
- class src.ballandhoop.whiteBalancing.WhiteBalancing(dirPath='storage/awb/', delta=2, verboseOutput=False)
Bases:
objectThis class organizes the white balancing and manual calculation of the wb_gains. It takes a picture with arbitrary gains, takes (optional) a region of interest [210:430, 150:320] in the middle of the image (cropping it) and averaging all red, blue and green values. The goal is to change the red and blue gain that way, that all means are equal. Works best with a well illuminated and white only background.
- Parameters:
dirPath – the path where the debugging pictures are saved to, defaults to storage/awb
delta – the accepted difference delta between the mean color values r,g,b, defaults to 2
verboseOutput – flag if more output should be given, defaults to False
- calculate(cropping=False)
Does the calculation
- Parameters:
cropping – flag if roi [210:430, 150:320] should be cropped before the mean calculation
- Returns:
(r_gain,b_gain)
- Return type:
(float, float) each between 0 and 8