|
import cv2 |
|
import numpy as np |
|
import scipy as sp |
|
import scipy.sparse.linalg |
|
from numba import jit, prange |
|
import gradio as gr |
|
|
|
@jit(nopython=True) |
|
def neighbours(i, j, max_i, max_j): |
|
pairs = [] |
|
for n in [-1, 1]: |
|
if 0 <= i+n <= max_i: |
|
pairs.append((i+n, j)) |
|
if 0 <= j+n <= max_j: |
|
pairs.append((i, j+n)) |
|
return pairs |
|
|
|
@jit(nopython=True) |
|
def build_poisson_matrix(img_h, img_w, alpha): |
|
im2var = np.arange(img_h * img_w).reshape(img_h, img_w) |
|
A_data = [] |
|
A_row = [] |
|
A_col = [] |
|
b = np.zeros(img_h*img_w*5) |
|
|
|
e = 0 |
|
for y in range(img_h): |
|
for x in range(img_w): |
|
A_data.append(1) |
|
A_row.append(e) |
|
A_col.append(im2var[y, x]) |
|
e += 1 |
|
|
|
for n_y, n_x in neighbours(y, x, img_h-1, img_w-1): |
|
A_data.append(1) |
|
A_row.append(e) |
|
A_col.append(im2var[y, x]) |
|
|
|
A_data.append(-1) |
|
A_row.append(e) |
|
A_col.append(im2var[n_y, n_x]) |
|
|
|
e += 1 |
|
|
|
return A_data, A_row, A_col, b, e |
|
|
|
@jit(nopython=True, parallel=True) |
|
def fill_b_vector(b, img, alpha, img_h, img_w): |
|
e = 0 |
|
for y in prange(img_h): |
|
for x in range(img_w): |
|
b[e] = img[y, x] |
|
e += 1 |
|
|
|
for n_y, n_x in neighbours(y, x, img_h-1, img_w-1): |
|
b[e] = alpha * (img[y, x] - img[n_y, n_x]) |
|
e += 1 |
|
|
|
def poisson_sharpening(img: np.ndarray, alpha: float) -> np.ndarray: |
|
""" |
|
Returns a sharpened image with strength of alpha. |
|
:param img: the image |
|
:param alpha: edge threshold and gradient scaler |
|
""" |
|
img_h, img_w = img.shape[:2] |
|
|
|
A_data, A_row, A_col, b, e = build_poisson_matrix(img_h, img_w, alpha) |
|
fill_b_vector(b, img, alpha, img_h, img_w) |
|
|
|
A = sp.sparse.csr_matrix((A_data, (A_row, A_col)), 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) |
|
|
|
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 = np.zeros(img.shape) |
|
for b in range(3): |
|
sharpen_img[:,:,b] = poisson_sharpening(img[:,:,b], alpha) |
|
|
|
return (sharpen_img * 255).astype(np.uint8) |
|
|
|
|
|
examples = [ |
|
["img1.jpg", 9.0], |
|
["img2.PNG", 7.0], |
|
] |
|
|
|
|
|
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() |