Compare commits

..

4 Commits

13 changed files with 48 additions and 50 deletions

2
.gitignore vendored
View File

@ -1,6 +1,6 @@
data data
*/models* */models*
venv .venv
*/out* */out*
python/__pycache__ python/__pycache__
cpp/bin cpp/bin

View File

@ -23,7 +23,7 @@ Implémentation de l'algorithme "Viola Jones" en Python et C++.
Vous pouvez configurer l'algorithme avec les variables globales définies au début du fichier *ViolaJones.cpp* puis lancer 'make start'. Vous pouvez configurer l'algorithme avec les variables globales définies au début du fichier *ViolaJones.cpp* puis lancer 'make start'.
Il y a également la commande 'make clean' qui permet de supprimer tout fichiers compilées. Il y a également la commande 'make clean' qui permet de supprimer tous fichiers compilés.
### Python ### Python
@ -34,7 +34,7 @@ Vous pouvez configurer l'algorithme dans le fichier *config.py* puis lancer l'al
## Entraînement ## Entraînement
L'algorithme à été entraîné avec un processeur Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz et un GPU NVIDIA GeForce RTX 2080 Ti. L'algorithme a été entraîné avec un processeur Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz et un GPU NVIDIA GeForce RTX 2080 Ti.
### Tableau de comparaison des temps d'exécution ### Tableau de comparaison des temps d'exécution
@ -202,7 +202,7 @@ L'algorithme de ViolaJones étant déterministe, les fichiers devraient être é
| ViolaJones T = 200 (NJIT) | 3,989,600 | 3ms 989µs 600ns | 15,957,700 | 15ms 957µs 700ns | | ViolaJones T = 200 (NJIT) | 3,989,600 | 3ms 989µs 600ns | 15,957,700 | 15ms 957µs 700ns |
| ViolaJones T = 300 (NJIT) | 5,983,900 | 5ms 983µs 900ns | 23,935,500 | 23ms 935µs 500ns | | ViolaJones T = 300 (NJIT) | 5,983,900 | 5ms 983µs 900ns | 23,935,500 | 23ms 935µs 500ns |
## Resources additionnels ## Ressources additionnelles
- [Rapid Object Detection using a Boosted Cascade of Simple Features](https://www.cs.cmu.edu/~efros/courses/LBMV07/Papers/viola-cvpr-01.pdf) - [Rapid Object Detection using a Boosted Cascade of Simple Features](https://www.cs.cmu.edu/~efros/courses/LBMV07/Papers/viola-cvpr-01.pdf)
- [Chapter 39. Parallel Prefix Sum (Scan) with CUDA](https://developer.nvidia.com/gpugems/gpugems3/part-vi-gpu-computing/chapter-39-parallel-prefix-sum-scan-cuda) - [Chapter 39. Parallel Prefix Sum (Scan) with CUDA](https://developer.nvidia.com/gpugems/gpugems3/part-vi-gpu-computing/chapter-39-parallel-prefix-sum-scan-cuda)

View File

@ -1,11 +1,11 @@
FROM nvidia/cuda:12.5.1-devel-ubi9 AS builder FROM nvidia/cuda:12.6.2-devel-ubi9 AS builder
WORKDIR /home/ViolaJones/cpp WORKDIR /home/ViolaJones/cpp
COPY *.cu *.cpp *.hpp Makefile ./ COPY *.cu *.cpp *.hpp Makefile ./
RUN make -j "$(nproc)" && make -j "$(nproc)" ./bin/ViolaJonesTest RUN make -j "$(nproc)" && make -j "$(nproc)" ./bin/ViolaJonesTest
FROM nvidia/cuda:12.5.1-base-ubi9 FROM nvidia/cuda:12.6.2-base-ubi9
WORKDIR /home/ViolaJones/cpp WORKDIR /home/ViolaJones/cpp

View File

@ -12,5 +12,4 @@ services:
reservations: reservations:
devices: devices:
- driver: nvidia - driver: nvidia
count: 1
capabilities: [gpu] capabilities: [gpu]

View File

@ -1,6 +1,6 @@
FROM alpine:3.20.1 FROM alpine:3.20.3
RUN apk add --no-cache curl=8.8.0-r0 python3=3.12.3-r1 && rm -rf /var/cache/apk* RUN apk add --no-cache curl=8.11.0-r1 python3=3.12.7-r0 && rm -rf /var/cache/apk*
WORKDIR /home/ViolaJones/downloader WORKDIR /home/ViolaJones/downloader
COPY requirements.txt activate.sh ./ COPY requirements.txt activate.sh ./

View File

@ -4,16 +4,14 @@
set -e set -e
test -z "$EXEC_DIR" && EXEC_DIR=. test -z "$EXEC_DIR" && EXEC_DIR=.
test -z "$VENV_PATH" && VENV_PATH="$EXEC_DIR/venv" test -z "$VENV_PATH" && VENV_PATH="$EXEC_DIR/.venv"
activate(){ activate(){
if [ ! -d "$VENV_PATH" ]; then if [ ! -d "$VENV_PATH" ]; then
echo 'Creating python virtual environnement' echo 'Creating python virtual environnement'
python -m venv "$VENV_PATH" python -m venv --upgrade-deps "$VENV_PATH"
echo 'Activating virtual environnement' echo 'Activating virtual environnement'
activate activate
echo 'Updating base pip packages'
python -m pip install -U setuptools pip
echo 'Installing requirements' echo 'Installing requirements'
pip install -r requirements.txt pip install -r requirements.txt
elif [ -f "$VENV_PATH"/Scripts/activate ]; then . "$VENV_PATH"/Scripts/activate elif [ -f "$VENV_PATH"/Scripts/activate ]; then . "$VENV_PATH"/Scripts/activate

View File

@ -3,29 +3,31 @@ from tqdm import tqdm
from functools import partial from functools import partial
from sys import argv from sys import argv
import numpy as np import numpy as np
from numpy.typing import NDArray
from typing import Final, Callable
from os import path, listdir from os import path, listdir
# Induce determinism # Induce determinism
np.random.seed(133742) np.random.seed(196_863)
# Makes the "leave" argument default to False # Makes the 'leave' argument default to False
tqdm = partial(tqdm, leave = False) tqdm: Callable = partial(tqdm, leave = False)
def read_pgm(pgm_file: BufferedReader) -> np.ndarray: def read_pgm(pgm_file: BufferedReader) -> NDArray[np.uint8]:
"""Read the data of a PGM file """Read the data of a PGM file
Args: Args:
pgm_file (BufferedReader): PGM File pgm_file (BufferedReader): PGM File
Returns: Returns:
np.ndarray: PGM data NDArray[np.uint8]: PGM data
""" """
assert (f := pgm_file.readline()) == b'P5\n', f"Incorrect file format: {f}" assert (f := pgm_file.readline()) == b'P5\n', f'Incorrect file format: {f}'
(width, height) = [int(i) for i in pgm_file.readline().split()] (width, height) = (int(i) for i in pgm_file.readline().split())
assert width > 0 and height > 0, f"Incorrect dimensions: {width}x{height}" assert width > 0 and height > 0, f'Incorrect dimensions: {width}x{height}'
assert (depth := int(pgm_file.readline())) < 256, f"Incorrect depth: {depth}" assert (depth := int(pgm_file.readline())) < 256, f'Incorrect depth: {depth}'
buff = np.empty(height * width, dtype = np.uint8) buff: Final[NDArray[np.uint8]] = np.empty(height * width, dtype = np.uint8)
for i in range(buff.shape[0]): for i in range(buff.shape[0]):
buff[i] = ord(pgm_file.read(1)) buff[i] = ord(pgm_file.read(1))
return buff.reshape((height, width)) return buff.reshape((height, width))
@ -36,25 +38,25 @@ def __main__(data_path: str) -> None:
Args: Args:
data_path (str): Path of the PGM files data_path (str): Path of the PGM files
""" """
for set_name in tqdm(["train", "test"], desc = "set name"): for set_name in tqdm(['train', 'test'], desc = 'set name'):
X, y = [], [] X, y = [], []
for y_i, label in enumerate(tqdm(["non-face", "face"], desc = "label")): for y_i, label in enumerate(tqdm(['non-face', 'face'], desc = 'label')):
for filename in tqdm(listdir(f"{data_path}/{set_name}/{label}"), desc = "Reading pgm file"): for filename in tqdm(listdir(f'{data_path}/{set_name}/{label}'), desc = 'Reading pgm file'):
with open(f"{data_path}/{set_name}/{label}/{filename}", "rb") as face: with open(f'{data_path}/{set_name}/{label}/{filename}', 'rb') as face:
X.append(read_pgm(face)) X.append(read_pgm(face))
y.append(y_i) y.append(y_i)
X, y = np.asarray(X), np.asarray(y) X, y = np.asarray(X), np.asarray(y)
idx = np.random.permutation(y.shape[0]) idx: NDArray[np.int64] = np.random.permutation(y.shape[0])
X, y = X[idx], y[idx] X, y = X[idx], y[idx]
for org, s in tqdm(zip("Xy", [X, y]), desc = f"Writing {set_name}"): for org, s in tqdm(zip('Xy', [X, y]), desc = f'Writing {set_name}'):
with open(f"{data_path}/{org}_{set_name}.bin", "w") as out: with open(f'{data_path}/{org}_{set_name}.bin', 'w') as out:
out.write(f'{str(s.shape)[1:-1].replace(",", "")}\n') out.write(f'{str(s.shape)[1:-1].replace(',', '')}\n')
raw = s.ravel() raw: NDArray = s.ravel()
for s_i in tqdm(raw[:-1], desc = f"Writing {org}"): for s_i in tqdm(raw[:-1], desc = f'Writing {org}'):
out.write(f"{s_i} ") out.write(f'{s_i} ')
out.write(str(raw[-1])) out.write(str(raw[-1]))
if __name__ == "__main__": if __name__ == '__main__':
__main__(argv[1]) if len(argv) == 2 else print(f"Usage: python {__file__[__file__.rfind(path.sep) + 1:]} ./data_location") __main__(argv[1]) if len(argv) == 2 else print(f'Usage: python {__file__[__file__.rfind(path.sep) + 1:]} ./data_location')

View File

@ -1,2 +1,2 @@
numpy==2.0.0 numpy==2.1.3
tqdm==4.66.4 tqdm==4.67.0

View File

@ -1,6 +1,6 @@
FROM nvidia/cuda:12.5.1-devel-ubi9 AS builder FROM nvidia/cuda:12.6.2-devel-ubi9
RUN dnf install -y python3.12-3.12.1-4.el9 \ RUN dnf install -y python3.12-3.12.1-4.el9_4.4 \
&& dnf clean all \ && dnf clean all \
&& ln -s /usr/bin/python3.12 /usr/bin/python && ln -s /usr/bin/python3.12 /usr/bin/python

View File

@ -57,7 +57,7 @@ clean:
.PHONY: mrproper .PHONY: mrproper
mrproper: clean mrproper: clean
@rm -rfv __pycache__ venv @rm -rfv __pycache__ .venv
.PHONY: help .PHONY: help
help: help:

View File

@ -4,16 +4,14 @@
set -e set -e
test -z "$EXEC_DIR" && EXEC_DIR=. test -z "$EXEC_DIR" && EXEC_DIR=.
test -z "$VENV_PATH" && VENV_PATH="$EXEC_DIR/venv" test -z "$VENV_PATH" && VENV_PATH="$EXEC_DIR/.venv"
activate(){ activate(){
if [ ! -d "$VENV_PATH" ]; then if [ ! -d "$VENV_PATH" ]; then
echo 'Creating python virtual environnement' echo 'Creating python virtual environnement'
python -m venv "$VENV_PATH" python -m venv --upgrade-deps "$VENV_PATH"
echo 'Activating virtual environnement' echo 'Activating virtual environnement'
activate activate
echo 'Updating base pip packages'
python -m pip install -U setuptools pip
echo 'Installing requirements' echo 'Installing requirements'
pip install -r requirements.txt pip install -r requirements.txt
elif [ -f "$VENV_PATH"/Scripts/activate ]; then . "$VENV_PATH"/Scripts/activate elif [ -f "$VENV_PATH"/Scripts/activate ]; then . "$VENV_PATH"/Scripts/activate

View File

@ -12,5 +12,4 @@ services:
reservations: reservations:
devices: devices:
- driver: nvidia - driver: nvidia
count: 1
capabilities: [gpu] capabilities: [gpu]

View File

@ -1,3 +1,5 @@
numba==0.60.0 numba==0.60.0
scikit-learn==1.5.1 scikit-learn==1.5.2
tqdm==4.66.4 tqdm==4.67.0
#pudb==2024.1.3