paper-scanner 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.
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: paper-scanner
3
+ Version: 0.1.0
4
+ Summary: A utility to automatically crop and flatten photos of documents into highly detailed scanned images.
5
+ Author-email: Your Name <your.email@example.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: opencv-python-headless>=4.0
12
+ Requires-Dist: numpy>=1.0
13
+
14
+ # Paper Scanner
15
+
16
+ A command-line utility to automatically transform tilted photographs of documents into perfectly flat, highly detailed scanned images.
17
+
18
+ ## Features
19
+ - **Automatic Edge Detection**: Detects the four corners of a document.
20
+ - **Perspective Flattening**: Warps a tilted photo into a perfect top-down view.
21
+ - **Flat-Field Illumination Correction**: Removes harsh shadows and uneven lighting to generate a perfect white background while preserving the original ink colors and anti-aliasing of the text.
22
+ - **Auto-Upscaling**: Mathematically doubles the megapixels and applies unsharp masking so your text stays razor-sharp even when zoomed all the way in.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install paper-scanner
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```bash
33
+ paper-scanner path/to/your/image.jpg
34
+ ```
35
+
36
+ This will output a new file named `image_scanned.jpg` in the same directory.
@@ -0,0 +1,23 @@
1
+ # Paper Scanner
2
+
3
+ A command-line utility to automatically transform tilted photographs of documents into perfectly flat, highly detailed scanned images.
4
+
5
+ ## Features
6
+ - **Automatic Edge Detection**: Detects the four corners of a document.
7
+ - **Perspective Flattening**: Warps a tilted photo into a perfect top-down view.
8
+ - **Flat-Field Illumination Correction**: Removes harsh shadows and uneven lighting to generate a perfect white background while preserving the original ink colors and anti-aliasing of the text.
9
+ - **Auto-Upscaling**: Mathematically doubles the megapixels and applies unsharp masking so your text stays razor-sharp even when zoomed all the way in.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install paper-scanner
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ```bash
20
+ paper-scanner path/to/your/image.jpg
21
+ ```
22
+
23
+ This will output a new file named `image_scanned.jpg` in the same directory.
@@ -0,0 +1,25 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "paper-scanner"
7
+ version = "0.1.0"
8
+ authors = [
9
+ { name="Your Name", email="your.email@example.com" },
10
+ ]
11
+ description = "A utility to automatically crop and flatten photos of documents into highly detailed scanned images."
12
+ readme = "README.md"
13
+ requires-python = ">=3.7"
14
+ dependencies = [
15
+ "opencv-python-headless>=4.0",
16
+ "numpy>=1.0"
17
+ ]
18
+ classifiers = [
19
+ "Programming Language :: Python :: 3",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: OS Independent",
22
+ ]
23
+
24
+ [project.scripts]
25
+ paper-scanner = "crop_paper.cli:main"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,147 @@
1
+ import cv2
2
+ import numpy as np
3
+ import sys
4
+ import os
5
+
6
+ def order_points(pts):
7
+ # order points: top-left, top-right, bottom-right, bottom-left
8
+ rect = np.zeros((4, 2), dtype="float32")
9
+
10
+ # top-left will have the smallest sum, bottom-right the largest sum
11
+ s = pts.sum(axis=1)
12
+ rect[0] = pts[np.argmin(s)]
13
+ rect[2] = pts[np.argmax(s)]
14
+
15
+ # top-right will have the smallest difference, bottom-left the largest difference
16
+ diff = np.diff(pts, axis=1)
17
+ rect[1] = pts[np.argmin(diff)]
18
+ rect[3] = pts[np.argmax(diff)]
19
+
20
+ return rect
21
+
22
+ def four_point_transform(image, pts):
23
+ rect = order_points(pts)
24
+ (tl, tr, br, bl) = rect
25
+
26
+ # compute width of new image
27
+ widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
28
+ widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
29
+ maxWidth = max(int(widthA), int(widthB))
30
+
31
+ # compute height of new image
32
+ heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
33
+ heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
34
+ maxHeight = max(int(heightA), int(heightB))
35
+
36
+ dst = np.array([
37
+ [0, 0],
38
+ [maxWidth - 1, 0],
39
+ [maxWidth - 1, maxHeight - 1],
40
+ [0, maxHeight - 1]], dtype="float32")
41
+
42
+ M = cv2.getPerspectiveTransform(rect, dst)
43
+ warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
44
+ return warped
45
+
46
+ def crop_paper(image_path):
47
+ print(f"Processing '{image_path}'...")
48
+ image = cv2.imread(image_path)
49
+ if image is None:
50
+ print(f"Error loading {image_path}. Check if the file exists.")
51
+ return
52
+
53
+ # Resize image to speed up processing and improve contour detection
54
+ ratio = image.shape[0] / 500.0
55
+ orig = image.copy()
56
+ image = cv2.resize(image, (int(image.shape[1] / ratio), 500))
57
+
58
+ # Convert to grayscale, blur slightly to remove high frequency noise, and find edges
59
+ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
60
+ gray = cv2.GaussianBlur(gray, (5, 5), 0)
61
+ edged = cv2.Canny(gray, 75, 200)
62
+
63
+ # Find contours
64
+ contours, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
65
+ contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]
66
+
67
+ screenCnt = None
68
+ for c in contours:
69
+ peri = cv2.arcLength(c, True)
70
+ approx = cv2.approxPolyDP(c, 0.02 * peri, True)
71
+ # If our approximated contour has four points, we can assume that we have found our paper
72
+ if len(approx) == 4:
73
+ screenCnt = approx
74
+ break
75
+
76
+ if screenCnt is None:
77
+ print("Warning: Could not automatically detect the outline of the paper.")
78
+ print("Saving the original image without cropping.")
79
+ warped = orig
80
+ else:
81
+ # Apply the perspective transform to crop it out
82
+ warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)
83
+
84
+ # ---------------------------------------------------------
85
+ # NEW: Enhance the document to make it look scanned
86
+
87
+ # 1. Crop a small margin (2.5%) off the edges to firmly remove any background/table artifacts
88
+ margin_y = int(warped.shape[0] * 0.025)
89
+ margin_x = int(warped.shape[1] * 0.025)
90
+ if margin_y > 0 and margin_x > 0:
91
+ warped = warped[margin_y:-margin_y, margin_x:-margin_x]
92
+
93
+ # 2. Convert to grayscale to estimate background illumination
94
+ gray = cv2.cvtColor(warped, cv2.COLOR_BGR2GRAY)
95
+
96
+ # 3. Estimate background illumination to remove shadows
97
+ # Dilation erases the dark text, leaving just the paper's lighting
98
+ kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25, 25))
99
+ bg = cv2.morphologyEx(gray, cv2.MORPH_DILATE, kernel)
100
+ bg = cv2.GaussianBlur(bg, (25, 25), 0)
101
+
102
+ # 4. Divide EACH color channel by the background (Flat-field correction for color)
103
+ # This removes shadows but preserves the natural colors and anti-aliasing!
104
+ scanned = np.zeros_like(warped)
105
+ for i in range(3):
106
+ scanned[:, :, i] = cv2.divide(warped[:, :, i], bg, scale=255)
107
+
108
+ # 5. Apply Gamma Correction to preserve and darken thin fonts!
109
+ # Gamma > 1 pulls light grays (thin text) down into darker shades,
110
+ # while leaving pure white (255) completely unaffected.
111
+ gamma = 2.2
112
+ table = np.array([((i / 255.0) ** gamma) * 255 for i in np.arange(0, 256)]).astype("uint8")
113
+ scanned = cv2.LUT(scanned, table)
114
+
115
+ # 6. Apply a gentle contrast stretch to deepen the blacks
116
+ scanned = cv2.convertScaleAbs(scanned, alpha=1.2, beta=-10)
117
+
118
+ # 7. Ensure the background is perfectly white without destroying colored elements
119
+ gray_scanned = cv2.cvtColor(scanned, cv2.COLOR_BGR2GRAY)
120
+ scanned[gray_scanned > 210] = [255, 255, 255]
121
+
122
+ # 8. Multiply Megapixels!
123
+ # Upscale the image 2x using Lanczos interpolation (great for keeping text edges sharp)
124
+ scanned = cv2.resize(scanned, None, fx=2.0, fy=2.0, interpolation=cv2.INTER_LANCZOS4)
125
+
126
+ # 9. Apply a subtle Unsharp Mask to guarantee the text is razor-sharp when zooming in
127
+ gaussian = cv2.GaussianBlur(scanned, (0, 0), 2.0)
128
+ scanned = cv2.addWeighted(scanned, 1.5, gaussian, -0.5, 0)
129
+ # ---------------------------------------------------------
130
+
131
+ base_name = os.path.basename(image_path)
132
+ name, _ = os.path.splitext(base_name)
133
+ output_path = f"{name}_scanned.jpg"
134
+
135
+ cv2.imwrite(output_path, scanned)
136
+ print(f"Successfully saved scanned image to '{output_path}'")
137
+
138
+ def main():
139
+ if len(sys.argv) < 2:
140
+ print("Usage: paper-scanner <path_to_image>")
141
+ sys.exit(1)
142
+
143
+ target_image = sys.argv[1]
144
+ crop_paper(target_image)
145
+
146
+ if __name__ == "__main__":
147
+ main()
@@ -0,0 +1,36 @@
1
+ Metadata-Version: 2.4
2
+ Name: paper-scanner
3
+ Version: 0.1.0
4
+ Summary: A utility to automatically crop and flatten photos of documents into highly detailed scanned images.
5
+ Author-email: Your Name <your.email@example.com>
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: opencv-python-headless>=4.0
12
+ Requires-Dist: numpy>=1.0
13
+
14
+ # Paper Scanner
15
+
16
+ A command-line utility to automatically transform tilted photographs of documents into perfectly flat, highly detailed scanned images.
17
+
18
+ ## Features
19
+ - **Automatic Edge Detection**: Detects the four corners of a document.
20
+ - **Perspective Flattening**: Warps a tilted photo into a perfect top-down view.
21
+ - **Flat-Field Illumination Correction**: Removes harsh shadows and uneven lighting to generate a perfect white background while preserving the original ink colors and anti-aliasing of the text.
22
+ - **Auto-Upscaling**: Mathematically doubles the megapixels and applies unsharp masking so your text stays razor-sharp even when zoomed all the way in.
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install paper-scanner
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```bash
33
+ paper-scanner path/to/your/image.jpg
34
+ ```
35
+
36
+ This will output a new file named `image_scanned.jpg` in the same directory.
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/crop_paper/__init__.py
4
+ src/crop_paper/cli.py
5
+ src/paper_scanner.egg-info/PKG-INFO
6
+ src/paper_scanner.egg-info/SOURCES.txt
7
+ src/paper_scanner.egg-info/dependency_links.txt
8
+ src/paper_scanner.egg-info/entry_points.txt
9
+ src/paper_scanner.egg-info/requires.txt
10
+ src/paper_scanner.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ paper-scanner = crop_paper.cli:main
@@ -0,0 +1,2 @@
1
+ opencv-python-headless>=4.0
2
+ numpy>=1.0