jugggernault commited on
Commit
0f02cf8
·
1 Parent(s): 43ace56

initial commit

Browse files
Files changed (4) hide show
  1. app.py +125 -0
  2. improcess.py +112 -0
  3. profile.jpeg +0 -0
  4. 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