File size: 2,978 Bytes
38d65f9
 
0f5237c
 
6ebce6b
38d65f9
 
6ebce6b
 
 
 
 
 
 
 
 
 
 
 
0f5237c
6ebce6b
 
 
 
 
0f5237c
 
6ebce6b
 
 
 
0f5237c
6ebce6b
0f5237c
6ebce6b
 
0f5237c
 
 
6ebce6b
 
 
 
0f5237c
 
 
6ebce6b
 
 
 
 
 
 
 
 
 
0f5237c
38d65f9
6ebce6b
0f5237c
 
 
 
6ebce6b
 
 
 
 
 
 
0f5237c
 
38d65f9
 
0f5237c
6ebce6b
0f5237c
38d65f9
04fbf12
38d65f9
0f5237c
 
38d65f9
 
 
 
 
 
 
0f5237c
38d65f9
 
0f5237c
38d65f9
 
 
 
 
 
 
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
95
96
97
98
99
100
import cv2
import numpy as np
import scipy as sp
import scipy.sparse.linalg
from numba import njit, prange
import gradio as gr

@njit
def neighbours(y, x, max_y, max_x):
    neighbors = []
    if y > 0:
        neighbors.append((y-1, x))
    if y < max_y:
        neighbors.append((y+1, x))
    if x > 0:
        neighbors.append((y, x-1))
    if x < max_x:
        neighbors.append((y, x+1))
    return neighbors

@njit
def poisson_sharpening(img, alpha):
    img_h, img_w = img.shape
    img_s = img.copy()
    
    im2var = np.arange(img_h * img_w).reshape(img_h, img_w)
    
    A_data = np.zeros(img_h * img_w * 5, dtype=np.float64)
    A_row = np.zeros(img_h * img_w * 5, dtype=np.int32)
    A_col = np.zeros(img_h * img_w * 5, dtype=np.int32)
    b = np.zeros(img_h * img_w * 5, dtype=np.float64)
    
    return _poisson_sharpening_inner(img_s, alpha, im2var, A_data, A_row, A_col, b, img_h, img_w)

@njit(parallel=True)
def _poisson_sharpening_inner(img_s, alpha, im2var, A_data, A_row, A_col, b, img_h, img_w):
    e = 0
    for y in prange(img_h):
        for x in range(img_w):
            A_data[e] = 1
            A_row[e] = e
            A_col[e] = im2var[y, x]
            b[e] = img_s[y, x]
            e += 1
            
            for n_y, n_x in neighbours(y, x, img_h-1, img_w-1):
                A_data[e] = 1
                A_row[e] = e
                A_col[e] = im2var[y, x]
                e += 1
                
                A_data[e] = -1
                A_row[e] = e - 1
                A_col[e] = im2var[n_y, n_x]
                
                b[e-1] = alpha * (img_s[y, x] - img_s[n_y, n_x])
                e += 1
    
    A = sp.sparse.csr_matrix((A_data[:e], (A_row[:e], A_col[:e])), shape=(e, img_h * img_w))
    v = sp.sparse.linalg.lsqr(A, b[:e])[0]

    return np.clip(v.reshape(img_h, img_w), 0, 1)

@njit(parallel=True)
def sharpen_image_channels(img, alpha):
    sharpen_img = np.zeros_like(img)
    for b in prange(3):
        sharpen_img[:,:,b] = poisson_sharpening(img[:,:,b], alpha)
    return sharpen_img

def get_image(img):
    return cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype('float32') / 255.0

def sharpen_image(input_img, alpha):
    img = get_image(input_img)
    sharpen_img = sharpen_image_channels(img, alpha)
    return (sharpen_img * 255).astype(np.uint8)

# Create examples list
examples = [
    ["img1.jpg", 9.0],
    ["img2.PNG", 7.0],
]

# Create the Gradio interface
iface = gr.Interface(
    fn=sharpen_image,
    inputs=[
        gr.Image(label="Input Image", type="numpy"),
        gr.Slider(minimum=1.0, maximum=15.0, step=0.01, value=9.0, label="Sharpening Strength (alpha)")
    ],
    outputs=gr.Image(label="Sharpened Image"),
    title="Poisson Image Sharpening",
    description="Upload an image or choose from the examples, then adjust the sharpening strength to enhance edges and details.",
    theme='bethecloud/storj_theme',
    examples=examples,
    cache_examples=True
)

iface.launch()