File size: 3,107 Bytes
e3e9c11
8500b56
970030e
 
 
e3e9c11
f1cae0a
 
 
 
e3e9c11
 
 
 
 
 
970030e
 
 
e3e9c11
970030e
e3e9c11
 
970030e
e3e9c11
 
 
 
970030e
e3e9c11
970030e
 
e3e9c11
970030e
e3e9c11
970030e
 
 
 
 
e3e9c11
970030e
 
 
 
 
 
 
 
 
e3e9c11
970030e
e3e9c11
970030e
 
 
 
 
 
 
 
e3e9c11
970030e
 
e3e9c11
 
 
 
 
 
 
 
970030e
e3e9c11
 
970030e
 
 
 
e3e9c11
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import streamlit as st
import cv2
import numpy as np
from PIL import Image

def show_img(img, title="Image"):
    # Check if the image has one channel (grayscale)
    if len(img.shape) == 2:
        # Convert the grayscale image to BGR format by stacking the channels
        img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    st.image(img, caption=title, channels="BGR", use_column_width=True)

def find_contours(edged_img):
    contours, _ = cv2.findContours(edged_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)
    return contours

def sort_points(pts):
    pts = pts.reshape((4, 2))
    new_pts = np.zeros((4, 2), dtype="float32")

    sum_pts = pts.sum(axis=1)
    diff_pts = np.diff(pts, axis=1)

    new_pts[0] = pts[np.argmin(sum_pts)]
    new_pts[2] = pts[np.argmax(sum_pts)]
    new_pts[1] = pts[np.argmin(diff_pts)]
    new_pts[3] = pts[np.argmax(diff_pts)]

    return new_pts

def transform_image(image_file):
    img = cv2.imread(image_file)
    original = img.copy()
    show_img(img, "Original Image")
    (H, W) = img.shape[:2]

    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (7, 7), 0)
    edged = cv2.Canny(blur, 60, 160)
    show_img(edged, "Edged Image")
    conts = find_contours(edged.copy())
    for c in conts:
        peri = cv2.arcLength(c, True)
        aprox = cv2.approxPolyDP(c, 0.02 * peri, True)

        if len(aprox) == 4:
            larger = aprox
            break

    cv2.drawContours(img, [larger], -1, (120, 255, 0), 28)
    cv2.drawContours(img, [larger], -1, (120, 255, 0), 2)
    show_img(img, "Contours Image")

    points_larger = sort_points(larger)
    pts1 = np.float32(points_larger)
    pts2 = np.float32([[0, 0], [W, 0], [W, H], [0, H]])

    matrix = cv2.getPerspectiveTransform(pts1, pts2)
    transform = cv2.warpPerspective(original, matrix, (W, H))

    show_img(transform, "Transformed Image")
    return transform

def process_img(img):
    processed_img = cv2.resize(img, None, fx=1.6, fy=1.6, interpolation=cv2.INTER_CUBIC)
    processed_img = cv2.cvtColor(processed_img, cv2.COLOR_BGR2GRAY)
    processed_img = cv2.adaptiveThreshold(processed_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 9)
    return processed_img

# Streamlit App
st.set_page_config(page_title="Document Scanner", page_icon="📄")

st.title("Document Scanner with Computer Vision")
st.write("Upload an image of a document, and the app will scan and enhance it for you.")

uploaded_file = st.file_uploader("Choose an image...", type=["jpg", "jpeg", "png"])

if uploaded_file is not None:
    image = np.array(Image.open(uploaded_file))
    st.write("## Original Image")
    show_img(image)

    # Save the image temporarily for OpenCV processing
    temp_image_path = "temp_image.jpg"
    Image.fromarray(image).save(temp_image_path)

    # Transform and process the image
    transformed_image = transform_image(temp_image_path)
    processed_image = process_img(transformed_image)
    
    st.write("## Processed Image")
    show_img(processed_image)