streamlit

Форк
0
/
images.py 
316 строк · 9.3 Кб
1
# Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2024)
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#     http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

15
"""St.image example."""
16

17
import io
18
import random
19

20
import numpy as np
21
from PIL import Image, ImageDraw
22

23
import streamlit as st
24

25

26
class StreamlitImages(object):
27
    def __init__(self, size=200, step=10):
28
        self._size = size
29
        self._step = step
30
        self._half = self._size / 2
31
        self._data = {}
32

33
        self.create_image()
34
        self.generate_image_types()
35
        self.generate_image_channel_data()
36
        self.generate_bgra_image()
37
        self.generate_gif()
38
        self.generate_pseudorandom_image()
39
        self.generate_gray_image()
40
        self.save()
41

42
    def create_image(self):
43
        # Create a new image
44
        self._image = Image.new("RGB", (self._size, self._size))
45
        d = ImageDraw.Draw(self._image)
46

47
        # Draw a red square
48
        d.rectangle(
49
            [
50
                (self._step, self._step),
51
                (self._half - self._step, self._half - self._step),
52
            ],
53
            fill="red",
54
            outline=None,
55
            width=0,
56
        )
57

58
        # Draw a green circle.  In PIL, green is 00800, lime is 00ff00
59
        d.ellipse(
60
            [
61
                (self._half + self._step, self._step),
62
                (self._size - self._step, self._half - self._step),
63
            ],
64
            fill="lime",
65
            outline=None,
66
            width=0,
67
        )
68

69
        # Draw a blue triangle
70
        d.polygon(
71
            [
72
                (self._half / 2, self._half + self._step),
73
                (self._half - self._step, self._size - self._step),
74
                (self._step, self._size - self._step),
75
            ],
76
            fill="blue",
77
            outline=None,
78
        )
79

80
        # Creating a pie slice shaped 'mask' ie an alpha channel.
81
        alpha = Image.new("L", self._image.size, "white")
82
        d = ImageDraw.Draw(alpha)
83
        d.pieslice(
84
            [
85
                (self._step * 3, self._step * 3),
86
                (self._size - self._step, self._size - self._step),
87
            ],
88
            0,
89
            90,
90
            fill="black",
91
            outline=None,
92
            width=0,
93
        )
94
        self._image.putalpha(alpha)
95

96
    def generate_image_types(self):
97
        for fmt in ("jpeg", "png"):
98
            i = self._image.copy()
99
            d = ImageDraw.Draw(i)
100
            d.text((self._step, self._step), fmt, fill=(0xFF, 0xFF, 0xFF, 0xFF))
101
            # jpegs dont have alpha channels.
102
            if fmt == "jpeg":
103
                i = i.convert("RGB")
104
            data = io.BytesIO()
105
            i.save(data, format=fmt.upper())
106
            self._data["image.%s" % fmt] = data.getvalue()
107

108
    def generate_image_channel_data(self):
109
        # np.array(image) returns the following shape
110
        #   (width, height, channels)
111
        # and
112
        #   transpose((2, 0, 1)) is really
113
        #   transpose((channels, width, height))
114
        # So then we get channels, width, height which makes extracting
115
        # single channels easier.
116
        array = np.array(self._image).transpose((2, 0, 1))
117

118
        for idx, name in zip(range(0, 4), ["red", "green", "blue", "alpha"]):
119
            data = io.BytesIO()
120
            img = Image.fromarray(array[idx].astype(np.uint8))
121
            img.save(data, format="PNG")
122
            self._data["%s.png" % name] = data.getvalue()
123

124
    def generate_bgra_image(self):
125
        # Split Images and rearrange
126
        array = np.array(self._image).transpose((2, 0, 1))
127

128
        # Recombine image to BGRA
129
        bgra = (
130
            np.stack((array[2], array[1], array[0], array[3]))
131
            .astype(np.uint8)
132
            .transpose(1, 2, 0)
133
        )
134

135
        data = io.BytesIO()
136
        Image.fromarray(bgra).save(data, format="PNG")
137
        self._data["bgra.png"] = data.getvalue()
138

139
    def generate_gif(self):
140
        # Create grayscale image.
141
        im = Image.new("L", (self._size, self._size), "white")
142

143
        images = []
144

145
        # Make ten frames with the circle of a random size and location
146
        random.seed(0)
147
        for i in range(0, 10):
148
            frame = im.copy()
149
            draw = ImageDraw.Draw(frame)
150
            pos = (random.randrange(0, self._size), random.randrange(0, self._size))
151
            circle_size = random.randrange(10, self._size / 2)
152
            draw.ellipse([pos, tuple(p + circle_size for p in pos)], "black")
153
            images.append(frame.copy())
154

155
        # Save the frames as an animated GIF
156
        data = io.BytesIO()
157
        images[0].save(
158
            data,
159
            format="GIF",
160
            save_all=True,
161
            append_images=images[1:],
162
            duration=100,
163
            loop=0,
164
        )
165

166
        self._data["circle.gif"] = data.getvalue()
167

168
    def generate_pseudorandom_image(self):
169
        w, h = self._size, self._size
170
        r = np.array([255 * np.sin(x / w * 2 * np.pi) for x in range(0, w)])
171
        g = np.array([255 * np.cos(x / w * 2 * np.pi) for x in range(0, w)])
172
        b = np.array([255 * np.tan(x / w * 2 * np.pi) for x in range(0, w)])
173

174
        r = np.tile(r, h).reshape(w, h).astype("uint8")
175
        g = np.tile(g, h).reshape(w, h).astype("uint8")
176
        b = np.tile(b, h).reshape(w, h).astype("uint8")
177

178
        rgb = np.stack((r, g, b)).transpose(1, 2, 0)
179

180
        data = io.BytesIO()
181
        Image.fromarray(rgb).save(data, format="PNG")
182
        self._data["pseudorandom.png"] = data.getvalue()
183

184
    def generate_gray_image(self):
185
        gray = (
186
            np.tile(np.arange(self._size) / self._size * 255, self._size)
187
            .reshape(self._size, self._size)
188
            .astype("uint8")
189
        )
190

191
        data = io.BytesIO()
192
        Image.fromarray(gray).save(data, format="PNG")
193
        self._data["gray.png"] = data.getvalue()
194

195
    def save(self):
196
        for name, data in self._data.items():
197
            Image.open(io.BytesIO(data)).save("/tmp/%s" % name)
198

199
    def get_images(self):
200
        return self._data
201

202

203
# Generate some images.
204
si = StreamlitImages()
205

206
# Get a single image of bytes and display
207
st.header("individual image bytes")
208
filename = "image.png"
209
data = si.get_images().get(filename)
210
st.image(data, caption=filename, output_format="PNG")
211

212
# Display a list of images
213
st.header("list images")
214
images = []
215
captions = []
216
for filename, data in si.get_images().items():
217
    images.append(data)
218
    captions.append(filename)
219
st.image(images, caption=captions, output_format="PNG")
220

221
st.header("PIL Image")
222
data = []
223

224
# Get a single image to use for all the numpy stuff
225
image = Image.open(io.BytesIO(si.get_images()["image.png"]))
226
data.append((image, "PIL Image.open('image.png')"))
227
image = Image.open(io.BytesIO(si.get_images()["image.jpeg"]))
228
data.append((image, "PIL Image.open('image.jpeg')"))
229
data.append(
230
    (Image.new("RGB", (200, 200), color="red"), "Image.new('RGB', color='red')")
231
)
232

233
images = []
234
captions = []
235
for i, c in data:
236
    images.append(i)
237
    captions.append(c)
238
st.image(images, caption=captions, output_format="PNG")
239

240
st.header("Bytes IO Image")
241
image = io.BytesIO(si.get_images()["image.png"])
242
st.image(image, caption=str(type(image)), output_format="PNG")
243

244
st.header("From a file")
245
st.image("/tmp/image.png", caption="/tmp/image.png", output_format="PNG")
246

247
st.header("From open")
248
st.image(open("/tmp/image.png", "rb").read(), caption="from read", output_format="PNG")
249

250
st.header("Numpy arrays")
251
image = Image.open(io.BytesIO(si.get_images()["image.png"]))
252
rgba = np.array(image)
253

254
data = []
255
# Full RGBA image
256
data.append((rgba, str(rgba.shape)))
257
# Select second channel
258
data.append((rgba[:, :, 1], str(rgba[:, :, 1].shape)))
259
# Make it x, y, 1
260
data.append(
261
    (np.expand_dims(rgba[:, :, 2], 2), str(np.expand_dims(rgba[:, :, 2], 2).shape))
262
)
263
# Drop alpha channel
264
data.append((rgba[:, :, :3], str(rgba[:, :, :3].shape)))
265

266
images = []
267
captions = []
268
for i, c in data:
269
    images.append(i)
270
    captions.append(c)
271
st.image(images, caption=captions, output_format="PNG")
272

273
try:
274
    st.header("opencv")
275
    import cv2
276

277
    image = np.fromstring(si.get_images()["image.png"], np.uint8)
278

279
    img = cv2.imdecode(image, cv2.IMREAD_UNCHANGED)
280
    st.image(img, output_format="PNG")
281
except Exception:
282
    pass
283

284
st.header("url")
285
url = "https://farm1.staticflickr.com/9/12668460_3e59ce4e61.jpg"
286
st.image(url, caption=url, width=200)
287

288
st.header("Clipping")
289
data = []
290
np.random.seed(0)
291
g = np.zeros((200, 200))
292
b = np.zeros((200, 200))
293

294
a = (np.random.ranf(size=200)) * 255
295
r = np.array(np.gradient(a)) / 255.0 + 0.5
296

297
a = np.tile(r, 200).reshape((200, 200))
298
a = a - 0.3
299
rgb = np.stack((a, g, b)).transpose(1, 2, 0)
300
data.append((rgb, "clamp: rgb image - 0.3"))
301

302
a = np.tile(r, 200).reshape((200, 200))
303
rgb = np.stack((a, g, b)).transpose(1, 2, 0)
304
data.append((rgb, "rgb image"))
305

306
a = np.tile(r, 200).reshape((200, 200))
307
a = a + 0.5
308
rgb = np.stack((a, g, b)).transpose(1, 2, 0)
309
data.append((rgb, "clamp: rgb image + 0.5"))
310

311
images = []
312
captions = []
313
for i, c in data:
314
    images.append(i)
315
    captions.append(c)
316
st.image(images, caption=captions, clamp=True, output_format="PNG")
317

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.