18 changed files with 94 additions and 1 deletions
+4
View File
@@ -0,0 +1,4 @@
venv/
__pycache__/
*.pyc
.pytest_cache/
+31
View File
@@ -130,6 +130,37 @@ L'identifiant `id` suit la nomenclature standardisée de l'Union Astronomique In
] ]
``` ```
## Arborescence du projet
```
data/
pictures_test/ # images de test, Pipeline B
messier_classifier/ # dataset C0/C1/C2
manifest.csv # colonnes : nom;label (label = "messier" ou "ngc")
dataset_hipparcos.csv
dataset_constellations.json
pipeline_a/
skymap_generator.py
pipeline_b/
star_detector.py
pipeline_c/
c0_dataset_acquisition.py
c1_model_training.py
c2_operational_model.py
tests/
tests_pipeline_a.py
tests_pipeline_b.py
tests_pipeline_c0.py
tests_pipeline_c1.py
tests_pipeline_c2.py
app.py
CONTRIBUTING.md
ARCHITECTURE.md
README.md
```
Chaque pipeline (A/B/C) vit dans son propre dossier, reflétant l'indépendance actée en phase de Découpage. Le pipeline C conserve la séparation C0/C1/C2 jusque dans les fichiers de test, ces trois sous-étapes ayant des natures très différentes (scraping, entraînement, inférence). Pas de fichier `utils.py` créé par anticipation : le code partagé entre pipelines, s'il s'avère nécessaire, sera extrait au moment où un besoin concret de duplication apparaîtra, plutôt que par anticipation.
## Décisions techniques actées ## Décisions techniques actées
- Catalogue source : Hipparcos, pré-traité offline via `astropy` en CSV propre (RA, Dec, magnitude, nom) plutôt que parsé à la volée dans l'application - Catalogue source : Hipparcos, pré-traité offline via `astropy` en CSV propre (RA, Dec, magnitude, nom) plutôt que parsé à la volée dans l'application
View File
View File
View File
View File
View File
View File
+29
View File
@@ -0,0 +1,29 @@
import numpy as np # Je le laisse pour plus tard
import cv2
import os
def reading_picture(path):
if not os.path.exists(path):
raise FileNotFoundError(f"{path} n'existe pas.")
pic = cv2.imread(path, cv2.IMREAD_GRAYSCALE)
if pic is None:
raise ValueError(f"{path} est corrompu ou n'est pas une image valide.")
return pic
def blob_detector(picture):
params = cv2.SimpleBlobDetector_Params()
params.minThreshold = 10
params.maxThreshold = 200
params.filterByArea = True
params.minArea = 4
params.filterByCircularity = True
params.minCircularity = 0.1
params.filterByConvexity = True
params.minConvexity = 0.87
params.filterByInertia = True
params.minInertiaRatio = 0.01
# TODO: valeurs provisoires, à recalibrer avec de vraies images de test cette semaine.
detector = cv2.SimpleBlobDetector.create(params)
stars = detector.detect(picture)
result = [star.pt for star in stars]
return result
View File
View File
BIN
View File
Binary file not shown.
View File
+29
View File
@@ -0,0 +1,29 @@
import pytest
import cv2
import numpy as np
from pipeline_b import star_detector
def test_file_exists_and_is_an_image(tmp_path):
file = tmp_path / "image.jpg"
tableau_image = np.random.randint(0, 256, (64, 64), dtype=np.uint8)
cv2.imwrite(str(file), tableau_image)
assert isinstance(star_detector.reading_picture(file), np.ndarray)
def test_file_exists_not_an_image(tmp_path):
file = tmp_path / "file.txt"
file.write_text("Not an image.")
with pytest.raises(ValueError):
star_detector.reading_picture(file)
def test_file_does_not_exists(tmp_path):
with pytest.raises(FileNotFoundError):
star_detector.reading_picture(tmp_path/"do_I_exist.txt")
@pytest.mark.skip(reason="A corriger : égalité stricte sur flottants, canall couleur incohérent, détour disque inutile")
def test_blob_detector_actually_detects_a_blob(tmp_path):
file = tmp_path / "image.jpg"
tableau_image = np.full((64,64), 0, dtype=np.uint8)
cv2.imwrite(str(file), tableau_image)
src = cv2.imread(file)
cv2.circle(src, center=(23, 31), radius = 5, color= (255, 255, 255), thickness=-1)
assert star_detector.blob_detector(src) == [(23, 31)]
View File
View File
View File