ankanpy commited on
Commit
d60ad95
·
1 Parent(s): 6c0d323

updated app.py

Browse files
Files changed (3) hide show
  1. app.py +186 -141
  2. app2.py +157 -0
  3. requirements.txt +1 -1
app.py CHANGED
@@ -1,157 +1,202 @@
1
- """Application to demo inpainting, Median and Bilateral Blur using streamlit.
2
-
3
- Run using: streamlit run 10_04_image_restoration_app.py
4
- """
5
-
6
  import streamlit as st
7
- import pathlib
8
- from streamlit_drawable_canvas import st_canvas
9
- import cv2
10
  import numpy as np
11
- import io
12
- import base64
13
  from PIL import Image
 
 
 
14
 
15
 
16
- # # Function to create a download link for output image
17
- # def get_image_download_link(img, filename, text):
18
- # """Generates a link to download a particular image file."""
19
- # buffered = io.BytesIO()
20
- # img.save(buffered, format='JPEG')
21
- # img_str = base64.b64encode(buffered.getvalue()).decode()
22
- # href = f'<a href="data:file/txt;base64,{img_str}" download="{filename}">{text}</a>'
23
- # return href
24
 
25
 
26
- # Set title.
27
- st.sidebar.title('Image Restoration App with OpenCV')
 
 
 
28
 
29
- # Description
30
- st.sidebar.text('Upload an image and apply various restoration techniques.')
31
 
 
 
 
 
 
32
 
33
- # Specify canvas parameters in application
34
- uploaded_file = st.sidebar.file_uploader("Upload Image to restore:", type=["png", "jpg"])
35
- image = None
36
- res = None
37
 
38
- if uploaded_file is not None:
 
 
39
 
40
- # Convert the file to an opencv image.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
42
  image = cv2.imdecode(file_bytes, 1)
43
- # Display the uploaded image
44
- st.subheader("Original Image")
45
- st.image(image[:, :, ::-1])
46
- # Display a selection box for choosing the filter to apply.
47
- option = st.sidebar.selectbox('Median or Bilateral Blur or Inpaint?', ('None', 'Median Blur', 'Bilateral Blur', 'Image Inpaint'))
48
-
49
- if option == 'Median Blur':
50
- ksize = st.sidebar.slider("ksize: ", 3, 15, 5, 2)
51
- image = cv2.medianBlur(image, ksize)
52
- res=image[:,:,::-1]
53
- st.subheader("Median Blurred Image")
54
- st.image(res)
55
- # Display download button
56
- result = Image.fromarray(res)
57
- buffered = io.BytesIO()
58
- result.save(buffered, format="PNG")
59
- img_bytes = buffered.getvalue()
60
- st.download_button(label='Download Output', data=img_bytes, file_name='median_blur_output.png', mime='image/png')
61
-
62
- elif option == 'Bilateral Blur':
63
- dia = st.sidebar.slider("diameter: ", 1, 50, 20)
64
- sigmaColor = st.sidebar.slider("sigmaColor: ", 0, 250, 200, 10)
65
- sigmaSpace = st.sidebar.slider("sigmaSpace: ", 0, 250, 100, 10)
66
- image = cv2.bilateralFilter(image, dia, sigmaColor, sigmaSpace)
67
- res=image[:,:,::-1]
68
- st.subheader("Bilateral Blurred Image")
69
- st.image(res)
70
- # Display download button
71
- result = Image.fromarray(res)
72
- buffered = io.BytesIO()
73
- result.save(buffered, format="PNG")
74
- img_bytes = buffered.getvalue()
75
- st.download_button(label='Download Output', data=img_bytes, file_name='bilateral_blur_output.png', mime='image/png')
76
-
77
- elif option == 'Image Inpaint':
78
-
79
- stroke_width = st.sidebar.slider("Stroke width: ", 1, 25, 5)
80
- h, w = image.shape[:2]
81
- if w > 800:
82
- h_, w_ = int(h * 800 / w), 800
83
- else:
84
- h_, w_ = h, w
85
-
86
- # Create a canvas component.
87
- st.subheader("Draw over the areas you want to inpaint:")
88
- canvas_result = st_canvas(
89
- fill_color='white',
90
- stroke_width=stroke_width,
91
- stroke_color='black',
92
- background_image=Image.open(uploaded_file).resize((h_, w_)),
93
- update_streamlit=True,
94
- height=h_,
95
- width=w_,
96
- drawing_mode='freedraw',
97
- key="canvas",
98
  )
99
- stroke = canvas_result.image_data
100
-
101
- if stroke is not None:
102
-
103
- if st.sidebar.checkbox('show mask'):
104
- st.subheader("Mask")
105
- st.image(stroke)
106
-
107
- mask = cv2.split(stroke)[3]
108
- mask = np.uint8(mask)
109
- mask = cv2.resize(mask, (w, h))
110
-
111
- st.sidebar.caption('Happy with the selection?')
112
- option = st.sidebar.selectbox('Mode', ['None', 'Telea', 'NS', 'Compare both'])
113
-
114
- if option == 'Telea':
115
- st.subheader('Result of Telea')
116
- res = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_TELEA)[:,:,::-1]
117
- st.image(res)
118
- # Display download button
119
- result = Image.fromarray(res)
120
- buffered = io.BytesIO()
121
- result.save(buffered, format="PNG")
122
- img_bytes = buffered.getvalue()
123
- st.download_button(label='Download Output', data=img_bytes, file_name='inpaint_telea_output.png', mime='image/png')
124
- elif option == 'Compare both':
125
- col1, col2 = st.columns(2)
126
- res1 = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_TELEA)[:,:,::-1]
127
- res2 = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_NS)[:,:,::-1]
128
- with col1:
129
- st.subheader('Result of Telea')
130
- st.image(res1)
131
- # Display download button
132
- result1 = Image.fromarray(res1)
133
- buffered1 = io.BytesIO()
134
- result1.save(buffered1, format="PNG")
135
- img_bytes1 = buffered1.getvalue()
136
- st.download_button(label='Download Output', data=img_bytes1, file_name='inpaint_telea_output.png', mime='image/png')
137
- with col2:
138
- st.subheader('Result of NS')
139
- st.image(res2)
140
- # Display download button
141
- result2 = Image.fromarray(res2)
142
- buffered2 = io.BytesIO()
143
- result2.save(buffered2, format="PNG")
144
- img_bytes2 = buffered2.getvalue()
145
- st.download_button(label='Download Output', data=img_bytes2, file_name='inpaint_ns_output.png', mime='image/png')
146
- elif option == 'NS':
147
- st.subheader('Result of NS')
148
- res = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_NS)[:,:,::-1]
149
- st.image(res)
150
- # Display download button
151
- result = Image.fromarray(res)
152
- buffered = io.BytesIO()
153
- result.save(buffered, format="PNG")
154
- img_bytes = buffered.getvalue()
155
- st.download_button(label='Download Output', data=img_bytes, file_name='inpaint_ns_output.png', mime='image/png')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  else:
157
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
 
 
 
2
  import numpy as np
3
+ import cv2
 
4
  from PIL import Image
5
+ import io
6
+ import time
7
+ from streamlit_drawable_canvas import st_canvas
8
 
9
 
10
+ # Helper functions
11
+ def np_to_pil(np_img_bgr):
12
+ if len(np_img_bgr.shape) == 2:
13
+ return Image.fromarray(np_img_bgr)
14
+ else:
15
+ return Image.fromarray(np_img_bgr[..., ::-1])
 
 
16
 
17
 
18
+ def pil_to_np(pil_img):
19
+ np_img_rgb = np.array(pil_img)
20
+ if np_img_rgb.shape[-1] == 4:
21
+ np_img_rgb = np_img_rgb[..., :3]
22
+ return np_img_rgb[..., ::-1]
23
 
 
 
24
 
25
+ def download_button_img(np_img_bgr, label, filename):
26
+ img = np_to_pil(np_img_bgr)
27
+ buf = io.BytesIO()
28
+ img.save(buf, format="PNG")
29
+ st.download_button(label, data=buf.getvalue(), file_name=filename, mime="image/png")
30
 
 
 
 
 
31
 
32
+ # Set page config
33
+ st.set_page_config(page_title="Image Restoration App", layout="wide")
34
+ st.title("Image Restoration App")
35
 
36
+ # Upload section
37
+ st.sidebar.title("Upload Image")
38
+ uploaded_file = st.sidebar.file_uploader("Choose an image", type=["png", "jpg", "jpeg"])
39
+
40
+
41
+ if "orig_image" not in st.session_state:
42
+ st.session_state.orig_image = None
43
+ if "current_image" not in st.session_state:
44
+ st.session_state.current_image = None
45
+ if "inpaint_result" not in st.session_state:
46
+ st.session_state.inpaint_result = None
47
+ if "canvas_result" not in st.session_state:
48
+ st.session_state.canvas_result = None
49
+
50
+ if uploaded_file:
51
  file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
52
  image = cv2.imdecode(file_bytes, 1)
53
+ st.session_state.orig_image = image
54
+ st.session_state.current_image = image.copy()
55
+ st.session_state.inpaint_result = None
56
+
57
+ if st.session_state.orig_image is None:
58
+ st.info("Upload an image to get started.")
59
+ st.stop()
60
+
61
+ # Tabs
62
+ tabs = st.tabs(["Filters", "Inpainting", "Compare"])
63
+
64
+ # FILTERS TAB
65
+ with tabs[0]:
66
+ col1, col2 = st.columns([1, 2])
67
+ with col1:
68
+ st.subheader("Filters")
69
+ filter_type = st.selectbox(
70
+ "Choose filter:",
71
+ ["None", "Gaussian", "Median", "Bilateral", "Brightness/Contrast", "Grayscale"],
72
+ key="filter",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  )
74
+
75
+ if filter_type == "Gaussian":
76
+ ksize = st.slider("Kernel Size", 1, 31, 5, step=2, key="gauss_ksize")
77
+ sigma = st.slider("Sigma X", 0.0, 10.0, 2.0, key="gauss_sigma")
78
+ elif filter_type == "Median":
79
+ ksize = st.slider("Kernel Size", 1, 31, 5, step=2, key="median_ksize")
80
+ elif filter_type == "Bilateral":
81
+ d = st.slider("Diameter", 1, 30, 9, key="bilateral_d")
82
+ sigmaColor = st.slider("Sigma Color", 1, 150, 75, key="bilateral_color")
83
+ sigmaSpace = st.slider("Sigma Space", 1, 150, 75, key="bilateral_space")
84
+ elif filter_type == "Brightness/Contrast":
85
+ brightness = st.slider("Brightness", -100, 100, 0, key="brightness")
86
+ contrast = st.slider("Contrast", -100, 100, 0, key="contrast")
87
+
88
+ if st.button("Apply Filter", key="apply_filter"):
89
+ img = st.session_state.current_image.copy()
90
+ if filter_type == "Gaussian":
91
+ img = cv2.GaussianBlur(img, (ksize, ksize), sigma)
92
+ elif filter_type == "Median":
93
+ img = cv2.medianBlur(img, ksize)
94
+ elif filter_type == "Bilateral":
95
+ img = cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace)
96
+ elif filter_type == "Brightness/Contrast":
97
+ img = cv2.convertScaleAbs(img, alpha=1 + contrast / 100.0, beta=brightness)
98
+ elif filter_type == "Grayscale":
99
+ img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
100
+ st.session_state.current_image = img
101
+ st.session_state.inpaint_result = None
102
+
103
+ if st.button("Reset Image", key="reset_filter"):
104
+ st.session_state.current_image = st.session_state.orig_image.copy()
105
+ st.session_state.inpaint_result = None
106
+
107
+ with col2:
108
+ st.subheader("Image Preview")
109
+ img = st.session_state.current_image
110
+ st.image(img if len(img.shape) == 2 else img[..., ::-1], use_container_width=True)
111
+
112
+ # INPAINTING TAB
113
+ with tabs[1]:
114
+ col1, col2, col3 = st.columns([1, 1.5, 1.5])
115
+
116
+ with col1:
117
+ st.subheader("Inpainting Settings")
118
+ stroke_width = st.slider("Stroke Width", 1, 25, 5, key="stroke")
119
+ method = st.selectbox("Inpainting Method", ["Telea", "NS"], key="inpaint_method")
120
+
121
+ if st.button("Apply Inpaint", key="apply_inpaint"):
122
+ canvas = st.session_state.get("canvas_result")
123
+ if canvas and canvas.image_data is not None:
124
+ mask_rgba = canvas.image_data
125
+ if mask_rgba.shape[-1] == 4:
126
+ mask = mask_rgba[..., 3]
127
+ h, w = st.session_state.current_image.shape[:2]
128
+ mask = cv2.resize(mask, (w, h))
129
+ mask = (mask > 0).astype(np.uint8) * 255
130
+ flag = cv2.INPAINT_TELEA if method == "Telea" else cv2.INPAINT_NS
131
+ result = cv2.inpaint(st.session_state.current_image, mask, 3, flag)
132
+ st.session_state.inpaint_result = result
133
+
134
+ if st.button("Reset to Original", key="reset_inpaint"):
135
+ st.session_state.current_image = st.session_state.orig_image.copy()
136
+ st.session_state.inpaint_result = None
137
+ st.markdown("---")
138
+ if st.button("Reset Canvas"):
139
+ st.session_state.canvas_key = f"canvas_{int(time.time())}"
140
+
141
+ with col2:
142
+ st.subheader("Draw Mask")
143
+ h, w = st.session_state.current_image.shape[:2]
144
+ max_width = 500
145
+ scale = min(1.0, max_width / w)
146
+ canvas_w, canvas_h = int(w * scale), int(h * scale)
147
+
148
+ show_mask = st.checkbox("Show Mask Preview", key="show_mask")
149
+
150
+ if "canvas_key" not in st.session_state:
151
+ st.session_state.canvas_key = "canvas"
152
+
153
+ if not show_mask:
154
+ pil_bg = np_to_pil(st.session_state.current_image).resize((canvas_w, canvas_h))
155
+ canvas = st_canvas(
156
+ fill_color="white",
157
+ stroke_width=stroke_width,
158
+ stroke_color="black",
159
+ background_image=pil_bg,
160
+ update_streamlit=True,
161
+ height=canvas_h,
162
+ width=canvas_w,
163
+ drawing_mode="freedraw",
164
+ key=st.session_state.canvas_key,
165
+ )
166
+ st.session_state.canvas_result = canvas
167
+ else:
168
+ canvas = st.session_state.get("canvas_result")
169
+ if canvas and canvas.image_data is not None:
170
+ mask = canvas.image_data[..., 3] if canvas.image_data.shape[-1] == 4 else None
171
+ if mask is not None:
172
+ mask = cv2.resize(mask, (w, h))
173
+ mask = (mask > 0).astype(np.uint8) * 255
174
+ st.image(mask, caption="Inpainting Mask", use_container_width=True)
175
+
176
+ with col3:
177
+ st.subheader("Inpainting Result")
178
+ result = st.session_state.inpaint_result
179
+ if result is not None:
180
+ st.image(result[..., ::-1], use_container_width=True)
181
+ download_button_img(result, "Download Inpainted Image", "inpainted_result.png")
182
  else:
183
+ st.info("Draw a mask and apply inpainting to see result.")
184
+
185
+ # COMPARE TAB
186
+ with tabs[2]:
187
+ col1, col2 = st.columns(2)
188
+ with col1:
189
+ st.subheader("Original Image")
190
+ orig = st.session_state.orig_image
191
+ st.image(orig[..., ::-1], use_container_width=True)
192
+ download_button_img(orig, "Download Original", "original.png")
193
+
194
+ with col2:
195
+ st.subheader("Processed Image")
196
+ current = (
197
+ st.session_state.inpaint_result
198
+ if st.session_state.inpaint_result is not None
199
+ else st.session_state.current_image
200
+ )
201
+ st.image(current if len(current.shape) == 2 else current[..., ::-1], use_container_width=True)
202
+ download_button_img(current, "Download Current", "current.png")
app2.py ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Application to demo inpainting, Median and Bilateral Blur using streamlit.
2
+
3
+ Run using: streamlit run 10_04_image_restoration_app.py
4
+ """
5
+
6
+ import streamlit as st
7
+ import pathlib
8
+ from streamlit_drawable_canvas import st_canvas
9
+ import cv2
10
+ import numpy as np
11
+ import io
12
+ import base64
13
+ from PIL import Image
14
+
15
+
16
+ # # Function to create a download link for output image
17
+ # def get_image_download_link(img, filename, text):
18
+ # """Generates a link to download a particular image file."""
19
+ # buffered = io.BytesIO()
20
+ # img.save(buffered, format='JPEG')
21
+ # img_str = base64.b64encode(buffered.getvalue()).decode()
22
+ # href = f'<a href="data:file/txt;base64,{img_str}" download="{filename}">{text}</a>'
23
+ # return href
24
+
25
+
26
+ # Set title.
27
+ st.sidebar.title('Image Restoration App with OpenCV')
28
+
29
+ # Description
30
+ st.sidebar.text('Upload an image and apply various restoration techniques.')
31
+
32
+
33
+ # Specify canvas parameters in application
34
+ uploaded_file = st.sidebar.file_uploader("Upload Image to restore:", type=["png", "jpg"])
35
+ image = None
36
+ res = None
37
+
38
+ if uploaded_file is not None:
39
+
40
+ # Convert the file to an opencv image.
41
+ file_bytes = np.asarray(bytearray(uploaded_file.read()), dtype=np.uint8)
42
+ image = cv2.imdecode(file_bytes, 1)
43
+ # Display the uploaded image
44
+ st.subheader("Original Image")
45
+ st.image(image[:, :, ::-1])
46
+ # Display a selection box for choosing the filter to apply.
47
+ option = st.sidebar.selectbox('Median or Bilateral Blur or Inpaint?', ('None', 'Median Blur', 'Bilateral Blur', 'Image Inpaint'))
48
+
49
+ if option == 'Median Blur':
50
+ ksize = st.sidebar.slider("ksize: ", 3, 15, 5, 2)
51
+ image = cv2.medianBlur(image, ksize)
52
+ res=image[:,:,::-1]
53
+ st.subheader("Median Blurred Image")
54
+ st.image(res)
55
+ # Display download button
56
+ result = Image.fromarray(res)
57
+ buffered = io.BytesIO()
58
+ result.save(buffered, format="PNG")
59
+ img_bytes = buffered.getvalue()
60
+ st.download_button(label='Download Output', data=img_bytes, file_name='median_blur_output.png', mime='image/png')
61
+
62
+ elif option == 'Bilateral Blur':
63
+ dia = st.sidebar.slider("diameter: ", 1, 50, 20)
64
+ sigmaColor = st.sidebar.slider("sigmaColor: ", 0, 250, 200, 10)
65
+ sigmaSpace = st.sidebar.slider("sigmaSpace: ", 0, 250, 100, 10)
66
+ image = cv2.bilateralFilter(image, dia, sigmaColor, sigmaSpace)
67
+ res=image[:,:,::-1]
68
+ st.subheader("Bilateral Blurred Image")
69
+ st.image(res)
70
+ # Display download button
71
+ result = Image.fromarray(res)
72
+ buffered = io.BytesIO()
73
+ result.save(buffered, format="PNG")
74
+ img_bytes = buffered.getvalue()
75
+ st.download_button(label='Download Output', data=img_bytes, file_name='bilateral_blur_output.png', mime='image/png')
76
+
77
+ elif option == 'Image Inpaint':
78
+
79
+ stroke_width = st.sidebar.slider("Stroke width: ", 1, 25, 5)
80
+ h, w = image.shape[:2]
81
+ if w > 800:
82
+ h_, w_ = int(h * 800 / w), 800
83
+ else:
84
+ h_, w_ = h, w
85
+
86
+ # Create a canvas component.
87
+ st.subheader("Draw over the areas you want to inpaint:")
88
+ canvas_result = st_canvas(
89
+ fill_color='white',
90
+ stroke_width=stroke_width,
91
+ stroke_color='black',
92
+ background_image=Image.open(uploaded_file).resize((h_, w_)),
93
+ update_streamlit=True,
94
+ height=h_,
95
+ width=w_,
96
+ drawing_mode='freedraw',
97
+ key="canvas",
98
+ )
99
+ stroke = canvas_result.image_data
100
+
101
+ if stroke is not None:
102
+
103
+ if st.sidebar.checkbox('show mask'):
104
+ st.subheader("Mask")
105
+ st.image(stroke)
106
+
107
+ mask = cv2.split(stroke)[3]
108
+ mask = np.uint8(mask)
109
+ mask = cv2.resize(mask, (w, h))
110
+
111
+ st.sidebar.caption('Happy with the selection?')
112
+ option = st.sidebar.selectbox('Mode', ['None', 'Telea', 'NS', 'Compare both'])
113
+
114
+ if option == 'Telea':
115
+ st.subheader('Result of Telea')
116
+ res = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_TELEA)[:,:,::-1]
117
+ st.image(res)
118
+ # Display download button
119
+ result = Image.fromarray(res)
120
+ buffered = io.BytesIO()
121
+ result.save(buffered, format="PNG")
122
+ img_bytes = buffered.getvalue()
123
+ st.download_button(label='Download Output', data=img_bytes, file_name='inpaint_telea_output.png', mime='image/png')
124
+ elif option == 'Compare both':
125
+ col1, col2 = st.columns(2)
126
+ res1 = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_TELEA)[:,:,::-1]
127
+ res2 = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_NS)[:,:,::-1]
128
+ with col1:
129
+ st.subheader('Result of Telea')
130
+ st.image(res1)
131
+ # Display download button
132
+ result1 = Image.fromarray(res1)
133
+ buffered1 = io.BytesIO()
134
+ result1.save(buffered1, format="PNG")
135
+ img_bytes1 = buffered1.getvalue()
136
+ st.download_button(label='Download Output', data=img_bytes1, file_name='inpaint_telea_output.png', mime='image/png')
137
+ with col2:
138
+ st.subheader('Result of NS')
139
+ st.image(res2)
140
+ # Display download button
141
+ result2 = Image.fromarray(res2)
142
+ buffered2 = io.BytesIO()
143
+ result2.save(buffered2, format="PNG")
144
+ img_bytes2 = buffered2.getvalue()
145
+ st.download_button(label='Download Output', data=img_bytes2, file_name='inpaint_ns_output.png', mime='image/png')
146
+ elif option == 'NS':
147
+ st.subheader('Result of NS')
148
+ res = cv2.inpaint(src=image, inpaintMask=mask, inpaintRadius=3, flags=cv2.INPAINT_NS)[:,:,::-1]
149
+ st.image(res)
150
+ # Display download button
151
+ result = Image.fromarray(res)
152
+ buffered = io.BytesIO()
153
+ result.save(buffered, format="PNG")
154
+ img_bytes = buffered.getvalue()
155
+ st.download_button(label='Download Output', data=img_bytes, file_name='inpaint_ns_output.png', mime='image/png')
156
+ else:
157
+ pass
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
  numpy
2
- streamlit
3
  streamlit_drawable_canvas
4
  opencv-python-headless
5
  pillow
 
1
  numpy
2
+ streamlit==1.40.0
3
  streamlit_drawable_canvas
4
  opencv-python-headless
5
  pillow