Skip to content

Commit

Permalink
Add docstring comments and move models to dedicated folder
Browse files Browse the repository at this point in the history
  • Loading branch information
tannyle289 committed Aug 28, 2024
1 parent 0f19cf1 commit 64f923a
Show file tree
Hide file tree
Showing 14 changed files with 176 additions and 44 deletions.
18 changes: 16 additions & 2 deletions exports/base_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,15 @@


class BaseExport(IBaseExport):
"""
Base Export class that implements functions for
initializing and saving frame under specific format.
"""

def __init__(self, proj_dir_name):
"""
Constructor.
"""
self._var = VariableClass()
_cur_dir = pdirname(pabspath(__file__))
self.proj_dir = pjoin(_cur_dir, f'../data/{proj_dir_name}')
Expand All @@ -19,10 +27,10 @@ def __init__(self, proj_dir_name):

def initialize_save_dir(self):
"""
See ibase_project.py
See ibase_export.py
Returns:
None
success True or False
"""
self.result_dir_path = pjoin(self.proj_dir, f'{self._var.DATASET_FORMAT}-v{self._var.DATASET_VERSION}')
os.makedirs(self.result_dir_path, exist_ok=True)
Expand All @@ -35,6 +43,12 @@ def initialize_save_dir(self):
return False

def save_frame(self, frame, predicted_frames, cv2, labels_and_boxes):
"""
See ibase_export.py
Returns:
Predicted frame counter.
"""
print(f'5.1. Condition met, processing valid frame: {predicted_frames}')
# Save original frame
unix_time = int(time.time())
Expand Down
1 change: 1 addition & 0 deletions exports/export_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class ExportFactory:
"""
Export Factory initializes specific export types.
"""

def __init__(self):
self._var = VariableClass()
self.save_format = self._var.DATASET_FORMAT
Expand Down
16 changes: 16 additions & 0 deletions exports/ibase_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,27 @@


class IBaseExport(ABC):
"""
Interface for Base Export.
"""

@abstractmethod
def initialize_save_dir(self):
"""
Initializes save directory for Base export format
"""
pass

@abstractmethod
def save_frame(self, frame, predicted_frames, cv2, labels_and_boxes):
"""
Saves a single frames as well as it predicted annotation.
It should save 2 separate files under the same name, 1 .png for the raw frame and 1 .txt for the annotations.
Args:
frame: The current frame to be saved.
predicted_frames: Frames with predictions that might need to be saved alongside the original.
cv2: The OpenCV module used for image processing, passed in to avoid tight coupling.
labels_and_boxes: A list containing labels and their corresponding bounding boxes for the frame.
"""
pass
22 changes: 21 additions & 1 deletion exports/iyolov8_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,35 @@


class IYolov8Export(ABC):

"""
Interface for Yolov8 Export.
"""
@abstractmethod
def initialize_save_dir(self):
"""
Initializes save directory for Yolov8 export format
"""
pass

@abstractmethod
def save_frame(self, frame, predicted_frames, cv2, labels_and_boxes):
"""
Saves a single frames as well as it predicted annotation.
It should save 2 separate files under the same name,
- 1 .png for the raw frame and is saved in images subdirectory.
- 1 .txt for the annotations and is saved in labels subdirectory.
Args:
frame: The current frame to be saved.
predicted_frames: Frames with predictions that might need to be saved alongside the original.
cv2: The OpenCV module used for image processing, passed in to avoid tight coupling.
labels_and_boxes: A list containing labels and their corresponding bounding boxes for the frame.
"""
pass

@abstractmethod
def create_yaml(self, model2):
"""
Create .yaml file to map annotation labels with their corresponding names.
"""
pass
15 changes: 13 additions & 2 deletions exports/yolov8_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@


class Yolov8Export(IYolov8Export):
"""
Yolov8 Export class that implements functions for
initializing, saving frame and creating yaml file under specific format.
"""

def __init__(self, proj_dir_name):
"""
Constructor.
Expand All @@ -25,10 +30,10 @@ def __init__(self, proj_dir_name):

def initialize_save_dir(self):
"""
See ibase_project.py
See iyolov8_export.py
Returns:
None
Success true or false.
"""
self.result_dir_path = pjoin(self.proj_dir, f'{self._var.DATASET_FORMAT}-v{self._var.DATASET_VERSION}')
os.makedirs(self.result_dir_path, exist_ok=True)
Expand All @@ -51,6 +56,12 @@ def initialize_save_dir(self):
return False

def save_frame(self, frame, predicted_frames, cv2, labels_and_boxes):
"""
See iyolov8_export.py
Returns:
Predicted frame counter.
"""
print(f'5.1. Condition met, processing valid frame: {predicted_frames}')
# Save original frame
unix_time = int(time.time())
Expand Down
3 changes: 3 additions & 0 deletions integrations/integration_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@


class IntegrationFactory:
"""
Integration Factory initializes specific integration types.
"""
def __init__(self):
self._var = VariableClass()
self.name = self._var.INTEGRATION_NAME
Expand Down
13 changes: 13 additions & 0 deletions integrations/iroboflow_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,24 @@


class IRoboflowIntegration(ABC):
"""
Interface for Roboflow Integration class.
"""

@abstractmethod
def upload_dataset(self, src_project_path):
"""
Upload dataset to Roboflow platform.
Args:
src_project_path: Project save path
"""
pass

@abstractmethod
def __connect__(self):
"""
Connect to Roboflow agent.
You need to provide Roboflow parameters in .env file.
"""
pass
30 changes: 30 additions & 0 deletions integrations/is3_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,49 @@


class IS3Integration(ABC):
"""
Interface for S3 Integration class.
"""

@abstractmethod
def upload_file(self, source_path, output_path):
"""
Upload a single file to S3 compatible platform.
Args:
source_path: File save path
output_path: Desired path we want to save in S3
"""
pass

@abstractmethod
def upload_dataset(self, src_project_path):
"""
Upload dataset to S3 compatible platform.
Args:
src_project_path: Projecet save path
"""
pass

@abstractmethod
def __connect__(self):
"""
Connect to S3 compatible agent.
You need to provide S3 parameters in .env file.
"""
pass

@abstractmethod
def __check_bucket_exists__(self, bucket_name):
"""
Check if input bucket exists after connecting to S3 compatible agent.
You need to provide S3 parameters in .env file.
Args:
bucket_name: Bucket name.
Returns:
True or False
"""
pass
33 changes: 26 additions & 7 deletions integrations/roboflow_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,27 @@


class RoboflowIntegration:
"""
Roboflow Integration class that implements functions for connecting, uploading dataset
to Roboflow platform.
"""

def __init__(self):
"""
Constructor.
"""
self._var = VariableClass()
self.agent, self.ws, self.project = self.__connect__()

def __connect__(self):
"""
See iroboflow_integration.py
Returns:
agent: Connected agent.
workspace: Selected workspace in that agent.
project: Selected project in that workspace.
"""
try:
# Attempt to initialize Roboflow with the API key
agent = roboflow.Roboflow(api_key=self._var.ROBOFLOW_API_KEY)
Expand All @@ -29,15 +45,18 @@ def __connect__(self):
raise ConnectionRefusedError(f'Error during Roboflow login: {e}')

def upload_dataset(self, src_project_path):
"""
See iroboflow_integration.py
"""
# Upload data set to an existing project
self.ws.upload_dataset(
src_project_path,
pbasename(self.project.id),
num_workers=10,
project_license="MIT",
project_type="object-detection",
batch_name=None,
num_retries=0
src_project_path,
pbasename(self.project.id),
num_workers=10,
project_license="MIT",
project_type="object-detection",
batch_name=None,
num_retries=0
)
print('Uploaded')

Expand Down
40 changes: 26 additions & 14 deletions integrations/s3_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,33 @@


class S3Integration:
"""
S3 Integration class that implements functions for connecting, uploading single file and dataset
to S3 compatible platform.
"""

def __init__(self):
"""
Constructor.
"""
self._var = VariableClass()
self.session, self.agent = self.__connect__()
self.bucket = self._var.S3_BUCKET
self.__check_bucket_exists__(self.bucket)

def __connect__(self):
"""
See is3_integration.py
Returns:
session: Connected session.
agent: Connected agent.
"""
session = boto3.session.Session()
# Connect to Wasabi S3
# Connect to S3 Compatible
agent = session.client(
self._var.INTEGRATION_NAME,
endpoint_url=self._var.S3_ENDPOINT, # Wasabi endpoint URL
endpoint_url=self._var.S3_ENDPOINT,
aws_access_key_id=self._var.S3_ACCESS_KEY,
aws_secret_access_key=self._var.S3_SECRET_KEY,
)
Expand All @@ -25,25 +40,19 @@ def __connect__(self):
return session, agent

def upload_file(self, source_path, output_path):
"""
See is3_integration.py
"""
try:
self.agent.upload_file(source_path, self.bucket, output_path)
print(f"Successfully uploaded '{source_path}' to 's3://{self.bucket}/{output_path}'")
except Exception as e:
print(f"Failed to upload '{source_path}' to 's3://{self.bucket}/{output_path}': {e}")

# def upload_dataset(self, src_project_path):
# # Iterate over all the files in the folder
# for root, dirs, files in os.walk(src_project_path):
# for filename in files:
# # Construct the full file path
# source_path = os.path.join(root, filename)
#
# output_path = f'{self._var.DATASET_FORMAT}-v{self._var.DATASET_VERSION}/{filename}'
# # Upload the file
# self.upload_file(source_path, output_path)
# print(f'Uploaded: {source_path} to s3://{self.bucket}/{output_path}')

def upload_dataset(self, src_project_path):
"""
See is3_integration.py
"""
# Iterate over all the files in the folder, including sub folders
for root, dirs, files in os.walk(src_project_path):
for filename in files:
Expand All @@ -62,6 +71,9 @@ def upload_dataset(self, src_project_path):
print(f'Uploaded: {source_path} to s3://{self.bucket}/{output_path}')

def __check_bucket_exists__(self, bucket_name):
"""
See is3_integration.py
"""
try:
self.agent.head_bucket(Bucket=bucket_name)
print(f"Bucket '{bucket_name}' found.")
Expand Down
File renamed without changes.
File renamed without changes.
16 changes: 0 additions & 16 deletions projects/base_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,3 @@ def create_proj_save_dir(self, dir_name):
self.proj_dir = pjoin(_cur_dir, f'../data/{dir_name}')
self.proj_dir = pabspath(self.proj_dir) # normalise the link
print(f'1. Created/Found project folder under {self.proj_dir} path')

# def create_result_save_dir(self):
# """
# See ibase_project.py
#
# Returns:
# None
# """
# if self._var.DATASET_FORMAT == 'yolov8':
# result_dir_path = pjoin(self.proj_dir, f'{datetime.now().strftime("%d-%m-%Y_%H-%M-%S")}')
# image_dir_path = pjoin(result_dir_path, 'images')
# label_dir_path = pjoin(result_dir_path, 'labels')
# yaml_path = pjoin(result_dir_path, 'data.yaml')
# return result_dir_path, image_dir_path, label_dir_path, yaml_path
# else:
# raise TypeError('Unsupported dataset format!')
Loading

0 comments on commit 64f923a

Please sign in to comment.