formhtr 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- formhtr-0.1.0/LICENSE +21 -0
- formhtr-0.1.0/MANIFEST.in +2 -0
- formhtr-0.1.0/PKG-INFO +183 -0
- formhtr-0.1.0/README.md +151 -0
- formhtr-0.1.0/pyproject.toml +52 -0
- formhtr-0.1.0/setup.cfg +4 -0
- formhtr-0.1.0/src/formhtr/__init__.py +8 -0
- formhtr-0.1.0/src/formhtr/cli.py +163 -0
- formhtr-0.1.0/src/formhtr/data/fonts/Arial.ttf +0 -0
- formhtr-0.1.0/src/formhtr/deps.py +42 -0
- formhtr-0.1.0/src/formhtr/libs/__init__.py +2 -0
- formhtr-0.1.0/src/formhtr/libs/annotate_ROI/__init__.py +0 -0
- formhtr-0.1.0/src/formhtr/libs/annotate_ROI/annotate_ROIs_widget.py +71 -0
- formhtr-0.1.0/src/formhtr/libs/annotate_ROI/cli_inputs.py +20 -0
- formhtr-0.1.0/src/formhtr/libs/annotate_ROI/utils.py +24 -0
- formhtr-0.1.0/src/formhtr/libs/extract_ROI/__init__.py +0 -0
- formhtr-0.1.0/src/formhtr/libs/extract_ROI/autodect.py +106 -0
- formhtr-0.1.0/src/formhtr/libs/extract_ROI/cli_inputs.py +13 -0
- formhtr-0.1.0/src/formhtr/libs/extract_ROI/select_ROIs_widget.py +74 -0
- formhtr-0.1.0/src/formhtr/libs/logsheet_config.py +115 -0
- formhtr-0.1.0/src/formhtr/libs/pdf_to_image.py +48 -0
- formhtr-0.1.0/src/formhtr/libs/processing/__init__.py +0 -0
- formhtr-0.1.0/src/formhtr/libs/processing/align_images.py +99 -0
- formhtr-0.1.0/src/formhtr/libs/processing/barcode.py +55 -0
- formhtr-0.1.0/src/formhtr/libs/processing/checkbox.py +39 -0
- formhtr-0.1.0/src/formhtr/libs/processing/process_area.py +319 -0
- formhtr-0.1.0/src/formhtr/libs/processing/read_content.py +47 -0
- formhtr-0.1.0/src/formhtr/libs/processing/rtree.py +69 -0
- formhtr-0.1.0/src/formhtr/libs/processing/store_results.py +120 -0
- formhtr-0.1.0/src/formhtr/libs/region.py +81 -0
- formhtr-0.1.0/src/formhtr/libs/services/__init__.py +0 -0
- formhtr-0.1.0/src/formhtr/libs/services/amazon_vision.py +44 -0
- formhtr-0.1.0/src/formhtr/libs/services/azure_vision.py +47 -0
- formhtr-0.1.0/src/formhtr/libs/services/call_services.py +31 -0
- formhtr-0.1.0/src/formhtr/libs/services/google_vision.py +30 -0
- formhtr-0.1.0/src/formhtr/libs/services/utils.py +15 -0
- formhtr-0.1.0/src/formhtr/libs/statistics.py +16 -0
- formhtr-0.1.0/src/formhtr/libs/visualise_regions.py +40 -0
- formhtr-0.1.0/src/formhtr/logsheet.py +188 -0
- formhtr-0.1.0/src/formhtr/manual_align.py +109 -0
- formhtr-0.1.0/src/formhtr/roi_tools.py +73 -0
- formhtr-0.1.0/src/formhtr.egg-info/PKG-INFO +183 -0
- formhtr-0.1.0/src/formhtr.egg-info/SOURCES.txt +45 -0
- formhtr-0.1.0/src/formhtr.egg-info/dependency_links.txt +1 -0
- formhtr-0.1.0/src/formhtr.egg-info/entry_points.txt +2 -0
- formhtr-0.1.0/src/formhtr.egg-info/requires.txt +17 -0
- formhtr-0.1.0/src/formhtr.egg-info/top_level.txt +1 -0
formhtr-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Matej Troják
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
formhtr-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: formhtr
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Handprint text recognition in form documents.
|
|
5
|
+
Author-email: Matej Trojak <matej.trojak@embl.de>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/grp-bork/formHTR
|
|
8
|
+
Keywords: ocr,forms,computer-vision
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: opencv-python
|
|
16
|
+
Requires-Dist: pillow==9.5.0
|
|
17
|
+
Requires-Dist: pdf2image
|
|
18
|
+
Requires-Dist: pandas
|
|
19
|
+
Requires-Dist: xlsxwriter
|
|
20
|
+
Requires-Dist: imutils
|
|
21
|
+
Requires-Dist: zxing-cpp
|
|
22
|
+
Requires-Dist: google-cloud-vision
|
|
23
|
+
Requires-Dist: rtree
|
|
24
|
+
Requires-Dist: boto3
|
|
25
|
+
Requires-Dist: azure-cognitiveservices-vision-computervision
|
|
26
|
+
Requires-Dist: pyzbar
|
|
27
|
+
Requires-Dist: biopython
|
|
28
|
+
Requires-Dist: scikit-image
|
|
29
|
+
Requires-Dist: img2pdf
|
|
30
|
+
Requires-Dist: PyPDF2
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# formHTR
|
|
34
|
+
Handprint text recognition in form documents.
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/formhtr/)
|
|
37
|
+
|
|
38
|
+

|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
### pip
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install formhtr
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The tool also requires the `zbar` shared library installed (used by `pyzbar`).
|
|
49
|
+
For PDF-related tooling, `qpdf` is also required.
|
|
50
|
+
|
|
51
|
+
System dependencies:
|
|
52
|
+
|
|
53
|
+
- macOS (Homebrew): `brew install zbar qpdf`
|
|
54
|
+
- Debian/Ubuntu: `sudo apt-get install libzbar0 qpdf`
|
|
55
|
+
- Fedora: `sudo dnf install zbar qpdf`
|
|
56
|
+
|
|
57
|
+
You can verify runtime requirements with:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
formhtr doctor
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### conda (dev)
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
conda env create -f conda_env.yaml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
Run `formhtr --help` for full CLI help.
|
|
72
|
+
|
|
73
|
+
### Quickstart
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# 1) Verify system dependencies
|
|
77
|
+
formhtr doctor
|
|
78
|
+
|
|
79
|
+
# 2) Create ROI config for a template
|
|
80
|
+
formhtr select-rois --pdf-file template.pdf --output-file config.json
|
|
81
|
+
|
|
82
|
+
# 3) Optionally annotate ROI types and variable names
|
|
83
|
+
formhtr annotate-rois --pdf-file template.pdf --config-file config.json --output-file config_annotated.json
|
|
84
|
+
|
|
85
|
+
# 4) Process a scanned logsheet into XLSX
|
|
86
|
+
formhtr process-logsheet \
|
|
87
|
+
--pdf-logsheet scan.pdf \
|
|
88
|
+
--pdf-template template.pdf \
|
|
89
|
+
--config-file config_annotated.json \
|
|
90
|
+
--output-file output.xlsx \
|
|
91
|
+
--google google_credentials.json \
|
|
92
|
+
--amazon amazon_credentials.json \
|
|
93
|
+
--azure azure_credentials.json
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Create ROIs
|
|
97
|
+
|
|
98
|
+
This functionality is split (for now) into two separate scripts.
|
|
99
|
+
|
|
100
|
+
#### select ROIs
|
|
101
|
+
|
|
102
|
+
Find and define locations of regions of interest (ROIs) in the given PDF.
|
|
103
|
+
|
|
104
|
+
Generally, it is possible to draw ROIs (rectangles) manually but also to detect them automatically.
|
|
105
|
+
The coordinates of ROIs are stored in a JSON file.
|
|
106
|
+
|
|
107
|
+
The tool is supposed to be run from the command line, as the control commands are entered there.
|
|
108
|
+
|
|
109
|
+
*Control commands*
|
|
110
|
+
|
|
111
|
+
* Press `q` or `Esc` to exit editing and save the config file.
|
|
112
|
+
* Press `r` to remove the last rectangle.
|
|
113
|
+
|
|
114
|
+
Run `formhtr select-rois -h` for details.
|
|
115
|
+
|
|
116
|
+
#### annotate ROIs
|
|
117
|
+
|
|
118
|
+
Specify the type of content for each rectangle.
|
|
119
|
+
|
|
120
|
+
The workflow is designed in a way that you can navigate over specified ROIs and assign them the expected type of their content.
|
|
121
|
+
This is done by pressing appropriate control commands.
|
|
122
|
+
|
|
123
|
+
*Control commands*
|
|
124
|
+
|
|
125
|
+
* Press `q` or `Esc` to exit editing and save the config file.
|
|
126
|
+
* Press `h` to add "Handwritten" type to the current ROI.
|
|
127
|
+
* Press `c` to add "Checkbox" type to the current ROI.
|
|
128
|
+
* Press `b` to add "Barcode" type to the current ROI.
|
|
129
|
+
* Press `r` or `d` to delete the type from the current ROI.
|
|
130
|
+
* Press `v` to enter the variable name.
|
|
131
|
+
* Press an arrow to navigate through ROIs (only left and right for now).
|
|
132
|
+
|
|
133
|
+
Run `formhtr annotate-rois -h` for details.
|
|
134
|
+
|
|
135
|
+
### process logsheet
|
|
136
|
+
|
|
137
|
+
Extract values from specified ROIs.
|
|
138
|
+
|
|
139
|
+
This is the crucial step that applies various techniques to extract the information as precisely as possible.
|
|
140
|
+
It can process one logsheet at a time, given the template and config files.
|
|
141
|
+
|
|
142
|
+
Run `formhtr process-logsheet -h` for details.
|
|
143
|
+
|
|
144
|
+
#### Credentials
|
|
145
|
+
|
|
146
|
+
The processing of logsheets is using external services requiring credentials to use them. Here we specify structure that is expected for credentials, always in JSON format.
|
|
147
|
+
|
|
148
|
+
__Google__
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
{
|
|
152
|
+
"type": "service_account",
|
|
153
|
+
"project_id": "theid",,
|
|
154
|
+
"private_key_id": "thekey",
|
|
155
|
+
"private_key": "-----BEGIN PRIVATE KEY-----anotherkey-----END PRIVATE KEY-----\n"
|
|
156
|
+
"client_email": "emailaddress",
|
|
157
|
+
"client_id": "id",
|
|
158
|
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
|
159
|
+
"token_uri": "https://oauth2.googleapis.com/token",
|
|
160
|
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
|
161
|
+
"client_x509_cert_url": "someurl",
|
|
162
|
+
"universe_domain": "googleapis.com"
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
__Amazon__
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
{
|
|
170
|
+
"ACCESS_KEY": "YOUR_KEY_ID_HERE",
|
|
171
|
+
"SECRET_KEY": "YOUR_ACCESS_KEY_HERE",
|
|
172
|
+
"REGION": "YOUR_REGION_NAME_HERE"
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
__Microsoft__
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
{
|
|
180
|
+
"SUBSCRIPTION_KEY": "YOURKEYHERE",
|
|
181
|
+
"ENDPOINT": "https://ENDPOINT"
|
|
182
|
+
}
|
|
183
|
+
```
|
formhtr-0.1.0/README.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# formHTR
|
|
2
|
+
Handprint text recognition in form documents.
|
|
3
|
+
|
|
4
|
+
[](https://pypi.org/project/formhtr/)
|
|
5
|
+
|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
### pip
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install formhtr
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
The tool also requires the `zbar` shared library installed (used by `pyzbar`).
|
|
17
|
+
For PDF-related tooling, `qpdf` is also required.
|
|
18
|
+
|
|
19
|
+
System dependencies:
|
|
20
|
+
|
|
21
|
+
- macOS (Homebrew): `brew install zbar qpdf`
|
|
22
|
+
- Debian/Ubuntu: `sudo apt-get install libzbar0 qpdf`
|
|
23
|
+
- Fedora: `sudo dnf install zbar qpdf`
|
|
24
|
+
|
|
25
|
+
You can verify runtime requirements with:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
formhtr doctor
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### conda (dev)
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
conda env create -f conda_env.yaml
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Run `formhtr --help` for full CLI help.
|
|
40
|
+
|
|
41
|
+
### Quickstart
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# 1) Verify system dependencies
|
|
45
|
+
formhtr doctor
|
|
46
|
+
|
|
47
|
+
# 2) Create ROI config for a template
|
|
48
|
+
formhtr select-rois --pdf-file template.pdf --output-file config.json
|
|
49
|
+
|
|
50
|
+
# 3) Optionally annotate ROI types and variable names
|
|
51
|
+
formhtr annotate-rois --pdf-file template.pdf --config-file config.json --output-file config_annotated.json
|
|
52
|
+
|
|
53
|
+
# 4) Process a scanned logsheet into XLSX
|
|
54
|
+
formhtr process-logsheet \
|
|
55
|
+
--pdf-logsheet scan.pdf \
|
|
56
|
+
--pdf-template template.pdf \
|
|
57
|
+
--config-file config_annotated.json \
|
|
58
|
+
--output-file output.xlsx \
|
|
59
|
+
--google google_credentials.json \
|
|
60
|
+
--amazon amazon_credentials.json \
|
|
61
|
+
--azure azure_credentials.json
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Create ROIs
|
|
65
|
+
|
|
66
|
+
This functionality is split (for now) into two separate scripts.
|
|
67
|
+
|
|
68
|
+
#### select ROIs
|
|
69
|
+
|
|
70
|
+
Find and define locations of regions of interest (ROIs) in the given PDF.
|
|
71
|
+
|
|
72
|
+
Generally, it is possible to draw ROIs (rectangles) manually but also to detect them automatically.
|
|
73
|
+
The coordinates of ROIs are stored in a JSON file.
|
|
74
|
+
|
|
75
|
+
The tool is supposed to be run from the command line, as the control commands are entered there.
|
|
76
|
+
|
|
77
|
+
*Control commands*
|
|
78
|
+
|
|
79
|
+
* Press `q` or `Esc` to exit editing and save the config file.
|
|
80
|
+
* Press `r` to remove the last rectangle.
|
|
81
|
+
|
|
82
|
+
Run `formhtr select-rois -h` for details.
|
|
83
|
+
|
|
84
|
+
#### annotate ROIs
|
|
85
|
+
|
|
86
|
+
Specify the type of content for each rectangle.
|
|
87
|
+
|
|
88
|
+
The workflow is designed in a way that you can navigate over specified ROIs and assign them the expected type of their content.
|
|
89
|
+
This is done by pressing appropriate control commands.
|
|
90
|
+
|
|
91
|
+
*Control commands*
|
|
92
|
+
|
|
93
|
+
* Press `q` or `Esc` to exit editing and save the config file.
|
|
94
|
+
* Press `h` to add "Handwritten" type to the current ROI.
|
|
95
|
+
* Press `c` to add "Checkbox" type to the current ROI.
|
|
96
|
+
* Press `b` to add "Barcode" type to the current ROI.
|
|
97
|
+
* Press `r` or `d` to delete the type from the current ROI.
|
|
98
|
+
* Press `v` to enter the variable name.
|
|
99
|
+
* Press an arrow to navigate through ROIs (only left and right for now).
|
|
100
|
+
|
|
101
|
+
Run `formhtr annotate-rois -h` for details.
|
|
102
|
+
|
|
103
|
+
### process logsheet
|
|
104
|
+
|
|
105
|
+
Extract values from specified ROIs.
|
|
106
|
+
|
|
107
|
+
This is the crucial step that applies various techniques to extract the information as precisely as possible.
|
|
108
|
+
It can process one logsheet at a time, given the template and config files.
|
|
109
|
+
|
|
110
|
+
Run `formhtr process-logsheet -h` for details.
|
|
111
|
+
|
|
112
|
+
#### Credentials
|
|
113
|
+
|
|
114
|
+
The processing of logsheets is using external services requiring credentials to use them. Here we specify structure that is expected for credentials, always in JSON format.
|
|
115
|
+
|
|
116
|
+
__Google__
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
{
|
|
120
|
+
"type": "service_account",
|
|
121
|
+
"project_id": "theid",,
|
|
122
|
+
"private_key_id": "thekey",
|
|
123
|
+
"private_key": "-----BEGIN PRIVATE KEY-----anotherkey-----END PRIVATE KEY-----\n"
|
|
124
|
+
"client_email": "emailaddress",
|
|
125
|
+
"client_id": "id",
|
|
126
|
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
|
127
|
+
"token_uri": "https://oauth2.googleapis.com/token",
|
|
128
|
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
|
129
|
+
"client_x509_cert_url": "someurl",
|
|
130
|
+
"universe_domain": "googleapis.com"
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
__Amazon__
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
{
|
|
138
|
+
"ACCESS_KEY": "YOUR_KEY_ID_HERE",
|
|
139
|
+
"SECRET_KEY": "YOUR_ACCESS_KEY_HERE",
|
|
140
|
+
"REGION": "YOUR_REGION_NAME_HERE"
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
__Microsoft__
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
{
|
|
148
|
+
"SUBSCRIPTION_KEY": "YOURKEYHERE",
|
|
149
|
+
"ENDPOINT": "https://ENDPOINT"
|
|
150
|
+
}
|
|
151
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "formhtr"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Handprint text recognition in form documents."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Matej Trojak", email = "matej.trojak@embl.de" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["ocr", "forms", "computer-vision"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"numpy",
|
|
22
|
+
"opencv-python",
|
|
23
|
+
"pillow==9.5.0",
|
|
24
|
+
"pdf2image",
|
|
25
|
+
"pandas",
|
|
26
|
+
"xlsxwriter",
|
|
27
|
+
"imutils",
|
|
28
|
+
"zxing-cpp",
|
|
29
|
+
"google-cloud-vision",
|
|
30
|
+
"rtree",
|
|
31
|
+
"boto3",
|
|
32
|
+
"azure-cognitiveservices-vision-computervision",
|
|
33
|
+
"pyzbar",
|
|
34
|
+
"biopython",
|
|
35
|
+
"scikit-image",
|
|
36
|
+
"img2pdf",
|
|
37
|
+
"PyPDF2",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Repository = "https://github.com/grp-bork/formHTR"
|
|
42
|
+
|
|
43
|
+
[project.scripts]
|
|
44
|
+
formhtr = "formhtr.cli:main"
|
|
45
|
+
|
|
46
|
+
[tool.setuptools]
|
|
47
|
+
package-dir = {"" = "src"}
|
|
48
|
+
include-package-data = true
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.packages.find]
|
|
51
|
+
where = ["src"]
|
|
52
|
+
|
formhtr-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
from . import __version__
|
|
7
|
+
from .deps import check_system_dependencies, ensure_system_dependencies
|
|
8
|
+
from .logsheet import load_credentials, process_logsheet_to_xlsx
|
|
9
|
+
from .manual_align import manual_align_pdf
|
|
10
|
+
from .roi_tools import annotate_rois, select_rois
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
14
|
+
parser = argparse.ArgumentParser(prog="formhtr", description="formHTR CLI")
|
|
15
|
+
parser.add_argument("--version", action="version", version=f"%(prog)s {__version__}")
|
|
16
|
+
|
|
17
|
+
sub = parser.add_subparsers(dest="command", required=True)
|
|
18
|
+
|
|
19
|
+
p_process = sub.add_parser("process-logsheet", help="Extract values from a scanned logsheet to XLSX")
|
|
20
|
+
p_process.add_argument("--pdf-logsheet", required=True, help="Scanned logsheet PDF")
|
|
21
|
+
p_process.add_argument("--pdf-template", required=True, help="Template PDF")
|
|
22
|
+
p_process.add_argument("--config-file", required=True, help="Config JSON")
|
|
23
|
+
p_process.add_argument("--output-file", required=True, help="Output XLSX file")
|
|
24
|
+
p_process.add_argument("--google", required=True, help="Path to Google Vision credentials JSON")
|
|
25
|
+
p_process.add_argument("--amazon", required=True, help="Path to Amazon credentials JSON")
|
|
26
|
+
p_process.add_argument("--azure", required=True, help="Path to Azure credentials JSON")
|
|
27
|
+
p_process.add_argument("--debug", action=argparse.BooleanOptionalAction, default=False, help="Output annotated PDFs")
|
|
28
|
+
p_process.add_argument("--backside", action=argparse.BooleanOptionalAction, default=False, help="Backside page present")
|
|
29
|
+
p_process.add_argument("--backside-template", help="Backside template PDF")
|
|
30
|
+
p_process.add_argument("--backside-config", help="Backside config JSON")
|
|
31
|
+
p_process.add_argument(
|
|
32
|
+
"--ugly-checkboxes",
|
|
33
|
+
action=argparse.BooleanOptionalAction,
|
|
34
|
+
default=False,
|
|
35
|
+
help="Checkboxes have irregular shape / thick edges",
|
|
36
|
+
)
|
|
37
|
+
p_process.add_argument(
|
|
38
|
+
"--aligned",
|
|
39
|
+
action=argparse.BooleanOptionalAction,
|
|
40
|
+
default=False,
|
|
41
|
+
help="Scanned image already aligned with template (skip alignment)",
|
|
42
|
+
)
|
|
43
|
+
p_process.add_argument(
|
|
44
|
+
"--filter-grayscale",
|
|
45
|
+
action=argparse.BooleanOptionalAction,
|
|
46
|
+
default=False,
|
|
47
|
+
help="During alignment keep only darkest grayscale pixels",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
p_align = sub.add_parser("manual-align", help="Interactively align a scanned PDF to a template")
|
|
51
|
+
p_align.add_argument("--pdf-template", required=True, help="Template PDF")
|
|
52
|
+
p_align.add_argument("--pdf-logsheet", required=True, help="Scanned logsheet PDF")
|
|
53
|
+
p_align.add_argument("--output", required=True, help="Output aligned PDF")
|
|
54
|
+
p_align.add_argument("--backside-template", help="Backside template PDF")
|
|
55
|
+
|
|
56
|
+
p_select = sub.add_parser("select-rois", help="Interactively define ROIs in a template PDF")
|
|
57
|
+
p_select.add_argument("--pdf-file", required=True, help="Template PDF")
|
|
58
|
+
p_select.add_argument("--output-file", required=True, help="Output config JSON")
|
|
59
|
+
p_select.add_argument("--autodetect", action=argparse.BooleanOptionalAction, default=False)
|
|
60
|
+
p_select.add_argument("--autodetect-filter", type=float, default=3)
|
|
61
|
+
p_select.add_argument("--config-file", default=None, help="Existing config JSON to continue editing")
|
|
62
|
+
p_select.add_argument("--detect-residuals", action=argparse.BooleanOptionalAction, default=False)
|
|
63
|
+
p_select.add_argument("--credentials", default=None, help="Google credentials JSON (for residual detection)")
|
|
64
|
+
p_select.add_argument("--display-residuals", action=argparse.BooleanOptionalAction, default=False)
|
|
65
|
+
|
|
66
|
+
p_annot = sub.add_parser("annotate-rois", help="Interactively label ROI types/variables")
|
|
67
|
+
p_annot.add_argument("--pdf-file", required=True, help="Template PDF")
|
|
68
|
+
p_annot.add_argument("--config-file", required=True, help="Input config JSON")
|
|
69
|
+
p_annot.add_argument("--output-file", required=True, help="Output config JSON")
|
|
70
|
+
p_annot.add_argument("--remove-unannotated", action=argparse.BooleanOptionalAction, default=False)
|
|
71
|
+
p_annot.add_argument("--display-residuals", action=argparse.BooleanOptionalAction, default=False)
|
|
72
|
+
|
|
73
|
+
sub.add_parser("doctor", help="Check required system dependencies")
|
|
74
|
+
|
|
75
|
+
return parser
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main(argv: list[str] | None = None) -> int:
|
|
79
|
+
parser = _build_parser()
|
|
80
|
+
args = parser.parse_args(argv)
|
|
81
|
+
|
|
82
|
+
if args.command == "process-logsheet":
|
|
83
|
+
ensure_system_dependencies({"zbar"})
|
|
84
|
+
if args.backside and (not args.backside_template or not args.backside_config):
|
|
85
|
+
parser.error("--backside requires --backside-template and --backside-config.")
|
|
86
|
+
|
|
87
|
+
credentials = load_credentials(
|
|
88
|
+
google_credentials_path=args.google,
|
|
89
|
+
amazon_credentials_path=args.amazon,
|
|
90
|
+
azure_credentials_path=args.azure,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
ratio = process_logsheet_to_xlsx(
|
|
94
|
+
scanned_logsheet_pdf=args.pdf_logsheet,
|
|
95
|
+
template_pdf=args.pdf_template,
|
|
96
|
+
config_json=args.config_file,
|
|
97
|
+
output_xlsx=args.output_file,
|
|
98
|
+
credentials=credentials,
|
|
99
|
+
debug=args.debug,
|
|
100
|
+
backside=args.backside,
|
|
101
|
+
backside_template_pdf=args.backside_template,
|
|
102
|
+
backside_config_json=args.backside_config,
|
|
103
|
+
ugly_checkboxes=args.ugly_checkboxes,
|
|
104
|
+
already_aligned=args.aligned,
|
|
105
|
+
filter_grayscale=args.filter_grayscale,
|
|
106
|
+
)
|
|
107
|
+
if ratio is not None:
|
|
108
|
+
print(f"Success ratio: {ratio['ratio']:.3f}")
|
|
109
|
+
return 0
|
|
110
|
+
|
|
111
|
+
if args.command == "manual-align":
|
|
112
|
+
ensure_system_dependencies({"qpdf"})
|
|
113
|
+
manual_align_pdf(
|
|
114
|
+
template_pdf=args.pdf_template,
|
|
115
|
+
scanned_logsheet_pdf=args.pdf_logsheet,
|
|
116
|
+
output_pdf=args.output,
|
|
117
|
+
backside_template_pdf=args.backside_template,
|
|
118
|
+
)
|
|
119
|
+
return 0
|
|
120
|
+
|
|
121
|
+
if args.command == "select-rois":
|
|
122
|
+
if args.detect_residuals and not args.credentials:
|
|
123
|
+
parser.error("--detect-residuals requires --credentials.")
|
|
124
|
+
select_rois(
|
|
125
|
+
template_pdf=args.pdf_file,
|
|
126
|
+
output_config_json=args.output_file,
|
|
127
|
+
autodetect=args.autodetect,
|
|
128
|
+
autodetect_filter=args.autodetect_filter,
|
|
129
|
+
existing_config_json=args.config_file,
|
|
130
|
+
detect_residuals=args.detect_residuals,
|
|
131
|
+
google_credentials_path=args.credentials,
|
|
132
|
+
display_residuals=args.display_residuals,
|
|
133
|
+
)
|
|
134
|
+
return 0
|
|
135
|
+
|
|
136
|
+
if args.command == "annotate-rois":
|
|
137
|
+
annotate_rois(
|
|
138
|
+
template_pdf=args.pdf_file,
|
|
139
|
+
config_json=args.config_file,
|
|
140
|
+
output_config_json=args.output_file,
|
|
141
|
+
remove_unannotated=args.remove_unannotated,
|
|
142
|
+
display_residuals=args.display_residuals,
|
|
143
|
+
)
|
|
144
|
+
return 0
|
|
145
|
+
|
|
146
|
+
if args.command == "doctor":
|
|
147
|
+
missing = check_system_dependencies()
|
|
148
|
+
if not missing:
|
|
149
|
+
print("All required system dependencies are available: qpdf, zbar.")
|
|
150
|
+
return 0
|
|
151
|
+
|
|
152
|
+
print("Missing system dependencies:")
|
|
153
|
+
for name, hint in missing:
|
|
154
|
+
print(f"- {name}: {hint}")
|
|
155
|
+
return 1
|
|
156
|
+
|
|
157
|
+
parser.error(f"Unknown command: {args.command}")
|
|
158
|
+
return 2
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
if __name__ == "__main__":
|
|
162
|
+
raise SystemExit(main(sys.argv[1:]))
|
|
163
|
+
|
|
Binary file
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import ctypes.util
|
|
4
|
+
import platform
|
|
5
|
+
import shutil
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _install_hint(dep_name: str) -> str:
|
|
9
|
+
system = platform.system().lower()
|
|
10
|
+
if system == "darwin":
|
|
11
|
+
return f"brew install {dep_name}"
|
|
12
|
+
if system == "linux":
|
|
13
|
+
if dep_name == "zbar":
|
|
14
|
+
return "apt: sudo apt-get install libzbar0 | dnf: sudo dnf install zbar"
|
|
15
|
+
return f"apt: sudo apt-get install {dep_name} | dnf: sudo dnf install {dep_name}"
|
|
16
|
+
return f"Install {dep_name} using your system package manager."
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def check_system_dependencies() -> list[tuple[str, str]]:
|
|
20
|
+
missing: list[tuple[str, str]] = []
|
|
21
|
+
|
|
22
|
+
if shutil.which("qpdf") is None:
|
|
23
|
+
missing.append(("qpdf", _install_hint("qpdf")))
|
|
24
|
+
|
|
25
|
+
if ctypes.util.find_library("zbar") is None:
|
|
26
|
+
missing.append(("zbar", _install_hint("zbar")))
|
|
27
|
+
|
|
28
|
+
return missing
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def ensure_system_dependencies(required: set[str]) -> None:
|
|
32
|
+
missing = check_system_dependencies()
|
|
33
|
+
missing_required = [(name, hint) for name, hint in missing if name in required]
|
|
34
|
+
if not missing_required:
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
lines = ["Missing required system dependencies:"]
|
|
38
|
+
for name, hint in missing_required:
|
|
39
|
+
lines.append(f"- {name}: {hint}")
|
|
40
|
+
lines.append("Run `formhtr doctor` for a full dependency report.")
|
|
41
|
+
raise RuntimeError("\n".join(lines))
|
|
42
|
+
|
|
File without changes
|