Spaces:
Runtime error
Runtime error
Commit ·
0f02cf8
1
Parent(s): 43ace56
initial commit
Browse files- app.py +125 -0
- improcess.py +112 -0
- profile.jpeg +0 -0
- requirements.txt +4 -0
app.py
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import improcess
|
| 3 |
+
import numpy as np
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
# Fonction pour choisir un filtre et l'appliquer
|
| 7 |
+
def choose_filter(input_img, filter):
|
| 8 |
+
if input_img is None:
|
| 9 |
+
return None
|
| 10 |
+
match filter:
|
| 11 |
+
case "Gray Scale":
|
| 12 |
+
return improcess.gray_scale(input_img)
|
| 13 |
+
case "Gaussian Blur":
|
| 14 |
+
return improcess.gaussian_blur(input_img)
|
| 15 |
+
case "Binarize":
|
| 16 |
+
return improcess.binarize(input_img)
|
| 17 |
+
case "Negative":
|
| 18 |
+
return improcess.negative(input_img)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
# Fonction pour manipuler le contraste
|
| 22 |
+
def handle_contrast(output_image, contrast: list):
|
| 23 |
+
if output_image is None:
|
| 24 |
+
return None
|
| 25 |
+
for trans in contrast:
|
| 26 |
+
if trans == "Dark Contrast":
|
| 27 |
+
output_image = improcess.log_trans(output_image)
|
| 28 |
+
elif trans == "White Contrast":
|
| 29 |
+
output_image = improcess.exp_trans(output_image)
|
| 30 |
+
return output_image
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# Fonction pour egaliser l'histogramme
|
| 34 |
+
def equalize_hist(image, equalize):
|
| 35 |
+
if equalize == True:
|
| 36 |
+
return improcess.equalize(image)
|
| 37 |
+
return image
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def detect_feat(input_img, feature):
|
| 41 |
+
if input_img is None:
|
| 42 |
+
return None
|
| 43 |
+
match feature:
|
| 44 |
+
case "Edges":
|
| 45 |
+
input_img = improcess.find_edges(input_img)
|
| 46 |
+
return input_img
|
| 47 |
+
case "Contours":
|
| 48 |
+
input_img = improcess.find_contours(input_img)
|
| 49 |
+
return input_img
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
# Fonction pour réinitialiser l'image
|
| 53 |
+
def reset_img(input_img):
|
| 54 |
+
return input_img
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
# Interface Gradio
|
| 58 |
+
with gr.Blocks(theme="Zarkel/IBM_Carbon_Theme") as demo:
|
| 59 |
+
gr.Markdown(
|
| 60 |
+
"""
|
| 61 |
+
# <p align="center">Image processing lab</p>
|
| 62 |
+
"""
|
| 63 |
+
)
|
| 64 |
+
with gr.Row():
|
| 65 |
+
input_img = gr.Image(
|
| 66 |
+
"profile.jpeg", label="Original image", scale=1, interactive=True
|
| 67 |
+
)
|
| 68 |
+
with gr.Group():
|
| 69 |
+
output_img = gr.Image(
|
| 70 |
+
"profile.jpeg", label="Transformed image", scale=2, interactive=False
|
| 71 |
+
)
|
| 72 |
+
btn = gr.Button(value="Reset") # Bouton de réinitialisation
|
| 73 |
+
with gr.Row(variant="panel"):
|
| 74 |
+
with gr.Group():
|
| 75 |
+
equalize_img = gr.Checkbox(label="Equalize image")
|
| 76 |
+
gamma = gr.Slider(
|
| 77 |
+
minimum=0, maximum=1, label="Luminosity", interactive=True, value=0
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
contrast = gr.CheckboxGroup(
|
| 81 |
+
choices=["Dark Contrast", "White Contrast"], label="Contrast"
|
| 82 |
+
)
|
| 83 |
+
angle = gr.Slider(label="Rotation (deg)", minimum=0, maximum=360)
|
| 84 |
+
with gr.Group():
|
| 85 |
+
scale = gr.Slider(
|
| 86 |
+
minimum=0.1, maximum=1.5, value=1, label="Resize", info="Choose a scale"
|
| 87 |
+
)
|
| 88 |
+
filter = gr.Dropdown(
|
| 89 |
+
interactive=True,
|
| 90 |
+
label="Apply filter",
|
| 91 |
+
choices=["Gray Scale", "Binarize", "Negative", "Gaussian Blur"],
|
| 92 |
+
)
|
| 93 |
+
features = gr.Dropdown(
|
| 94 |
+
choices=["Contours", "Edges"],
|
| 95 |
+
interactive=True,
|
| 96 |
+
label="Extract feature",
|
| 97 |
+
)
|
| 98 |
+
|
| 99 |
+
# Mise à jour de l'image lorsqu'un filtre est appliqué
|
| 100 |
+
filter.change(fn=choose_filter, inputs=[input_img, filter], outputs=output_img)
|
| 101 |
+
|
| 102 |
+
# Mise à jour de l'image avec redimensionnement
|
| 103 |
+
scale.change(fn=improcess.resize, inputs=[input_img, scale], outputs=output_img)
|
| 104 |
+
|
| 105 |
+
# Bouton de réinitialisation de l'image
|
| 106 |
+
btn.click(fn=reset_img, inputs=[input_img], outputs=[output_img])
|
| 107 |
+
|
| 108 |
+
# Mise à jour de l'image avec correction de gamma
|
| 109 |
+
gamma.change(
|
| 110 |
+
fn=improcess.gamma_trans, inputs=[input_img, gamma], outputs=[output_img]
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
# Mise à jour de l'image avec contraste
|
| 114 |
+
contrast.change(
|
| 115 |
+
fn=handle_contrast, inputs=[output_img, contrast], outputs=output_img
|
| 116 |
+
)
|
| 117 |
+
# Egaliser l'histogramme de l'image
|
| 118 |
+
equalize_img.change(fn=equalize_hist, inputs=[input_img], outputs=[output_img])
|
| 119 |
+
# Effectuer une rotation de l'image
|
| 120 |
+
angle.change(fn=improcess.rotate, inputs=[input_img, angle], outputs=[output_img])
|
| 121 |
+
|
| 122 |
+
features.select(fn=detect_feat, inputs=[input_img, features], outputs=[output_img])
|
| 123 |
+
# Lancer l'application
|
| 124 |
+
if __name__ == "__main__":
|
| 125 |
+
demo.launch()
|
improcess.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import cv2 as cv
|
| 2 |
+
import numpy as np
|
| 3 |
+
from skimage import exposure
|
| 4 |
+
from scipy import signal
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def resize(image: np.ndarray, scale: float = 1.0) -> np.ndarray:
|
| 8 |
+
"""Fonction effectuant le changement d'échelle de l'image `image` selon le facteur `scale`
|
| 9 |
+
en utilisant l'interpolation linéaire.
|
| 10 |
+
|
| 11 |
+
Paramètre(s) d'entrée
|
| 12 |
+
|
| 13 |
+
image : ndarray
|
| 14 |
+
Image (niveaux de gris) d'un type reconnu par Python.
|
| 15 |
+
scale : float
|
| 16 |
+
Paramètre de changement d'échelle. Un nombre réel strictement positif
|
| 17 |
+
|
| 18 |
+
Paramètre(s) de sortie
|
| 19 |
+
----------------------
|
| 20 |
+
im_resized : ndarray
|
| 21 |
+
Image interpolé àa la nouvelle échelle, de même type que `image`
|
| 22 |
+
"""
|
| 23 |
+
|
| 24 |
+
new_height = int(image.shape[1] * scale)
|
| 25 |
+
new_width = int(image.shape[0] * scale)
|
| 26 |
+
new_shape = (new_height, new_width)
|
| 27 |
+
|
| 28 |
+
inter = cv.INTER_AREA if scale <= 1 else cv.INTER_LANCZOS4
|
| 29 |
+
im_resized = cv.resize(image, new_shape, interpolation=inter)
|
| 30 |
+
|
| 31 |
+
return im_resized.astype("uint8")
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def negative(image) -> np.ndarray:
|
| 35 |
+
neg_image = 255 - image
|
| 36 |
+
return neg_image.astype("uint8")
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def gray_scale(image):
|
| 40 |
+
return cv.cvtColor(image, cv.COLOR_RGB2GRAY).astype("uint8")
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
def binarize(image) -> np.ndarray:
|
| 44 |
+
gray_img = gray_scale(image)
|
| 45 |
+
bin_image = np.where(gray_img > 128, 255, 0)
|
| 46 |
+
return bin_image.astype("uint8")
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def log_trans(image) -> np.ndarray:
|
| 50 |
+
c = 255 / np.log(1 + np.max(image))
|
| 51 |
+
|
| 52 |
+
log_img = c * np.log(image + 1)
|
| 53 |
+
return log_img.astype("uint8")
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def exp_trans(image) -> np.ndarray:
|
| 57 |
+
image = image.astype(np.float32)
|
| 58 |
+
|
| 59 |
+
normalized_img = image / 255.0
|
| 60 |
+
|
| 61 |
+
exp_img = np.exp(normalized_img) - 1
|
| 62 |
+
|
| 63 |
+
exp_img = 255 * exp_img / np.max(exp_img)
|
| 64 |
+
|
| 65 |
+
return exp_img.astype("uint8")
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def gamma_trans(image, gamma):
|
| 69 |
+
gamma *= 5
|
| 70 |
+
gamma = 5 - gamma
|
| 71 |
+
gamma_img = image / 255
|
| 72 |
+
gamma_img = np.power(gamma_img, gamma) * 225
|
| 73 |
+
return gamma_img.astype("uint8")
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def equalize(image):
|
| 77 |
+
return exposure.equalize_hist(image).astype("uint8")
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def gaussian_blur(image):
|
| 81 |
+
return cv.GaussianBlur(image, ksize=(5, 5), sigmaX=1.0).astype("uint8")
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
def rotate(img, angle):
|
| 85 |
+
(height, width) = img.shape[:2]
|
| 86 |
+
|
| 87 |
+
rotPoint = (width // 2, height // 2)
|
| 88 |
+
rotMat = cv.getRotationMatrix2D(rotPoint, angle, 1.0)
|
| 89 |
+
dimensions = (width, height)
|
| 90 |
+
return cv.warpAffine(img, rotMat, dimensions)
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def find_contours(image):
|
| 94 |
+
gray_image = gray_scale(image)
|
| 95 |
+
_, thresh = cv.threshold(gray_image, 125, 255, cv.THRESH_BINARY)
|
| 96 |
+
contours, _ = cv.findContours(thresh, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)
|
| 97 |
+
blank = np.zeros(image.shape, dtype="uint8")
|
| 98 |
+
contour_img = cv.drawContours(blank, contours, -1, (255, 255, 255), 2)
|
| 99 |
+
return contour_img
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def find_edges(image):
|
| 103 |
+
gray_image = gray_scale(image)
|
| 104 |
+
return cv.Canny(gray_image, 125, 175).astype("uint8")
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
if __name__ == "__main__":
|
| 108 |
+
image = cv.imread("profile.jpeg")
|
| 109 |
+
|
| 110 |
+
cv.imshow("normal", image)
|
| 111 |
+
cv.imshow("Gamma", find_contours(image))
|
| 112 |
+
cv.waitKey(0)
|
profile.jpeg
ADDED
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
opencv-python-headless
|
| 3 |
+
scikit-image
|
| 4 |
+
numpy
|