imgcheck 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.
imgcheck-0.1.0/LICENSE ADDED
@@ -0,0 +1,45 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rama Narasimha Kanduri & CS Hari Krishna
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.
22
+
23
+ -------------------------------------------------------------------------------
24
+
25
+ ACKNOWLEDGEMENT REQUEST (not legally binding, but appreciated)
26
+
27
+ If you use imgcheck in your research, project, or product, we would really
28
+ appreciate it if you could — if possible — give a small credit in any of
29
+ these ways, whichever feels right to you:
30
+
31
+ Option 1 — Credit the tool:
32
+ "Dataset auditing was performed using imgcheck
33
+ (https://pypi.org/project/imgcheck)."
34
+
35
+ Option 2 — Credit the authors:
36
+ "Dataset auditing was performed using imgcheck
37
+ (Rama Narasimha Kanduri & CS Hari Krishna, 2026)."
38
+
39
+ Option 3 — Credit both:
40
+ "Dataset auditing was performed using imgcheck by
41
+ Rama Narasimha Kanduri & CS Hari Krishna
42
+ (https://pypi.org/project/imgcheck)."
43
+
44
+ Any acknowledgement — the tool name, the authors, or both — is warmly
45
+ appreciated. Thank you for using imgcheck!
@@ -0,0 +1,495 @@
1
+ Metadata-Version: 2.4
2
+ Name: imgcheck
3
+ Version: 0.1.0
4
+ Summary: Perceptual-hash based image deduplication and train/test leakage detection for image classification datasets
5
+ Author-email: Rama Narasimha Kanduri <kramanarasimha1@gmail.com>, CS Hari Krishna <csharikrishna1806@gmail.com>
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 Rama Narasimha Kanduri & CS Hari Krishna
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy
11
+ of this software and associated documentation files (the "Software"), to deal
12
+ in the Software without restriction, including without limitation the rights
13
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14
+ copies of the Software, and to permit persons to whom the Software is
15
+ furnished to do so, subject to the following conditions:
16
+
17
+ The above copyright notice and this permission notice shall be included in all
18
+ copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ SOFTWARE.
27
+
28
+ -------------------------------------------------------------------------------
29
+
30
+ ACKNOWLEDGEMENT REQUEST (not legally binding, but appreciated)
31
+
32
+ If you use imgcheck in your research, project, or product, we would really
33
+ appreciate it if you could — if possible — give a small credit in any of
34
+ these ways, whichever feels right to you:
35
+
36
+ Option 1 — Credit the tool:
37
+ "Dataset auditing was performed using imgcheck
38
+ (https://pypi.org/project/imgcheck)."
39
+
40
+ Option 2 — Credit the authors:
41
+ "Dataset auditing was performed using imgcheck
42
+ (Rama Narasimha Kanduri & CS Hari Krishna, 2026)."
43
+
44
+ Option 3 — Credit both:
45
+ "Dataset auditing was performed using imgcheck by
46
+ Rama Narasimha Kanduri & CS Hari Krishna
47
+ (https://pypi.org/project/imgcheck)."
48
+
49
+ Any acknowledgement — the tool name, the authors, or both — is warmly
50
+ appreciated. Thank you for using imgcheck!
51
+
52
+ Requires-Python: >=3.9
53
+ Description-Content-Type: text/markdown
54
+ License-File: LICENSE
55
+ Requires-Dist: Pillow>=9.0
56
+ Requires-Dist: ImageHash>=4.3
57
+ Requires-Dist: pandas>=1.5
58
+ Requires-Dist: openpyxl>=3.0
59
+ Provides-Extra: pdf
60
+ Requires-Dist: fpdf2>=2.7; extra == "pdf"
61
+ Dynamic: license-file
62
+
63
+ # imgcheck
64
+
65
+ > Perceptual-hash based tools for auditing and cleaning image classification datasets —
66
+ > find duplicates, detect train/test leakage, and catch cross-label mislabelling, all from one CLI.
67
+
68
+ ---
69
+
70
+ ## What it does
71
+
72
+ Image classification datasets silently suffer from three data quality problems that hurt model accuracy:
73
+
74
+ | Problem | What it means | Detect | Remove |
75
+ |---|---|---|---|
76
+ | **Within-class duplicates** | Same image appears multiple times in one class, inflating dataset size | `imgcheck clean` | `imgcheck clean-inplace` |
77
+ | **Train/test leakage** | A test image is a near-duplicate of a train image — model has effectively "seen" it, inflating test accuracy | `imgcheck leakage` | `imgcheck leakage-fix` |
78
+ | **Cross-label duplicates** | Same image appears under two *different* class labels — contradictory training signal | `imgcheck cross-label` | `imgcheck cross-label-fix` |
79
+
80
+ Plus a fast no-hashing sanity check:
81
+
82
+ | Command | What it gives you |
83
+ |---|---|
84
+ | `imgcheck stats` | Per-class image counts, resolutions, class imbalance ratio, corrupt files |
85
+
86
+ ---
87
+
88
+ ## Real-world example (Brain Tumor MRI Dataset)
89
+
90
+ Suppose your dataset looks like:
91
+
92
+ ```
93
+ dataset/
94
+ ├── glioma/ (1000 images)
95
+ ├── meningioma/ (800 images)
96
+ ├── pituitary/ (900 images)
97
+ └── no_tumor/ (500 images)
98
+
99
+ train/
100
+ ├── glioma/
101
+ ├── meningioma/
102
+ ├── pituitary/
103
+ └── no_tumor/
104
+
105
+ test/
106
+ ├── glioma/
107
+ ├── meningioma/
108
+ ├── pituitary/
109
+ └── no_tumor/
110
+ ```
111
+
112
+ ### Step 1 — Quick sanity check (no hashing, instant)
113
+
114
+ ```bash
115
+ imgcheck stats --dataset dataset/ --report reports/stats.xlsx
116
+ ```
117
+
118
+ Output tells you: image counts per class, resolution ranges, class imbalance ratio (e.g. `2.0x`), and any corrupt files.
119
+
120
+ ---
121
+
122
+ ### Step 2 — Find and remove within-class duplicates
123
+
124
+ **Option A — Safe: copy survivors to a new clean folder (original untouched)**
125
+ ```bash
126
+ imgcheck clean \
127
+ --dataset dataset/ \
128
+ --output dataset_clean/ \
129
+ --report reports/duplicates.xlsx \
130
+ --html reports/duplicates.html
131
+ ```
132
+
133
+ **Option B — In-place: delete duplicates directly from the dataset**
134
+ ```bash
135
+ imgcheck clean-inplace \
136
+ --dataset dataset/ \
137
+ --report reports/duplicates_removed.xlsx
138
+ ```
139
+
140
+ Both generate a report showing exactly which images were removed and which were kept, with Cluster IDs grouping chains of similar images.
141
+
142
+ ---
143
+
144
+ ### Step 3 — Find and remove train/test leakage
145
+
146
+ **First, detect and review (read-only)**
147
+ ```bash
148
+ imgcheck leakage \
149
+ --train train/ \
150
+ --test test/ \
151
+ --report reports/leakage.xlsx \
152
+ --html reports/leakage.html
153
+ ```
154
+
155
+ **Then, remove — Option A: delete leaked test images in-place**
156
+ ```bash
157
+ imgcheck leakage-fix \
158
+ --train train/ \
159
+ --test test/ \
160
+ --report reports/leakage_removed.xlsx \
161
+ --mode inplace
162
+ ```
163
+
164
+ **Or — Option B: copy only clean test images to a new folder**
165
+ ```bash
166
+ imgcheck leakage-fix \
167
+ --train train/ \
168
+ --test test/ \
169
+ --report reports/leakage_removed.xlsx \
170
+ --mode copy \
171
+ --output test_clean/
172
+ ```
173
+
174
+ ---
175
+
176
+ ### Step 4 — Find and remove cross-label mislabelling
177
+
178
+ **First, detect and review (read-only)**
179
+ ```bash
180
+ imgcheck cross-label \
181
+ --dataset dataset/ \
182
+ --report reports/crosslabel.xlsx \
183
+ --html reports/crosslabel.html
184
+ ```
185
+
186
+ **Then, remove — Option A: delete the mislabelled copy in-place**
187
+ ```bash
188
+ imgcheck cross-label-fix \
189
+ --dataset dataset/ \
190
+ --report reports/crosslabel_removed.xlsx \
191
+ --mode inplace
192
+ ```
193
+
194
+ **Or — Option B: copy clean dataset (minus mislabelled images) to a new folder**
195
+ ```bash
196
+ imgcheck cross-label-fix \
197
+ --dataset dataset/ \
198
+ --report reports/crosslabel_removed.xlsx \
199
+ --mode copy \
200
+ --output dataset_clean/
201
+ ```
202
+
203
+ > **Which copy gets removed?** For each cross-label pair, imgcheck keeps the image in the alphabetically-earlier class and removes the copy in the later class. This is deterministic regardless of file discovery order.
204
+
205
+ ---
206
+
207
+ ## How it works
208
+
209
+ All hashing commands use **perceptual hashing** — not cryptographic hashing. A perceptual hash encodes the *visual appearance* of an image as a short bitstring. Two images that look identical (even if they differ in JPEG quality, slight cropping, or minor brightness) produce hashes with a low **Hamming distance** (number of differing bits).
210
+
211
+ **Threshold guide:**
212
+
213
+ | `--threshold` | What gets matched |
214
+ |---|---|
215
+ | `0` | Exact pixel-perfect duplicates only |
216
+ | `1–3` | Near-duplicates (default: `3`) |
217
+ | `4–10` | Resized, re-compressed, or slightly edited variants |
218
+
219
+ **Clustering** uses **Union-Find**, so a transitive chain A ~ B ~ C is correctly collapsed into one group with one representative — not three confusing separate pairs.
220
+
221
+ ---
222
+
223
+ ## Dataset structure required
224
+
225
+ All commands expect a root folder of **class subfolders**:
226
+
227
+ ```
228
+ dataset/
229
+ ├── cats/
230
+ │ ├── img001.jpg
231
+ │ └── img002.png
232
+ ├── dogs/
233
+ │ └── img003.jpg
234
+ └── birds/
235
+ └── ...
236
+ ```
237
+
238
+ Class names can be **anything** — the tool reads them dynamically from disk. Nothing is hardcoded.
239
+
240
+ For `leakage` and `leakage-fix`, train and test roots must have **matching class subfolder names**:
241
+
242
+ ```
243
+ train/ test/
244
+ ├── cats/ ├── cats/
245
+ ├── dogs/ ├── dogs/
246
+ └── birds/ └── birds/
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Install
252
+
253
+ From the project root (where `pyproject.toml` lives):
254
+
255
+ ```bash
256
+ pip install -e .
257
+ ```
258
+
259
+ Installs the `imgcheck` command with all required dependencies:
260
+ `Pillow`, `ImageHash`, `pandas`, `openpyxl`
261
+
262
+ ### Optional: PDF reports
263
+
264
+ ```bash
265
+ pip install -e ".[pdf]"
266
+ ```
267
+
268
+ Adds `fpdf2` for the `--pdf` flag. The `--html` flag needs no extra install.
269
+
270
+ ---
271
+
272
+ ## Full command reference
273
+
274
+ ### `imgcheck stats`
275
+
276
+ ```bash
277
+ imgcheck stats \
278
+ --dataset path/to/dataset \
279
+ --report path/to/stats.xlsx # optional
280
+ ```
281
+
282
+ ### `imgcheck clean` *(detection + copy)*
283
+
284
+ ```bash
285
+ imgcheck clean \
286
+ --dataset path/to/dataset \
287
+ --output path/to/dataset_clean \
288
+ --report path/to/duplicates.xlsx \
289
+ --threshold 3 \
290
+ --algo phash \
291
+ --html path/to/duplicates.html \
292
+ --pdf path/to/duplicates.pdf \
293
+ --formats csv,json
294
+ ```
295
+
296
+ ### `imgcheck clean-inplace` *(removal — destructive)*
297
+
298
+ ```bash
299
+ imgcheck clean-inplace \
300
+ --dataset path/to/dataset \
301
+ --report path/to/removed.xlsx \
302
+ --threshold 3 \
303
+ --algo phash \
304
+ --formats csv,json
305
+ ```
306
+
307
+ ### `imgcheck leakage` *(detection only)*
308
+
309
+ ```bash
310
+ imgcheck leakage \
311
+ --train path/to/train \
312
+ --test path/to/test \
313
+ --report path/to/leakage.xlsx \
314
+ --threshold 3 \
315
+ --algo phash \
316
+ --html path/to/leakage.html \
317
+ --pdf path/to/leakage.pdf \
318
+ --formats csv,json
319
+ ```
320
+
321
+ ### `imgcheck leakage-fix` *(removal)*
322
+
323
+ ```bash
324
+ # inplace — deletes from test folder directly
325
+ imgcheck leakage-fix \
326
+ --train path/to/train \
327
+ --test path/to/test \
328
+ --report path/to/leakage_removed.xlsx \
329
+ --mode inplace \
330
+ --threshold 3 \
331
+ --algo phash
332
+
333
+ # copy — writes clean test set to a new folder
334
+ imgcheck leakage-fix \
335
+ --train path/to/train \
336
+ --test path/to/test \
337
+ --report path/to/leakage_removed.xlsx \
338
+ --mode copy \
339
+ --output path/to/test_clean \
340
+ --threshold 3
341
+ ```
342
+
343
+ ### `imgcheck cross-label` *(detection only)*
344
+
345
+ ```bash
346
+ imgcheck cross-label \
347
+ --dataset path/to/dataset \
348
+ --report path/to/crosslabel.xlsx \
349
+ --threshold 3 \
350
+ --algo phash \
351
+ --html path/to/crosslabel.html \
352
+ --pdf path/to/crosslabel.pdf \
353
+ --formats csv,json
354
+ ```
355
+
356
+ ### `imgcheck cross-label-fix` *(removal)*
357
+
358
+ ```bash
359
+ # inplace — deletes the mislabelled copy from dataset directly
360
+ imgcheck cross-label-fix \
361
+ --dataset path/to/dataset \
362
+ --report path/to/crosslabel_removed.xlsx \
363
+ --mode inplace \
364
+ --threshold 3
365
+
366
+ # copy — writes clean dataset (minus mislabelled images) to a new folder
367
+ imgcheck cross-label-fix \
368
+ --dataset path/to/dataset \
369
+ --report path/to/crosslabel_removed.xlsx \
370
+ --mode copy \
371
+ --output path/to/dataset_clean \
372
+ --threshold 3
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Options reference
378
+
379
+ ### Hashing options (`clean`, `clean-inplace`, `leakage`, `leakage-fix`, `cross-label`, `cross-label-fix`)
380
+
381
+ | Flag | Default | Description |
382
+ |---|---|---|
383
+ | `--threshold N` | `3` | Max Hamming distance to count as a match. `0` = exact only, `1–3` = near-duplicates, `4+` = resized/re-compressed variants |
384
+ | `--algo NAME` | `phash` | Perceptual hash algorithm |
385
+
386
+ | Algorithm | Best for |
387
+ |---|---|
388
+ | `phash` | General use, most robust (default) |
389
+ | `ahash` | Fastest, least accurate |
390
+ | `dhash` | Gradient/edge-heavy images |
391
+ | `whash` | Wavelet-based, handles compression artifacts well |
392
+
393
+ ### Report output options (`clean`, `leakage`, `cross-label`)
394
+
395
+ | Flag | Description |
396
+ |---|---|
397
+ | `--html PATH` | Self-contained HTML gallery, no extra dependency |
398
+ | `--pdf PATH` | Visual PDF report, requires `pip install imgcheck[pdf]` |
399
+ | `--formats csv,json` | Also export report tables as CSV and/or JSON |
400
+
401
+ ### Removal mode options (`leakage-fix`, `cross-label-fix`)
402
+
403
+ | Flag | Description |
404
+ |---|---|
405
+ | `--mode inplace` | Delete flagged images from source folder (default, destructive) |
406
+ | `--mode copy` | Copy surviving images to a new clean folder (safe) |
407
+ | `--output PATH` | Required when `--mode copy` |
408
+
409
+ ---
410
+
411
+ ## Using imgcheck as a Python library
412
+
413
+ ```python
414
+ from imgcheck.stats import compute_dataset_stats
415
+ from imgcheck.clean import clean_duplicates, clean_duplicates_inplace
416
+ from imgcheck.leakage import check_train_test_leakage
417
+ from imgcheck.leakage_fix import fix_train_test_leakage
418
+ from imgcheck.cross_label import check_cross_label_duplicates
419
+ from imgcheck.cross_label_fix import fix_cross_label_duplicates
420
+
421
+ # Health check
422
+ compute_dataset_stats("dataset/", report_path="stats.xlsx")
423
+
424
+ # Find duplicates → copy survivors to new folder
425
+ clean_duplicates("dataset/", "dataset_clean/", "duplicates.xlsx", threshold=3)
426
+
427
+ # Remove duplicates in-place
428
+ clean_duplicates_inplace("dataset/", "duplicates_removed.xlsx", threshold=3)
429
+
430
+ # Detect leakage
431
+ check_train_test_leakage("train/", "test/", "leakage.xlsx", threshold=3)
432
+
433
+ # Remove leaked test images in-place
434
+ fix_train_test_leakage("train/", "test/", "leakage_removed.xlsx", mode="inplace", threshold=3)
435
+
436
+ # Remove leaked test images → copy clean set to new folder
437
+ fix_train_test_leakage("train/", "test/", "leakage_removed.xlsx", mode="copy", output_root="test_clean/")
438
+
439
+ # Detect cross-label mislabelling
440
+ check_cross_label_duplicates("dataset/", "crosslabel.xlsx", threshold=3)
441
+
442
+ # Remove cross-label duplicates → copy clean dataset to new folder
443
+ fix_cross_label_duplicates("dataset/", "crosslabel_removed.xlsx", mode="copy", output_root="dataset_clean/")
444
+ ```
445
+
446
+ ---
447
+
448
+ ## Recommended audit workflow
449
+
450
+ ```bash
451
+ # 1. Sanity check — instant, no hashing
452
+ imgcheck stats --dataset dataset/
453
+
454
+ # 2. Remove within-class duplicates (safe copy)
455
+ imgcheck clean --dataset dataset/ --output dataset_clean/ --report reports/duplicates.xlsx --html reports/duplicates.html
456
+
457
+ # 3. Remove cross-label mislabelling (safe copy)
458
+ imgcheck cross-label-fix --dataset dataset/ --mode copy --output dataset_fixed/ --report reports/crosslabel_removed.xlsx
459
+
460
+ # 4. Check and remove train/test leakage (safe copy)
461
+ imgcheck leakage-fix --train train/ --test test/ --mode copy --output test_clean/ --report reports/leakage_removed.xlsx
462
+ ```
463
+
464
+ ---
465
+
466
+ ## Project layout
467
+
468
+ ```
469
+ imgcheck/
470
+ ├── pyproject.toml
471
+ ├── README.md
472
+ └── src/imgcheck/
473
+ ├── __init__.py # package version and authors
474
+ ├── hashing.py # image discovery, perceptual hashing, Hamming distance
475
+ ├── grouping.py # Union-Find transitive duplicate clustering
476
+ ├── clean.py # within-class duplicate detection + copy or inplace removal
477
+ ├── leakage.py # train/test leakage detection (read-only)
478
+ ├── leakage_fix.py # train/test leakage removal (inplace or copy)
479
+ ├── cross_label.py # cross-label duplicate detection (read-only)
480
+ ├── cross_label_fix.py # cross-label duplicate removal (inplace or copy)
481
+ ├── stats.py # fast dataset health check (no hashing)
482
+ ├── export.py # optional CSV/JSON export alongside Excel
483
+ ├── report.py # optional PDF (fpdf2) + HTML visual reports
484
+ └── cli.py # imgcheck <command> ... entry point
485
+ ```
486
+
487
+ ---
488
+
489
+ ## Authors
490
+
491
+ **Rama Narasimha Kanduri**
492
+ kramanarasimha1@gmail.com
493
+
494
+ **CS Hari Krishna**
495
+ csharikrishna1806@gmail.com