Compare commits
2
Commits
b9e9d00e7d
...
576e3c9452
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
576e3c9452 | ||
|
|
2921d5ec8e |
+10
@@ -0,0 +1,10 @@
|
|||||||
|
OLD/
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.venv/
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
*.egg-info/
|
||||||
|
config.py
|
||||||
|
.copienator-gui.json
|
||||||
|
.copienator/
|
||||||
+63
-12
@@ -33,26 +33,77 @@ question précédente ou autre.
|
|||||||
Les labels de questions sont utilisés comme noms de fichiers. Les
|
Les labels de questions sont utilisés comme noms de fichiers. Les
|
||||||
labels contenant notamment =:= ne sont pas acceptés par Windows.
|
labels contenant notamment =:= ne sont pas acceptés par Windows.
|
||||||
|
|
||||||
** Requirements
|
** Prérequis et installation
|
||||||
|
|
||||||
*** Python
|
*** Python 3.11 ou plus récent
|
||||||
|
|
||||||
Libraries :
|
Créer et activer un environnement virtuel est recommandé :
|
||||||
|
|
||||||
#+BEGIN_SRC bash
|
#+BEGIN_SRC bash
|
||||||
pip install numpy pandas matplotlib pillow pydantic pypdf pdf2image reportlab img2pdf pymupdf ftfy ezodf google
|
python -m venv .venv
|
||||||
pip install -e .
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
|
||||||
La seconde commande installe les exécutables =copienator= et
|
Sous Linux :
|
||||||
=copienator-gui=. Sans installation, les mêmes commandes restent
|
|
||||||
accessibles avec =python -m copienator=.
|
|
||||||
|
|
||||||
*** Poppler (for pdf2image)
|
#+BEGIN_SRC bash
|
||||||
|
source .venv/bin/activate
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
+ Linux : install poppler-utils
|
Sous Windows (PowerShell) :
|
||||||
+ Windows : Download from: https://github.com/oschwartz10612/poppler-windows
|
|
||||||
and add it to your PATH
|
#+BEGIN_SRC powershell
|
||||||
|
.venv\Scripts\Activate.ps1
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Installer ensuite Copienator et ses dépendances Python depuis la
|
||||||
|
racine du dépôt :
|
||||||
|
|
||||||
|
#+BEGIN_SRC bash
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -e .
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Cette commande installe les modules contrôlés par le diagnostic du GUI
|
||||||
|
(NumPy, pandas, Matplotlib, Pillow, pydantic, pypdf, pdf2image,
|
||||||
|
ReportLab, img2pdf, PyMuPDF, ftfy, ezodf et Google Gen AI), ainsi que
|
||||||
|
les exécutables =copienator= et =copienator-gui=. Le paquet fournissant
|
||||||
|
=google.genai= est =google-genai=, et non =google=.
|
||||||
|
|
||||||
|
Les commandes restent également accessibles avec
|
||||||
|
=python -m copienator= depuis la racine du dépôt.
|
||||||
|
|
||||||
|
*** Programmes externes obligatoires
|
||||||
|
|
||||||
|
Le diagnostic vérifie que Poppler et LaTeX sont accessibles depuis
|
||||||
|
=PATH=.
|
||||||
|
|
||||||
|
**** Linux (Debian et Ubuntu)
|
||||||
|
|
||||||
|
#+BEGIN_SRC bash
|
||||||
|
sudo apt install poppler-utils python3-tk texlive-latex-extra texlive-fonts-extra lmodern python3-pygments
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Cette sélection couvre les modèles LaTeX de la configuration par
|
||||||
|
défaut, notamment =standalone=, =lmodern=, =mathabx= et =minted=. Selon
|
||||||
|
les commandes LaTeX utilisées dans vos propres énoncés, d'autres
|
||||||
|
paquets TeX peuvent être nécessaires. =python3-tk= fournit Tkinter sur
|
||||||
|
les installations Python qui ne l'incluent pas d'origine.
|
||||||
|
|
||||||
|
**** Windows
|
||||||
|
|
||||||
|
1. Télécharger [[https://github.com/oschwartz10612/poppler-windows][Poppler pour Windows]] et ajouter son dossier =bin= à
|
||||||
|
=PATH=.
|
||||||
|
2. Installer une distribution LaTeX, par exemple MiKTeX ou TeX Live,
|
||||||
|
et vérifier que =pdflatex= est accessible depuis =PATH=.
|
||||||
|
|
||||||
|
Fermer puis rouvrir le terminal et le GUI après une modification de
|
||||||
|
=PATH=.
|
||||||
|
|
||||||
|
*** Programme externe facultatif
|
||||||
|
|
||||||
|
PDF Arranger permet d'ouvrir et de réorganiser plus facilement les
|
||||||
|
PDF. Son absence est signalée comme facultative dans le diagnostic. Il
|
||||||
|
doit fournir la commande =pdf-arranger= ou =pdfarranger= dans =PATH=.
|
||||||
|
|
||||||
*** Accès à Gemini
|
*** Accès à Gemini
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,19 @@ def page_number(b, nb_pages):
|
|||||||
center_x = (b[1] + b[3]) // 2
|
center_x = (b[1] + b[3]) // 2
|
||||||
return center_x // column_width
|
return center_x // column_width
|
||||||
|
|
||||||
|
|
||||||
|
def sort_bounding_boxes(bounding_boxes, nb_pages):
|
||||||
|
"""Return label boxes in reading order: columns first, then top to bottom."""
|
||||||
|
return sorted(
|
||||||
|
bounding_boxes,
|
||||||
|
key=lambda entry: (
|
||||||
|
page_number(entry["box_2d"], nb_pages),
|
||||||
|
entry["box_2d"][0],
|
||||||
|
entry["box_2d"][1],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def convert_box2d(b, pn_ori, npn, tot_ori, tot_dest):
|
def convert_box2d(b, pn_ori, npn, tot_ori, tot_dest):
|
||||||
l = b.copy()
|
l = b.copy()
|
||||||
l[1] = (l[1] - (1000 // tot_ori) * (pn_ori-1)) * tot_ori // tot_dest\
|
l[1] = (l[1] - (1000 // tot_ori) * (pn_ori-1)) * tot_ori // tot_dest\
|
||||||
@@ -75,9 +88,8 @@ def prepare_image(image_path: str, bounding_boxes, all_labels, nb_pages, last_la
|
|||||||
new_im = Image.new(im.mode, (width + padding, height), "white")
|
new_im = Image.new(im.mode, (width + padding, height), "white")
|
||||||
new_im.paste(im, (0, 0))
|
new_im.paste(im, (0, 0))
|
||||||
draw = ImageDraw.Draw(new_im)
|
draw = ImageDraw.Draw(new_im)
|
||||||
bounding_boxes.sort(key=lambda b: (page_number(b["box_2d"], nb_pages), b["box_2d"][0]))
|
|
||||||
|
|
||||||
for bbox in bounding_boxes:
|
for bbox in sort_bounding_boxes(bounding_boxes, nb_pages):
|
||||||
raw_y_min = int(bbox["box_2d"][0] * height / 1000)
|
raw_y_min = int(bbox["box_2d"][0] * height / 1000)
|
||||||
raw_x_min = int(bbox["box_2d"][1] * width / 1000)
|
raw_x_min = int(bbox["box_2d"][1] * width / 1000)
|
||||||
raw_y_max = int(bbox["box_2d"][2] * height / 1000)
|
raw_y_max = int(bbox["box_2d"][2] * height / 1000)
|
||||||
@@ -321,15 +333,28 @@ class ImageViewer:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
current_data = read_json(self.current_json_path)
|
current_data = read_json(self.current_json_path)
|
||||||
|
nb_pages = self.current_meta["schema"]["columns_per_file"][
|
||||||
|
self.current_meta["part"] - 1
|
||||||
|
]
|
||||||
|
original_items = current_data["list"]
|
||||||
|
ordered_items = sort_bounding_boxes(original_items, nb_pages)
|
||||||
|
|
||||||
|
if ordered_items != original_items:
|
||||||
|
current_data["list"] = ordered_items
|
||||||
|
atomic_write_json(self.current_json_path, current_data)
|
||||||
|
print(
|
||||||
|
f"Reordered labels by column in "
|
||||||
|
f"{self.current_json_path.name}."
|
||||||
|
)
|
||||||
|
|
||||||
# Perform the conversion now, post-edit
|
# Perform the conversion now, post-edit
|
||||||
converted_items = convert_list(
|
converted_items = convert_list(
|
||||||
current_data["list"],
|
ordered_items,
|
||||||
self.current_meta["part"],
|
self.current_meta["part"],
|
||||||
self.current_meta["schema"]
|
self.current_meta["schema"]
|
||||||
)
|
)
|
||||||
|
|
||||||
labels = normalized_labels(current_data["list"])
|
labels = normalized_labels(ordered_items)
|
||||||
false_labels = [
|
false_labels = [
|
||||||
label for label in labels if label not in self.valid_labels
|
label for label in labels if label not in self.valid_labels
|
||||||
]
|
]
|
||||||
@@ -472,4 +497,3 @@ def main(argv: Sequence[str] | None = None) -> int:
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
raise SystemExit(main())
|
raise SystemExit(main())
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,21 @@ name = "copienator"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = "Workflow assistant for preparing and correcting scanned exams"
|
description = "Workflow assistant for preparing and correcting scanned exams"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
dependencies = [
|
||||||
|
"numpy",
|
||||||
|
"pandas",
|
||||||
|
"matplotlib",
|
||||||
|
"Pillow",
|
||||||
|
"pydantic",
|
||||||
|
"pypdf",
|
||||||
|
"pdf2image",
|
||||||
|
"reportlab",
|
||||||
|
"img2pdf",
|
||||||
|
"PyMuPDF",
|
||||||
|
"ftfy",
|
||||||
|
"ezodf",
|
||||||
|
"google-genai",
|
||||||
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
copienator = "copienator.dispatcher:main"
|
copienator = "copienator.dispatcher:main"
|
||||||
|
|||||||
Reference in New Issue
Block a user