Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created FakeDetector and FakeGroundTruthDatareader, need to revise datareaders structure and layout(groundtruth) file format #5

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
62 changes: 62 additions & 0 deletions samples/cli_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import sys
import os

project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.append(project_root)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это к вопросу об использовании init.py, который мы обсуждали после собрания. По смыслу в директории utils должен быть такой файлик, тогда можно писать стандартные импорты. Ниже примеры. Надо попробовать это реализовать.

import utils.data_reader
from utils import data_reader


from src.gui_application.visualizer import Visualize
from src.utils.data_reader import GroundtruthReader, FakeGroundtruthReader
from src.utils.frame_data_reader import FrameDataReader
from src.vehicle_detector.detector import Detector
import datetime
import argparse
import os
from PIL import Image

import cv2 as cv
import numpy as np

def cli_argument_parser():
parser = argparse.ArgumentParser()

parser.add_argument('-t', '--mode',
help='Mode (\'image\', \'video\')',
type=str,
dest='mode',
choices=['image', 'video'],
required=True)
parser.add_argument('-v', '--video',
help='Path to a video file',
type=str,
dest='video_path')
parser.add_argument('-i', '--image',
help='Path to images',
type=str,
dest='images_path')
parser.add_argument('-g', '--groundtruth',
help='Path to a file of groundtruth',
type=str,
dest='groundtruth_path',
required=False)
parser.add_argument('-m', '--model',
help='Path to a model',
type=str,
dest='model_path',
required=True,
default=None)


args = parser.parse_args()
return args

#некоторое подобие main
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Удалить такой комментарий :)

def main():
args = cli_argument_parser()
reader = FrameDataReader.create( args.mode, (args.video_path or args.images_path) )
adapter = None
detector = Detector.create( "fake" )
visualizer = Visualize( reader, detector, FakeGroundtruthReader().read(args.groundtruth_path) )
visualizer.show()

if __name__ == '__main__':
main()
46 changes: 8 additions & 38 deletions src/gui_application/visualizer.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,13 @@
import cv2 as cv
from ..utils.data_reader import DataReader, GroundtruthReader, FakeGTReader
from ..utils.frame_data_reader import FrameDataReader
from ..utils.data_reader import GroundtruthReader, FakeGroundtruthReader
from ..vehicle_detector.fake_detector import FakeDetector
import random
# class PseudoDetector:
# def __init__(self, annotation_file):
# self.frame_annotations = self.__rd_form_ret_annotations(annotation_file)
# def __rd_form_ret_annotations(self, annotation_file):
# rand_bias = self.__get_random_bias()
# frame_annotations = {}
# with open(annotation_file, 'r') as file:
# annotations = file.readlines()

# for line in annotations:
# parts = line.strip().split()
# frame_idx = int(parts[0])
# label = parts[1]
# x1, y1 = int(parts[2]) + rand_bias, int(parts[3]) - rand_bias
# x2, y2 = int(parts[4]) - rand_bias, int(parts[5]) + rand_bias

# if frame_idx not in frame_annotations:
# frame_annotations[frame_idx] = []
# frame_annotations[frame_idx].append((label, x1, y1, x2, y2))
# return frame_annotations

# def __get_random_bias(self):
# random.seed()
# return random.randint(10, 15)



# def get_annotations(self):
# return self.frame_annotations

class Visualize:
def __init__(self, datareader:DataReader, detector:FakeDetector, gt_path:str):
def __init__(self, datareader:FrameDataReader, detector:FakeDetector, gt_data:list):
self.datareader = datareader
self.detector = detector
self.gt_data = FakeGTReader().read()
self.gt_layout = gt_data
def show(self):
try:
frame_idx = 0
Expand All @@ -47,8 +18,8 @@ def show(self):
for box in self.detector.detect(image):
self.__draw_box(image, box, (255, 0, 0))

if self.gt_data:
for box in self.__format_groundtruth(frame_idx):
if self.gt_layout:
for box in self.__get_groundtruth_bboxes(frame_idx):
self.__draw_box(image, box, (0, 255, 0))

frame_idx+=1
Expand All @@ -65,8 +36,7 @@ def __draw_box(self, image, box, color):
cv.putText(image, label, (x1, y1 - 10), cv.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
cv.imshow("Image", image)

def __format_groundtruth(self, frame_idx):

return [item[1:] for item in self.gt_data if item[0] == frame_idx]
def __get_groundtruth_bboxes(self, frame_idx):
return [item[1:] for item in self.gt_layout if item[0] == frame_idx]


208 changes: 65 additions & 143 deletions src/utils/data_reader.py
Original file line number Diff line number Diff line change
@@ -1,146 +1,5 @@
import csv
import cv2 as cv
import os
from abc import ABC, abstractmethod
import random
class DataReader(ABC):
@abstractmethod
def __iter__(self):
pass

@abstractmethod
def __next__(self):
pass

@staticmethod
def create(mode, dir_path):
if mode == "video":
return VideoDataReader(dir_path)
elif mode == "image":
return ImgDataReader(dir_path)
elif mode == "groundtruth":
return GroundtruthReader(dir_path)
else:
raise ValueError(f"Unsupported mode: {mode}")

class VideoDataReader(DataReader):

def __init__(self, video_path):
self.video_path = video_path
self.cap = cv.VideoCapture(video_path)
if not self.cap.isOpened():
raise ValueError(f"Cannot open video file: {video_path}")


def __iter__(self):
return self

def __next__(self):
if self.cap.isOpened():
ret, frame = self.cap.read()
if ret:
return frame
else:
self.cap.release()
raise StopIteration
else:
raise StopIteration

class ImgDataReader(DataReader):
def __init__(self, dir_path):
self.index = 0
self.directory_path = dir_path
if not os.path.exists(dir_path):
raise ValueError(f"Directory does not exist: {dir_path}")
self.image_files = [
os.path.join(dir_path, f) for f in os.listdir(dir_path)
if f.lower().endswith((".png", ".jpg", ".jpeg", ".bmp", ".tiff"))
]

def __iter__(self):
return self

def __next__(self):
if self.index < len(self.image_files):
img_path = self.image_files[self.index]
self.index += 1
img = cv.imread(img_path)
if img is None:
raise ValueError(f"Cannot read image file: {img_path}")
return img
else:
raise StopIteration

class FakeGTReader():
def __init__(
self,
total_frames: int = 1000,
prob_missing: float = 0.5,
image_width: int = 1920,
image_height: int = 1080,
max_objects_per_frame: int = 5,
seed: int = None
):
self.total_frames = total_frames
self.prob_missing = prob_missing
self.image_width = image_width
self.image_height = image_height
self.max_objects_per_frame = max_objects_per_frame
self.labels = ['car', 'truck', 'bus']

if seed is not None:
random.seed(seed)

def __generate_bbox(self):
"""Генерация случайного bounding box."""
x = random.randint(0, self.image_width - 1)
y = random.randint(0, self.image_height - 1)
w = random.randint(1, self.image_width - x)
h = random.randint(1, self.image_height - y)
return (x, y, h, w)

def read(self, file_path:str = None):
parsed_data = list()
if (file_path):
try:
with open(file_path, 'r') as file:
annotations = file.readlines()

for line in annotations:

parts = line.strip().split()

frame_idx = int(parts[0])
label = parts[1]
x1, y1 = int(parts[2]), int(parts[3])
x2, y2 = int(parts[4]), int(parts[5])


row_data = (frame_idx, label, x1, y1, x2, y2)
parsed_data.append(row_data)
return parsed_data
except FileNotFoundError:
print(f"File {file_path} was not found.")
except Exception as e:
print(f"Error when reading the file {file_path}: {e}")


else:
for frame in range(self.total_frames):

if random.random() < self.prob_missing:
continue


num_objects = random.randint(0, self.max_objects_per_frame)
for _ in range(num_objects):
label = random.choice(self.labels)
x, y, h, w = self.__generate_bbox()
parsed_data.append((frame, label, x, y, h, w))

return parsed_data


class GroundtruthReader():
@staticmethod
def read(file_path):
Expand All @@ -160,8 +19,8 @@ def read(file_path):
continue

frame_id, class_name, x1, y1, x2, y2 = row
row_data = (int(frame_id), str(class_name), float(x1), float(y1),
float(x2), float(y2))
row_data = (int(frame_id), str(class_name), int(x1), int(y1),
int(x2), int(y2))
parsed_data.append(row_data)

except FileNotFoundError:
Expand All @@ -171,6 +30,69 @@ def read(file_path):

return parsed_data

class FakeGroundtruthReader(GroundtruthReader):
def __init__(self,
max_frames = 1000,
obj_classes = None,
img_size = (1920, 1080),
seed = None):
"""
Initializing the synthetic data generator

:param max_frames: The maximum number of frames to generate
:param obj_classes: List of object classes
:param img_size: Image size (width, height)
:param seed: Seed for reproducibility
"""
super().__init__()
self.max_frames = max_frames
self.obj_classes = obj_classes or ['car', 'truck', 'bus']
self.img_width, self.img_height = img_size
self.seed = seed

if seed is not None:
random.seed(seed)

def read(self, file_path = None):
"""
Parsing CSV file with groundtruths.

:param file_path: The path to the file with groundtruths.
:return: list[tuples] of parsed data by rows.
"""
data = []

num_frames = random.randint(self.max_frames // 2, self.max_frames)

for frame_id in range(num_frames):
if random.random() < 0.2:
continue

num_objects = random.randint(1, 5)

for _ in range(num_objects):
x1, y1, w, h = self.__generate_bbox()
x2 = x1 + w
y2 = y1 + h

data.append((
frame_id,
random.choice(self.obj_classes),
round(x1, 2),
round(y1, 2),
round(x2, 2),
round(y2, 2)
))

return data

def __generate_bbox(self):
"""Генерация случайного bounding box."""
x = int(random.uniform(0, self.img_width - 50))
y = int(random.uniform(0, self.img_height - 50))
w = int(random.uniform(50, self.img_width - x))
h = int(random.uniform(50, self.img_height - y))
return (x, y, h, w)

class DetectionReader:
@staticmethod
Expand Down
Loading