Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
53 changes: 53 additions & 0 deletions .github/workflows/tree-hyperopt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Test and lint

on:
push:
branches: tree_hyperopt
pull_request:
branches: [ tree_hyperopt, main ]

permissions:
contents: read

jobs:
flake8_py3:
runs-on: ubuntu-latest
steps:
- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: 3.10.6

- name: Checkout
uses: actions/checkout@v3

- name: Install flake8
run: pip install flake8

- name: Run flake8
uses: py-actions/flake8@v2
with:
path: DecisionTrees
max-line-length: "120"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

pytest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Python 3.10
uses: actions/setup-python@v3
with:
python-version: 3.10.6

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install -r DecisionTrees/requirements.txt

- name: Run pytest
run: |
pytest

2 changes: 2 additions & 0 deletions DecisionTrees/.flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
max-line-length=120
15 changes: 15 additions & 0 deletions DecisionTrees/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ADAS algorithms hyperparameters tuning with decision trees

__Цель работы__: Исследовать и разработать инструмент для полуавтоматического подбора гиперпараметров алгоритмов детектирования линий с учетом погодных условий (окружающей среды) на основе деревьев решений

На данный момент доступны методы оптимизации:
1. GeneticLearner
2. HyperOptLearner
3. REINFORCELearner

Чтобы запустить примеры из core/examples достаточно запустить:

```
pip install -r requirements.txt
python -m core.examples.genetic
```
Empty file added DecisionTrees/adas/__init__.py
Empty file.
6 changes: 6 additions & 0 deletions DecisionTrees/adas/lib/algorithms/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .canny import canny, stat_canny, const_canny
from .hough_lines import hough_lines
from .angle import angle_lines

__all__ = ["canny", "stat_canny", "const_canny",
"hough_lines", "angle_lines"]
58 changes: 58 additions & 0 deletions DecisionTrees/adas/lib/algorithms/angle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from typing import List
import numpy as np
import numpy.ma as ma
import cv2 as cv


def get_cluster(angle_v, angles: List[float]):
cluster = 0
for i, angle in enumerate(angles):
if angle_v > angle:
cluster = i + 1
else:
break
return cluster


def scale_img(arr):
mask = arr == 0
arr = ma.masked_array(arr, mask)
new_arr = ((arr - arr.min()) * (1/(arr.max() - arr.min()) * 255)).astype('uint8')
return np.array(new_arr)


def angle_lines(img,
horizon: float,
step: int,
min_size: int,
angles: List[float],
grad_thr: float):
img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
img = cv.GaussianBlur(img, (5, 5), 2)

start_height = int(horizon) + 1
segmented = np.zeros_like(img)

grad_x = (img[start_height + step:-step:, 2 * step::] - img[start_height + step:-step, :-2 * step:]) / (2 * step)
grad_y = (img[start_height + 2 * step::, step:-step:] - img[start_height:-2 * step:, step:-step:]) / (2 * step)

grad_thr_mask = np.sqrt(grad_x ** 2 + grad_y ** 2) > grad_thr
grad_angles = np.arctan2(grad_y, grad_x)

for j in range(grad_x.shape[0]):
for i in range(grad_x.shape[1]):
if not grad_thr_mask[j][i]:
continue
segmented[start_height + step + j][step + i] = get_cluster(grad_angles[j][i], angles)

segmented = scale_img(segmented)
contours, _ = cv.findContours(segmented, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
final_image = np.zeros_like(img)

for c in contours:
if len(c) < min_size:
continue
for i in range(1, len(c)):
point, point_prev = c[i][0], c[i - 1][0]
cv.line(final_image, point_prev, point, (255, 255, 255), 1)
return final_image
23 changes: 23 additions & 0 deletions DecisionTrees/adas/lib/algorithms/canny.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import cv2 as cv
import numpy as np


def canny(img, thr1, thr2, s=0.0, ks=3):
if ks % 2 == 0:
ks += 1
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
blurred = cv.GaussianBlur(gray, (ks, ks), s)
return cv.Canny(blurred, thr1, thr2)


def const_canny(img):
return canny(img, 100, 200)


def stat_canny(image, sigma=0.33):
img = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
img = cv.GaussianBlur(img, (3, 3), 0)
v = np.median(img)
lower = int(max(0, (1.0 - sigma) * v))
upper = int(min(255, (1.0 + sigma) * v))
return cv.Canny(img, lower, upper)
44 changes: 44 additions & 0 deletions DecisionTrees/adas/lib/algorithms/hough_lines.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import cv2 as cv
import numpy as np


def hough_lines(img,
k=5,
thr1=150,
thr2=200,
roi_width_upper=0.3,
roi_width_lower=.0,
min_line_length=40,
max_line_gap=5,
hough_thr1=2,
hough_thr2=np.pi / 180,
vote_thr=100):
if k // 2 == 0:
k += 1

img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
img = cv.GaussianBlur(img, (k, k), 0)
img = cv.Canny(img, thr1, thr2)

height = img.shape[0]
width = img.shape[1]
polygons = np.array([[
(roi_width_lower * width, height),
((1 - roi_width_lower) * width, height),
(int((0.5 + roi_width_upper / 2) * width), int(0.5 * height)),
(int((0.5 - roi_width_upper / 2) * width), int(0.5 * height))
]], dtype=np.int32)
mask = np.zeros_like(img)
cv.fillPoly(mask, polygons, 255)
img = cv.bitwise_and(img, mask)

lines = cv.HoughLinesP(img, hough_thr1, hough_thr2, vote_thr, np.array([]),
minLineLength=min_line_length, maxLineGap=max_line_gap)
line_image = np.zeros_like(img)
if lines is None:
return line_image
for line in lines:
x1, y1, x2, y2 = line[0]
cv.line(line_image, (x1, y1), (x2, y2), (255, 255, 255), 1)

return line_image
9 changes: 9 additions & 0 deletions DecisionTrees/adas/lib/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .bdd import BDD10kEdges
from .biped import BIPED
from .cityscapes import CityScapesEdges, CityScapesRain
from .kitti import KittiEdges
from .utils import apply_roi

__all__ = ["BDD10kEdges", "BIPED", "CityScapesEdges",
"CityScapesRain", "KittiEdges",
"apply_roi"]
51 changes: 51 additions & 0 deletions DecisionTrees/adas/lib/data/bdd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import typing as tp
from os import path
from pathlib import Path

import cv2 as cv
import numpy as np
from torch.utils.data import Dataset
from tqdm import tqdm

from .utils import get_filenames, segmentation_to_edge


class BDD10kEdges(Dataset):
def __init__(self, root: str, holdout: str, pic_size: tp.Tuple[int, int] = (720, 1280)) -> None:
super().__init__()
self.root = root
self.holdout = holdout
self.pic_size = pic_size

self.img_path = path.join(root, "images", "10k", holdout)
self.img_names = []
for img_path in get_filenames(self.img_path):
self.img_names.append(path.split(img_path)[1].removesuffix(".jpg"))
self.img_names = sorted(self.img_names)

self.edge_path = path.join(root, "labels", f"edges_{pic_size[1]}_{pic_size[0]}", holdout)
if not path.isdir(self.edge_path):
self._prepare_edges()

def _prepare_edges(self):
Path(self.edge_path).mkdir(parents=True, exist_ok=True)
print(f"Couldn't find edges for BDD10k/{self.holdout}")
segmentation_path = path.join(self.root, "labels", "sem_seg", "colormaps", self.holdout)
for img_name in tqdm(self.img_names, desc="Building edges"):
seg_path = path.join(segmentation_path, img_name + ".png")
edge_path = path.join(self.edge_path, img_name + ".png")

segmentation = cv.imread(seg_path, cv.IMREAD_COLOR)
segmentation, _, _ = cv.split(segmentation)
edges = segmentation_to_edge(segmentation)

cv.imwrite(edge_path, edges)

def __getitem__(self, index) -> tp.Tuple[np.ndarray, np.ndarray]:
img_name = self.img_names[index]
img = cv.imread(path.join(self.img_path, img_name + ".jpg"), cv.IMREAD_COLOR)
edges = cv.imread(path.join(self.edge_path, img_name + ".png"), cv.IMREAD_GRAYSCALE)
return img, edges

def __len__(self) -> int:
return len(self.img_names)
31 changes: 31 additions & 0 deletions DecisionTrees/adas/lib/data/biped.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import typing as tp

import cv2 as cv
import numpy as np
from torch.utils.data import Dataset

from .utils import get_filenames


class BIPED(Dataset):
def __init__(self, path: str, holdout: str) -> None:
super().__init__()
self.path = path
self.data = self._load_holdout(holdout)

def _load_holdout(self, holdout) -> tp.List[tp.Tuple[np.ndarray, np.ndarray]]:
main_dir = f"{self.path}/BIPED/edges"
imgs_dir = f"{main_dir}/imgs/{holdout}/rgbr"
edges_dir = f"{main_dir}/edge_maps/{holdout}/rgbr"
if holdout == "train":
imgs_dir += "/real"
edges_dir += "/real"
imgs = [cv.imread(img, cv.IMREAD_COLOR) for img in sorted(get_filenames(imgs_dir))]
edges = [cv.imread(edge, cv.IMREAD_GRAYSCALE) for edge in sorted(get_filenames(edges_dir))]
return list(zip(imgs, edges))

def __getitem__(self, index) -> tp.Tuple[np.ndarray, np.ndarray]:
return self.data[index]

def __len__(self) -> int:
return len(self.data)
Loading