Compare commits
2
Commits
| 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
|
||||
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
|
||||
pip install numpy pandas matplotlib pillow pydantic pypdf pdf2image reportlab img2pdf pymupdf ftfy ezodf google
|
||||
pip install -e .
|
||||
python -m venv .venv
|
||||
#+END_SRC
|
||||
|
||||
La seconde commande installe les exécutables =copienator= et
|
||||
=copienator-gui=. Sans installation, les mêmes commandes restent
|
||||
accessibles avec =python -m copienator=.
|
||||
Sous Linux :
|
||||
|
||||
*** Poppler (for pdf2image)
|
||||
#+BEGIN_SRC bash
|
||||
source .venv/bin/activate
|
||||
#+END_SRC
|
||||
|
||||
+ Linux : install poppler-utils
|
||||
+ Windows : Download from: https://github.com/oschwartz10612/poppler-windows
|
||||
and add it to your PATH
|
||||
Sous Windows (PowerShell) :
|
||||
|
||||
#+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
|
||||
|
||||
|
||||
@@ -37,6 +37,19 @@ def page_number(b, nb_pages):
|
||||
center_x = (b[1] + b[3]) // 2
|
||||
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):
|
||||
l = b.copy()
|
||||
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.paste(im, (0, 0))
|
||||
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_x_min = int(bbox["box_2d"][1] * width / 1000)
|
||||
raw_y_max = int(bbox["box_2d"][2] * height / 1000)
|
||||
@@ -321,15 +333,28 @@ class ImageViewer:
|
||||
|
||||
try:
|
||||
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
|
||||
converted_items = convert_list(
|
||||
current_data["list"],
|
||||
ordered_items,
|
||||
self.current_meta["part"],
|
||||
self.current_meta["schema"]
|
||||
)
|
||||
|
||||
labels = normalized_labels(current_data["list"])
|
||||
labels = normalized_labels(ordered_items)
|
||||
false_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__":
|
||||
raise SystemExit(main())
|
||||
|
||||
|
||||
@@ -7,6 +7,21 @@ name = "copienator"
|
||||
version = "0.1.0"
|
||||
description = "Workflow assistant for preparing and correcting scanned exams"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"numpy",
|
||||
"pandas",
|
||||
"matplotlib",
|
||||
"Pillow",
|
||||
"pydantic",
|
||||
"pypdf",
|
||||
"pdf2image",
|
||||
"reportlab",
|
||||
"img2pdf",
|
||||
"PyMuPDF",
|
||||
"ftfy",
|
||||
"ezodf",
|
||||
"google-genai",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
copienator = "copienator.dispatcher:main"
|
||||
|
||||
Reference in New Issue
Block a user