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 6 commits
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
Empty file removed src/gui_application/main.py
Empty file.
72 changes: 72 additions & 0 deletions src/gui_application/visualizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import cv2 as cv
from ..utils.data_reader import DataReader, GroundtruthReader, FakeGTReader
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):
self.datareader = datareader
self.detector = detector
self.gt_data = FakeGTReader().read()
Copy link
Contributor

Choose a reason for hiding this comment

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

присваивание

def show(self):
try:
frame_idx = 0
for image in self.datareader:
if image is None:
break

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):
self.__draw_box(image, box, (0, 255, 0))

frame_idx+=1
if cv.waitKey(25) & 0xFF == ord('q'):
break
except Exception as e:
print(f"An error occurred: {e}")
finally:
cv.destroyAllWindows()

def __draw_box(self, image, box, color):
label, x1, y1, x2, y2 = box
cv.rectangle(image, (x1, y1), (x2, y2), color, 2)
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]


142 changes: 141 additions & 1 deletion src/utils/data_reader.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,147 @@
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

class GroundtruthReader:
@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)
Copy link
Contributor

Choose a reason for hiding this comment

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

Удалить

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():
Copy link
Contributor

Choose a reason for hiding this comment

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

Реализовать наследника от GroundtruthReader (из utils).

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 Down
47 changes: 47 additions & 0 deletions src/vehicle_detector/detector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import cv2 as cv
import random
from abc import ABC, abstractmethod
class Detector(ABC):
@abstractmethod
def detect(image):
pass
@staticmethod
def create(mode):
if mode == "vehicle":
return VehicleDetector()
elif mode == "fake":
return FakeDetector(42)
else:
raise ValueError(f"Unsupported mode: {mode}")

class VehicleDetector(Detector):
def __init__(self):
pass
def detect(image):
pass
class FakeDetector(Detector):
def __init__(self, seed = None):
if seed is not None:
random.seed(seed)

@staticmethod
def detect(image):
if image is None or image.size == 0:
return []
height, width = image.shape[:2]
bboxes = []
num_boxes = random.randint(0, 7)

for _ in range(num_boxes):
if width < 2 or height < 2:
continue
cl = random.choice(["car", "bus", "truck"])
x1 = random.randint(0, width - 2)
x2 = random.randint(x1 + 1, width - 1)

y1 = random.randint(0, height - 2)
y2 = random.randint(y1 + 1, height - 1)

bboxes.append((cl, x1, y1, x2, y2))

return bboxes
60 changes: 60 additions & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import sys
import os

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

from src.gui_application.visualizer import Visualize
from src.utils.data_reader import DataReader, GroundtruthReader
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',
Copy link
Contributor

Choose a reason for hiding this comment

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

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
def main():
args = cli_argument_parser()
reader = DataReader.create( args.mode, (args.video_path or args.images_path) )
adapter = None
detector = Detector.create( "fake" )
visualizer = Visualize( reader, detector, args.groundtruth_path )
Copy link
Contributor

Choose a reason for hiding this comment

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

visualizer = Visualize( reader, detector, GroundtruthReader.read(args.groundtruth_path) )

visualizer.show()

if __name__ == '__main__':
main()