|
16 | 16 | [tech.v3.tensor.dimensions :as dims] |
17 | 17 | [tech.v3.libs.buffered-image :as bufimg] |
18 | 18 | [tablecloth.api :as tc] |
19 | | - [clojure.java.io :as io])) |
| 19 | + [clojure.java.io :as io] |
| 20 | + [tech.v3.dataset.tensor :as ds-tensor])) |
20 | 21 | ;; # Cloud Optimized GeoTIFFs in JVM Clojure |
21 | 22 | ;; ## Motivation |
22 | 23 | ;; This document shows several different methods for handling COGs in JVM Clojure without |
|
80 | 81 | {:images images |
81 | 82 | :reader-format (.getFormatName reader)})))) |
82 | 83 |
|
| 84 | +(require '[tech.v3.datatype :as dtype]) |
| 85 | + |
83 | 86 | (defn get-pixel [^BufferedImage image x y] |
84 | 87 | (let [raster (.getRaster image) |
85 | 88 | ;; Handle images with an arbitrary number of bands. |
|
135 | 138 | ;; For our purposes we can just add the tablecloth dependency and that will transitively |
136 | 139 | ;; bring along the rest of the stack. |
137 | 140 |
|
138 | | -(require '[tablecloth.api :as tc]) |
139 | | - |
140 | | -(repeatedly 5 #(double-array 2 3)) |
141 | | - |
| 141 | +(require '[tablecloth.api :as tc] |
| 142 | + '[tech.v3.tensor :as tensor] |
| 143 | + '[tech.v3.dataset.tensor :as ds-tensor]) |
142 | 144 |
|
143 | 145 |
|
144 | 146 | (defn buffered-image->dataset [^BufferedImage img] |
145 | 147 | (let [width (.getWidth img) |
146 | 148 | height (.getHeight img) |
147 | 149 | num-bands (.getNumBands (.getRaster img)) |
148 | | - |
| 150 | + |
| 151 | + ;; The following will be easier after dtype-next's |
| 152 | + ;; [#133](https://github.com/cnuernber/dtype-next/issues/133) |
| 153 | + ;; is resolved. |
149 | 154 | tensor (-> img |
150 | 155 | dtype/->array-buffer |
151 | 156 | ;; height x width x bands |
|
162 | 167 | (fn [y x] y))) |
163 | 168 |
|
164 | 169 | ;; Build dataset |
165 | | - ds-map (into {:x xs :y ys} |
166 | | - (for [i (range num-bands)] |
167 | | - [(keyword (str "band-" i)) |
168 | | - (dtype/as-reader |
169 | | - (tensor i))]))] |
170 | | - (tc/dataset ds-map))) |
171 | | - |
| 170 | + ds-map (into {:x xs :y ys} |
| 171 | + (for [i (range num-bands)] |
| 172 | + [(keyword (str "band-" i)) |
| 173 | + (dtype/as-reader |
| 174 | + (tensor i))]))] |
| 175 | + (-> tensor |
| 176 | + (tensor/reshape [(* height width) |
| 177 | + num-bands]) |
| 178 | + ds-tensor/tensor->dataset |
| 179 | + (tc/add-columns {:x xs |
| 180 | + :y ys}) |
| 181 | + (tc/select-columns (concat [:x :y] |
| 182 | + (range num-bands))) |
| 183 | + (tc/rename-columns (into {} |
| 184 | + (for [i (range num-bands)] |
| 185 | + [i (keyword (str "band-" i))])))))) |
172 | 186 |
|
173 | 187 | (defonce ds (-> example-geotiff-medium |
174 | 188 | :images |
|
200 | 214 | (defonce ds-with-approx-dvi (add-dvi ds)) |
201 | 215 |
|
202 | 216 | (require '[tech.v3.dataset :as ds] |
203 | | - '[tech.v3.datatype :as dtype] |
204 | 217 | '[tech.v3.datatype.statistics :as dstats]) |
205 | 218 | (import '[java.awt Color]) |
206 | 219 |
|
|
223 | 236 | (add-approx-dvi-display ds-with-approx-dvi)) |
224 | 237 |
|
225 | 238 | (defn dataset->image |
226 | | - [dataset {:keys [r g b]}] |
227 | | - (let [xs (ds/column dataset :x) |
228 | | - ys (ds/column dataset :y) |
229 | | - rs (ds/column dataset r) |
230 | | - gs (ds/column dataset g) |
231 | | - bs (ds/column dataset b) |
232 | | - |
233 | | - max-x (-> xs last int) |
234 | | - min-x (-> xs first int) |
235 | | - max-y (-> ys last int) |
236 | | - min-y (-> ys first int) |
237 | | - |
238 | | - width (inc (- max-x min-x)) |
239 | | - height (inc (- max-y min-y)) |
240 | | - |
241 | | - ;; Create the image |
242 | | - img (BufferedImage. width height BufferedImage/TYPE_INT_RGB)] |
243 | | - |
244 | | - ;; Set pixels |
245 | | - (dotimes [i (ds/row-count dataset)] |
246 | | - (let [x (- (int (dtype/get-value xs i)) min-x) |
247 | | - y (- (int (dtype/get-value ys i)) min-y) |
248 | | - r (int (dtype/get-value rs i)) |
249 | | - g (int (dtype/get-value gs i)) |
250 | | - b (int (dtype/get-value bs i)) |
251 | | - color (Color. r g b)] |
252 | | - (.setRGB img x y (.getRGB color)))) |
253 | | - |
254 | | - img)) |
| 239 | + [dataset {:as columns-mapping |
| 240 | + :keys [r g b]}] |
| 241 | + (let [height (->> dataset |
| 242 | + :y |
| 243 | + ((juxt dstats/max dstats/min)) |
| 244 | + (apply -)) |
| 245 | + width (->> dataset |
| 246 | + :x |
| 247 | + ((juxt dstats/max dstats/min)) |
| 248 | + (apply -))] |
| 249 | + (-> columns-mapping |
| 250 | + (update-vals dataset) |
| 251 | + tc/dataset |
| 252 | + ds-tensor/dataset->tensor |
| 253 | + (tensor/reshape [height width 3]) |
| 254 | + bufimg/tensor->image))) |
255 | 255 |
|
256 | 256 | (dataset->image ds-with-dvi-display |
257 | 257 | {:r :dvi-display |
|
0 commit comments