Rens Dimmendaal commited on
Commit
c5d7102
1 Parent(s): 7ff6a1c
Files changed (4) hide show
  1. app.py +91 -0
  2. imgofai/__init__.py +8 -0
  3. imgofai/tree.py +101 -0
  4. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from imgofai import *
2
+
3
+ import matplotlib.pyplot as plt
4
+
5
+ import PIL
6
+
7
+ import numpy as np
8
+ from pathlib import Path
9
+
10
+ from imgofai.tree import img2df, df2xy
11
+ import pandas as pd
12
+ from sklearn.tree import DecisionTreeRegressor
13
+ from sklearn.preprocessing import FunctionTransformer
14
+ from sklearn.pipeline import make_pipeline
15
+
16
+ import streamlit as st
17
+
18
+ import requests
19
+
20
+ st.write("# Images of AI Demo")
21
+
22
+ st.write("This page demonstrates how I created the images I submitted for [Better Images of AI project](https://betterimagesofai.org/images)")
23
+
24
+ def add_radial_features(X,y=None):
25
+ assert isinstance(X, pd.DataFrame), "X is not a dataframe"
26
+ xp = X.copy()
27
+ xp['dim0'] = np.sqrt(((X - X.mean())**2).sum(axis=1))
28
+ xp['dim1'] = np.arctan2(X['dim1'],X['dim0'])
29
+
30
+ X = pd.concat([
31
+ X,
32
+ xp,
33
+ ],axis=1)
34
+
35
+ return X
36
+
37
+
38
+
39
+ def make_tree_approximator(radial = False, max_depth=4):
40
+ if radial:
41
+ model = make_pipeline(
42
+ FunctionTransformer(add_radial_features),
43
+ DecisionTreeRegressor(max_depth=max_depth),
44
+ )
45
+ else:
46
+ model = DecisionTreeRegressor(max_depth=max_depth)
47
+
48
+
49
+ model.fit(x_raw, y)
50
+ pred = PIL.Image.fromarray(
51
+ model.predict(x_raw).reshape(img_array.shape).round().astype("uint8")
52
+ )
53
+ score = model.score(x_raw, y)
54
+ return pred
55
+
56
+
57
+ st.write("## Try it out yourself:")
58
+
59
+ url = st.text_input("Image url:", "https://images.unsplash.com/reserve/bOvf94dPRxWu0u3QsPjF_tree.jpg?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1752&q=80")
60
+ img = PIL.Image.open(requests.get(url, stream=True).raw)
61
+
62
+ img_array = np.array(img)
63
+ df = img2df(img_array)
64
+ x_raw, y = df2xy(df)
65
+
66
+
67
+
68
+ ccol1, ccol2, _ = st.columns(3)
69
+
70
+ with ccol1:
71
+ max_depth1 = st.slider("max depth left:",1,12,2)
72
+ radial1 = st.checkbox("radial features left", value=False)
73
+
74
+ with ccol2:
75
+ max_depth2 = st.slider("max depth middle:",1,12,6)
76
+ radial2 = st.checkbox("radial features middle", value=False)
77
+
78
+
79
+ st.write("## Output")
80
+ col1, col2, col3 = st.columns(3)
81
+
82
+ with col1:
83
+ left_img = make_tree_approximator(radial1, max_depth=max_depth1)
84
+ st.image(left_img)
85
+
86
+ with col2:
87
+ mid_img = make_tree_approximator(radial2, max_depth=max_depth2)
88
+ st.image(mid_img)
89
+
90
+ with col3:
91
+ st.image(img)
imgofai/__init__.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ import datetime
2
+ from .tree import treeify
3
+
4
+ __version__ = "0.1.0"
5
+
6
+
7
+ def timestamp():
8
+ return datetime.datetime.now().strftime("%Y%m%d%H%M%S")
imgofai/tree.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+ import pandas as pd
4
+ from sklearn.tree import DecisionTreeRegressor
5
+ import PIL
6
+
7
+
8
+ def img2df(img_array):
9
+ dim0_arr = (
10
+ np.arange(img_array.shape[0])
11
+ .reshape((-1, 1))
12
+ .repeat(img_array.shape[1], axis=1)
13
+ .flatten()
14
+ )
15
+
16
+ dim1_arr = (
17
+ np.arange(img_array.shape[1])
18
+ .reshape((1, -1))
19
+ .repeat(img_array.shape[0], axis=0)
20
+ .flatten()
21
+ )
22
+
23
+ df = pd.DataFrame({"dim0": dim0_arr, "dim1": dim1_arr})
24
+
25
+ values = img_array.reshape((img_array.shape[0] * img_array.shape[1], -1))
26
+ for col in range(values.shape[1]):
27
+ df[f"value{col}"] = values[:, col]
28
+
29
+ return df
30
+
31
+
32
+ def normalize(img):
33
+ return (img - img.min()) / (img.max() - img.min())
34
+
35
+
36
+ def df2xy(df):
37
+ x = df[[c for c in df if c.startswith("dim")]]
38
+ y = df[[c for c in df if c.startswith("value")]]
39
+
40
+ if len(y.columns) == 1:
41
+ y = y.values.reshape(-1)
42
+ return x, y
43
+
44
+
45
+ def tree_window(
46
+ img, add_cartesian=True, add_rotation=False, add_polar=False, depths=(2, 6)
47
+ ):
48
+ df = img2df(img)
49
+ x_raw, y = df2xy(df)
50
+
51
+ sets = []
52
+ if add_cartesian:
53
+ sets.append(x_raw)
54
+ if add_rotation > 0:
55
+ # rotate
56
+ theta = np.radians(add_rotation)
57
+ c, s = np.cos(theta), np.sin(theta)
58
+ R = np.array(((c, -s), (s, c)))
59
+ xr = x_raw @ R
60
+ sets.append(xr)
61
+ if add_polar:
62
+ # polar
63
+ xp = x_raw.copy()
64
+ xp["dim0"] = np.sqrt(((x_raw - x_raw.mean()) ** 2).sum(axis=1))
65
+ xp["dim1"] = np.arctan2(x_raw["dim1"], x_raw["dim0"])
66
+ sets.append(xp)
67
+
68
+ x = pd.concat(sets, axis=1)
69
+
70
+ fig, axes = plt.subplots(ncols=len(depths) + 1, figsize=(36, 36))
71
+
72
+ for ax, depth in zip(axes, depths):
73
+ model = DecisionTreeRegressor(max_depth=depth)
74
+ model.fit(x, y)
75
+ pred = model.predict(x).reshape(img.shape)
76
+ if len(y.shape) == 2:
77
+ ax.imshow(pred)
78
+ else:
79
+ ax.imshow(pred, cmap="gray")
80
+ ax.set_axis_off()
81
+
82
+ if len(y.shape) == 2:
83
+ axes[-1].imshow(img)
84
+ else:
85
+ axes[-1].imshow(img, cmap="gray")
86
+ axes[-1].set_axis_off()
87
+
88
+ return fig
89
+
90
+
91
+ def treeify(img, max_depth):
92
+ img_array = np.array(img)
93
+ df = img2df(img_array)
94
+ x, y = df2xy(df)
95
+ model = DecisionTreeRegressor(max_depth=max_depth)
96
+ model.fit(x, y)
97
+ pred = PIL.Image.fromarray(
98
+ model.predict(x).reshape(img_array.shape).round().astype("uint8")
99
+ )
100
+ score = model.score(x, y)
101
+ return pred, score
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ matplotlib
2
+ Pillow
3
+ numpy
4
+ pandas
5
+ scikit-learn
6
+ streamlit
7
+ requests