dbuscombe commited on
Commit
345d0c0
1 Parent(s): c2ab5c8
.gitattributes CHANGED
@@ -32,3 +32,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
32
  *.zip filter=lfs diff=lfs merge=lfs -text
33
  *.zst filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
+ examples/*.* filter=lfs diff=lfs merge=lfs -text
36
+ saved_model/*.* filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## Daniel Buscombe, Marda Science LLC 2023
2
+ import gradio as gr
3
+ import numpy as np
4
+ import tensorflow as tf
5
+ import matplotlib.pyplot as plt
6
+ from skimage.transform import resize
7
+ from skimage.io import imsave
8
+ from skimage.filters import threshold_otsu
9
+ from skimage.measure import EllipseModel, CircleModel, ransac
10
+
11
+ ##========================================================
12
+ def fromhex(n):
13
+ """hexadecimal to integer"""
14
+ return int(n, base=16)
15
+
16
+ ##========================================================
17
+ def label_to_colors(
18
+ img,
19
+ mask,
20
+ alpha, # =128,
21
+ colormap, # =class_label_colormap, #px.colors.qualitative.G10,
22
+ color_class_offset, # =0,
23
+ do_alpha, # =True
24
+ ):
25
+ """
26
+ Take MxN matrix containing integers representing labels and return an MxNx4
27
+ matrix where each label has been replaced by a color looked up in colormap.
28
+ colormap entries must be strings like plotly.express style colormaps.
29
+ alpha is the value of the 4th channel
30
+ color_class_offset allows adding a value to the color class index to force
31
+ use of a particular range of colors in the colormap. This is useful for
32
+ example if 0 means 'no class' but we want the color of class 1 to be
33
+ colormap[0].
34
+ """
35
+
36
+ colormap = [
37
+ tuple([fromhex(h[s : s + 2]) for s in range(0, len(h), 2)])
38
+ for h in [c.replace("#", "") for c in colormap]
39
+ ]
40
+
41
+ cimg = np.zeros(img.shape[:2] + (3,), dtype="uint8")
42
+ minc = np.min(img)
43
+ maxc = np.max(img)
44
+
45
+ for c in range(minc, maxc + 1):
46
+ cimg[img == c] = colormap[(c + color_class_offset) % len(colormap)]
47
+
48
+ cimg[mask == 1] = (0, 0, 0)
49
+
50
+ if do_alpha is True:
51
+ return np.concatenate(
52
+ (cimg, alpha * np.ones(img.shape[:2] + (1,), dtype="uint8")), axis=2
53
+ )
54
+ else:
55
+ return cimg
56
+
57
+ ##====================================
58
+ def standardize(img):
59
+ # standardization using adjusted standard deviation
60
+
61
+ N = np.shape(img)[0] * np.shape(img)[1]
62
+ s = np.maximum(np.std(img), 1.0 / np.sqrt(N))
63
+ m = np.mean(img)
64
+ img = (img - m) / s
65
+ del m, s, N
66
+ #
67
+ if np.ndim(img) == 2:
68
+ img = np.dstack((img, img, img))
69
+
70
+ return img
71
+
72
+ ############################################################
73
+ ############################################################
74
+
75
+ #load model
76
+ filepath = './saved_model'
77
+ model = tf.keras.models.load_model(filepath, compile = True)
78
+ model.compile
79
+
80
+ #segmentation
81
+ def segment(input_img, dims=(1024, 1024)):
82
+
83
+ w = input_img.shape[0]
84
+ h = input_img.shape[1]
85
+ img = standardize(input_img)
86
+
87
+ img = resize(img, dims, preserve_range=True, clip=True)
88
+ img = np.expand_dims(img,axis=0)
89
+
90
+ est_label = model.predict(img)
91
+
92
+ #Test Time Augmentation
93
+ est_label2 = np.flipud(model.predict((np.flipud(img)), batch_size=1))
94
+ est_label3 = np.fliplr(model.predict((np.fliplr(img)), batch_size=1))
95
+ est_label4 = np.flipud(np.fliplr(model.predict((np.flipud(np.fliplr(img))))))
96
+
97
+ #soft voting - sum the softmax scores to return the new TTA estimated softmax scores
98
+ est_label = est_label + est_label2 + est_label3 + est_label4
99
+ est_label /= 4
100
+
101
+ pred = np.squeeze(est_label, axis=0)
102
+ pred = resize(pred, (w, h), preserve_range=True, clip=True)
103
+
104
+ bias=.1
105
+ thres_land = threshold_otsu(pred[:,:,1])-bias
106
+ print("Coin threshold: %f" % (thres_land))
107
+ mask = (pred[:,:,1]<=thres_land).astype('uint8')
108
+
109
+ imsave("greyscale.png", mask*255)
110
+
111
+ class_label_colormap = [
112
+ "#3366CC",
113
+ "#DC3912",
114
+ "#FF9900",
115
+ ]
116
+ # add classes
117
+ class_label_colormap = class_label_colormap[:2]
118
+
119
+ color_label = label_to_colors(
120
+ mask,
121
+ input_img[:, :, 0] == 0,
122
+ alpha=128,
123
+ colormap=class_label_colormap,
124
+ color_class_offset=0,
125
+ do_alpha=False,
126
+ )
127
+
128
+ imsave("color.png", color_label)
129
+
130
+ #overlay plot
131
+ plt.clf()
132
+ plt.imshow(input_img,cmap='gray')
133
+ plt.imshow(color_label, alpha=0.4)
134
+ plt.axis("off")
135
+ plt.margins(x=0, y=0)
136
+
137
+ ############################################################
138
+ dst = 1-mask.squeeze()
139
+ points = np.array(np.nonzero(dst)).T
140
+ points = np.column_stack((points[:,1], points[:,0]))
141
+
142
+ # print("Fitting ellipse to coin to compute diameter ....")
143
+ # model_robust, inliers = ransac(points, EllipseModel, min_samples=100,residual_threshold=2, max_trials=3)
144
+ # r=np.max([model_robust.params[2] , model_robust.params[3]])
145
+ # x=model_robust.params[0]
146
+ # y=model_robust.params[1]
147
+ # a_over_b = model_robust.params[2] / model_robust.params[3] ##a/b
148
+
149
+ print("Fitting circle to coin to compute diameter ....")
150
+ model_robust, inliers = ransac(points, CircleModel, min_samples=100,residual_threshold=2, max_trials=100)
151
+ r=model_robust.params[2]
152
+ x=model_robust.params[0]
153
+ y=model_robust.params[1]
154
+
155
+ print('diameter of coin = %f pixels' % (r*2))
156
+ print('image scaling (assuming quarter dollar) = %f mm/pixel' % (24.26 / r*2))
157
+
158
+ plt.plot(x, y, 'ko')
159
+ plt.plot(np.arange(x-r, x+r, int(r*2)), np.arange(y-r, y+r, int(r*2)),'m')
160
+
161
+ plt.savefig("overlay.png", dpi=300, bbox_inches="tight")
162
+
163
+ return 'diameter of coin = %f pixels' % (r*2), 'image scaling (assuming quarter dollar) = %f mm/pixel' % (24.26 / r*2), color_label, plt , "greyscale.png", "color.png", "overlay.png"
164
+
165
+ title = "Find and measure coins in images of sand!"
166
+ description = "This model demonstration segments beach sediment imagery into two classes: a) background, and b) coin, then measuring the coin. Allows upload of imagery and download of label imagery only one at a time. This model is part of the Doodleverse https://github.com/Doodleverse"
167
+
168
+
169
+ examples = [['examples/20191011_091052.jpg'],
170
+ ['examples/20191010_135020.jpg'],
171
+ ['examples/IMG_20210922_170908944.jpg'],
172
+ ['examples/IMG_20211121_120533257_HDR.jpg'],
173
+ ['examples/20210208_172834.jpg'],
174
+ ['examples/20220101_165359.jpg']]
175
+
176
+ inp = gr.Image()
177
+ out1 = gr.Image(type='numpy')
178
+ out2 = gr.Plot(type='matplotlib')
179
+ out3 = gr.File()
180
+ out4 = gr.File()
181
+ out5 = gr.File()
182
+
183
+ Segapp = gr.Interface(segment, inp, ["text", "text", out1, out2, out3, out4, out5], title = title, description = description, examples=examples, theme="grass")
184
+ #, allow_flagging='manual', flagging_options=["bad", "ok", "good", "perfect"], flagging_dir="flagged")
185
+
186
+ Segapp.launch(enable_queue=True)
examples/20191010_135020.jpg ADDED

Git LFS Details

  • SHA256: ca3d55cf474048c1e30244d4dfb366acf92abe7b772fbe702f3f3ae0128301e5
  • Pointer size: 132 Bytes
  • Size of remote file: 2.87 MB
examples/20191011_091052.jpg ADDED

Git LFS Details

  • SHA256: b9ecf86f4807c043e12d0a67f44309a6d393352860ae17f498cb77fab141c376
  • Pointer size: 132 Bytes
  • Size of remote file: 3.48 MB
examples/20210208_172834.jpg ADDED

Git LFS Details

  • SHA256: 68b82144eabc0a07a89a9f8c4a1aaef803bc9de9e4a76fdde1aca7667e08d696
  • Pointer size: 132 Bytes
  • Size of remote file: 1.95 MB
examples/20220101_165359.jpg ADDED

Git LFS Details

  • SHA256: 4ae1b8de54569aaff5101b7942d6fb03489d469716733c924cb531e7e545718c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.05 MB
examples/IMG_20210922_170908944.jpg ADDED

Git LFS Details

  • SHA256: d52253ff35764bc4c0e9f34cadc6654f8a43e63d56f89bde948242196fc6dc7d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.8 MB
examples/IMG_20211121_120533257_HDR.jpg ADDED

Git LFS Details

  • SHA256: a1bce4ddd65045f01786a057c31c0a288f6a6984be4611d85e4f48b486e75e40
  • Pointer size: 132 Bytes
  • Size of remote file: 2.31 MB
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ tensorflow
2
+ numpy
3
+ matplotlib
4
+ scikit-image
saved_model/fingerprint.pb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:afbf6f4ec9f4537fa9ae13f8cc94b3457093108c6271d93186e997e5f3b3a2e9
3
+ size 55
saved_model/keras_metadata.pb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fbf3edbe31752c2e7bc70b8ad19a55ab26f2aa77de0de20e5aebc07b3be153fc
3
+ size 223684
saved_model/saved_model.pb ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:92d833684120f47e160abd15afc0c03628af7d8dcb6757512843172cd2768514
3
+ size 1873216
saved_model/variables/variables.data-00000-of-00001 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3c63c997f8abd2afdbc1141f3f56fec9cab7e109b2402804cd7dbc1dc29d040f
3
+ size 23047425
saved_model/variables/variables.index ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:29a5a86d2cedea824aa16074f8b2c3724325f0fd7072aa940058edb8de23b00b
3
+ size 10864