ssh-AI commited on
Commit
fd99caf
·
verified ·
1 Parent(s): 417b6b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -140
app.py CHANGED
@@ -1,157 +1,99 @@
1
  import streamlit as st
2
  from PIL import Image, ImageEnhance
3
- import numpy as np
4
- import io
5
  import cv2
 
6
  from fpdf import FPDF
7
- import tempfile
8
- import os
9
 
10
- # --- Page config ---
11
- st.set_page_config(page_title="Document Scanner App", page_icon="📄", layout="centered")
12
 
13
- # --- Background image ---
14
- page_bg_img = '''
15
  <style>
16
- .stApp {
17
- background-image: url("https://images.unsplash.com/photo-1504150559088-41c99c17b7c6");
18
- background-size: cover;
19
- background-position: top left;
20
- background-repeat: no-repeat;
21
- background-attachment: fixed;
 
 
 
22
  }
23
- .block-container {
24
- background-color: rgba(255,255,255,0.8);
25
- border-radius: 10px;
26
- padding: 2rem;
27
  }
28
  </style>
29
- '''
30
  st.markdown(page_bg_img, unsafe_allow_html=True)
31
 
32
- # --- Title ---
33
- st.title("📄 Smart Document Scanner")
34
- st.write("Upload photos of ID Cards, Documents taken from mobile & get them auto-cropped, enhanced, and converted to PDF!")
35
-
36
- # --- Functions ---
37
-
38
- def auto_crop_image(image):
39
- # Convert to grayscale
40
- gray = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY)
41
- blur = cv2.GaussianBlur(gray, (5,5), 0)
42
- edged = cv2.Canny(blur, 50, 150)
43
-
44
- # Find contours
45
- contours, _ = cv2.findContours(edged, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
46
- if not contours:
47
- return image
48
-
49
- # Find the biggest contour
50
- c = max(contours, key=cv2.contourArea)
51
- x,y,w,h = cv2.boundingRect(c)
52
-
53
- # Crop and return
54
- cropped = image.crop((x,y,x+w,y+h))
55
- return cropped
56
-
57
- def enhance_image(image):
58
- enhancer = ImageEnhance.Contrast(image)
59
- image = enhancer.enhance(1.5)
60
-
61
- enhancer = ImageEnhance.Sharpness(image)
62
- image = enhancer.enhance(2.0)
63
-
64
- return image
65
-
66
- def rotate_image(image, angle):
67
- return image.rotate(angle, expand=True)
68
-
69
- def flip_image(image, mode):
70
- if mode == "Horizontal":
71
- return image.transpose(Image.FLIP_LEFT_RIGHT)
72
- elif mode == "Vertical":
73
- return image.transpose(Image.FLIP_TOP_BOTTOM)
74
- return image
75
-
76
- # --- Sidebar options ---
77
-
78
- st.sidebar.header("⚙️ Settings")
79
- crop_mode = st.sidebar.selectbox("Cropping Mode", ["Auto Crop", "Manual Crop"])
80
- apply_enhance = st.sidebar.checkbox("Enhance Image (contrast, sharpness)", value=False)
81
- rotate_angle = st.sidebar.selectbox("Rotate", [0, 90, 180, 270])
82
- flip_option = st.sidebar.selectbox("Flip", ["None", "Horizontal", "Vertical"])
83
 
84
- # --- Upload images ---
85
-
86
- uploaded_files = st.file_uploader("Upload images", type=["jpg", "jpeg", "png"], accept_multiple_files=True)
87
 
88
  if uploaded_files:
89
- st.success(f"✅ {len(uploaded_files)} file(s) uploaded successfully!")
90
- cleaned_images = []
91
-
92
- progress = st.progress(0)
93
-
94
- for idx, uploaded_file in enumerate(uploaded_files):
95
  image = Image.open(uploaded_file).convert("RGB")
96
-
97
- # Apply rotation
98
- if rotate_angle != 0:
99
- image = rotate_image(image, rotate_angle)
100
-
101
- # Apply flip
102
- if flip_option != "None":
103
- image = flip_image(image, flip_option)
104
-
105
- # Crop
106
- if crop_mode == "Auto Crop":
107
- image = auto_crop_image(image)
108
- else:
109
- # Manual Crop
110
- st.write(f"✂️ Manually crop for {uploaded_file.name}")
111
- cropped_area = st.slider(f"Adjust crop for {uploaded_file.name}", 0, 100, (5,95), key=idx)
112
- width, height = image.size
113
- left = width * cropped_area[0] // 100
114
- right = width * cropped_area[1] // 100
115
- image = image.crop((left, 0, right, height))
116
-
117
- # Enhance if selected
118
- if apply_enhance:
119
- image = enhance_image(image)
120
-
121
- st.image(image, caption=f"Processed: {uploaded_file.name}", use_container_width=True)
122
-
123
- cleaned_images.append(image)
124
-
125
- progress.progress((idx+1)/len(uploaded_files))
126
-
127
- # --- Generate PDF ---
128
- st.subheader("📄 Download PDF")
129
-
130
- if st.button("Generate PDF"):
131
- with tempfile.TemporaryDirectory() as tmpdirname:
132
- pdf = FPDF(unit="pt", format="A4")
133
- for img_idx, img in enumerate(cleaned_images):
134
- temp_img_path = os.path.join(tmpdirname, f"img_{img_idx}.jpg")
135
- img.save(temp_img_path, format="JPEG")
136
-
137
- # Calculate aspect ratio
138
- img_width, img_height = img.size
139
- page_width = pdf.w - 40 # 20 margin each side
140
- ratio = page_width / img_width
141
- new_width = page_width
142
- new_height = img_height * ratio
143
-
144
- pdf.add_page()
145
- pdf.image(temp_img_path, 20, 20, new_width, new_height)
146
-
147
- pdf_output_path = os.path.join(tmpdirname, "scanned_document.pdf")
148
- pdf.output(pdf_output_path)
149
-
150
- with open(pdf_output_path, "rb") as f:
151
- st.download_button(
152
- label="📥 Download Scanned PDF",
153
- data=f,
154
- file_name="scanned_document.pdf",
155
- mime="application/pdf"
156
- )
157
 
 
1
  import streamlit as st
2
  from PIL import Image, ImageEnhance
3
+ from io import BytesIO
4
+ import os
5
  import cv2
6
+ import numpy as np
7
  from fpdf import FPDF
8
+ from streamlit_cropper import st_cropper
 
9
 
10
+ # --- Set Page Config ---
11
+ st.set_page_config(page_title="Smart ID Scanner", page_icon="🪪", layout="centered")
12
 
13
+ # --- Add Background Style ---
14
+ page_bg_img = """
15
  <style>
16
+ body {
17
+ background: linear-gradient(to right, #ece9e6, #ffffff);
18
+ }
19
+ .stButton>button {
20
+ color: white;
21
+ background-color: #4CAF50;
22
+ border: none;
23
+ padding: 0.5em 1em;
24
+ border-radius: 5px;
25
  }
26
+ .stHeader, .stText, .stMarkdown {
27
+ color: #333333;
 
 
28
  }
29
  </style>
30
+ """
31
  st.markdown(page_bg_img, unsafe_allow_html=True)
32
 
33
+ # --- App Heading ---
34
+ st.markdown("<h1 style='text-align: center; color: #2E86C1;'>📄 Smart ID & Document Scanner</h1>", unsafe_allow_html=True)
35
+ st.write("---")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
+ # --- Upload Images ---
38
+ uploaded_files = st.file_uploader("Upload ID/Document Images 📷 (All formats supported)", type=['png', 'jpg', 'jpeg'], accept_multiple_files=True)
 
39
 
40
  if uploaded_files:
41
+ cropped_images = []
42
+ for uploaded_file in uploaded_files:
 
 
 
 
43
  image = Image.open(uploaded_file).convert("RGB")
44
+
45
+ st.subheader(f"Crop & Adjust: {uploaded_file.name}")
46
+
47
+ # --- Free style manual crop ---
48
+ crop_box = st_cropper(image, realtime_update=True, box_color='#FF9900', aspect_ratio=None)
49
+ cropped_img = crop_box.copy()
50
+
51
+ # --- Before / After Preview ---
52
+ st.write("### Preview:")
53
+ col1, col2 = st.columns(2)
54
+ with col1:
55
+ st.image(image, caption="Original", use_container_width=True)
56
+ with col2:
57
+ st.image(cropped_img, caption="Cropped", use_container_width=True)
58
+
59
+ # --- Enhancement Option ---
60
+ if st.button(f"Enhance Image: {uploaded_file.name}"):
61
+ with st.spinner('Enhancing...'):
62
+ enhancer = ImageEnhance.Contrast(cropped_img)
63
+ cropped_img = enhancer.enhance(1.5)
64
+ sharpener = ImageEnhance.Sharpness(cropped_img)
65
+ cropped_img = sharpener.enhance(2.0)
66
+ st.success("Enhanced Successfully!")
67
+ st.image(cropped_img, caption="Enhanced", use_container_width=True)
68
+
69
+ cropped_images.append(cropped_img)
70
+
71
+ st.write("---")
72
+
73
+ # --- Download Options ---
74
+ col1, col2 = st.columns(2)
75
+
76
+ # Save as PDF
77
+ with col1:
78
+ if st.button("Generate PDF 📄"):
79
+ with st.spinner('Generating PDF...'):
80
+ pdf = FPDF()
81
+ for img in cropped_images:
82
+ temp_path = f"/tmp/{np.random.randint(0,10000)}.jpg"
83
+ img.save(temp_path, format="JPEG")
84
+ pdf.add_page()
85
+ pdf.image(temp_path, x=10, y=10, w=190)
86
+ os.remove(temp_path)
87
+ pdf_output = BytesIO()
88
+ pdf.output(pdf_output)
89
+ st.download_button(label="📥 Download PDF", data=pdf_output.getvalue(), file_name="scanned_document.pdf", mime="application/pdf")
90
+
91
+ # Save as Images
92
+ with col2:
93
+ if st.button("Save as JPG/PNG 📷"):
94
+ with st.spinner('Saving Images...'):
95
+ for idx, img in enumerate(cropped_images):
96
+ img_output = BytesIO()
97
+ img.save(img_output, format='PNG')
98
+ st.download_button(label=f"📥 Download Image {idx+1}", data=img_output.getvalue(), file_name=f"scanned_image_{idx+1}.png", mime="image/png")
 
 
 
 
 
 
99