Liking cljdoc? Tell your friends :D

Buffered Image Support

tech.datatype contains support for loading/saving buffered images and creating tensors from buffered images.

Usage


user> (require '[tech.v2.datatype :as dtype])
nil
user> (require '[tech.libs.buffered-image :as bufimg])
nil
user> (def test-img (bufimg/load "../tech.opencv/test/data/test.jpg"))
#'user/test-img
user> test-img
#object[java.awt.image.BufferedImage 0x71374470 "BufferedImage@71374470: type = 5 ColorModel: #pixelBits = 24 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@27f821b6 transparency = 1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 512 height = 288 #numDataElements 3 dataOff[0] = 2"]

user> (dtype/get-datatype test-img)
:uint8
user> (dtype/shape test-img)
[288 512 3]
user> (bufimg/image-channel-format test-img)
:bgr

user> (require '[tech.v2.tensor :as dtt])
nil

;;It is safe to print tensors to repl.  They will elide data in a similar fashion
;;as numpy arrays.
user> (dtt/ensure-tensor test-img)
#tech.v2.tensor<uint8>[288 512 3]
[[[172 170 170]
  [172 170 170]
  [171 169 169]
  ...
  [ 24  18  23]
  [ 24  18  23]
  [ 24  18  23]]
  ...

;;You can get a fully-typed reader from a tensor to read indiviudal bytes:
user> (def test-rdr (tens-typecast/datatype->tensor-reader :uint8 (dtt/ensure-tensor test-img)))
#'user/test-rdr
user> (.read3d test-rdr 0 0 1)
170
user> (.read3d test-rdr 0 0 2)
170
user> (.read3d test-rdr 0 0 3)
172
;;If you have images of other base storage types you may get a different tensor than
;;you want:

user> (vec(keys bufimg/image-types))
[:int-bgr
 :byte-gray
 :byte-binary
 :ushort-gray
 :ushort-555-rgb
 :int-argb-pre
 :byte-indexed
 :custom
 :byte-bgr
 :byte-abgr-pre
 :int-rgb
 :ushort-565-rgb
 :byte-abgr
 :int-argb]

user> (def test-img (bufimg/new-image 4 4 :int-bgr))
#'user/test-img
user> (dtt/ensure-tensor test-img)
#tech.v2.tensor<int32>[4 4 1]
[[[0]
  [0]
  [0]
  [0]]
 [[0]
  [0]
  [0]
  [0]]
 [[0]
  [0]
  [0]
  [0]]
 [[0]
  [0]
  [0]
  [0]]]

;;So we have a convenience method that will always return a uint8 tensor:

user> (bufimg/as-ubyte-tensor test-img)
#tech.v2.tensor<uint8>[4 4 3]
[[[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]
 [[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]
 [[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]
 [[0 0 0]
  [0 0 0]
  [0 0 0]
  [0 0 0]]]

;;You can use this as you can any other tensor.  See the cheatsheet.

(def img-writer (tens-typecast/datatype->tensor-writer
                       :uint8
                        (bufimg/as-ubyte-tensor test-img)))
#'user/img-writer
user> (.write3d img-writer 2 2 1 255)
nil
user> (dtype/->reader test-img)
[0 0 0 0 0 0 0 0 0 0 65280 0 0 0 0 0]

user> (bufimg/as-ubyte-tensor test-img)
#tech.v2.tensor<uint8>[4 4 3]
[[[0   0 0]
  [0   0 0]
  [0   0 0]
  [0   0 0]]
 [[0   0 0]
  [0   0 0]
  [0   0 0]
  [0   0 0]]
 [[0   0 0]
  [0   0 0]
  [0 255 0]
  [0   0 0]]
 [[0   0 0]
  [0   0 0]
  [0   0 0]
  [0   0 0]]]

;;Having images be tensors is useful for a few things, but stats is one of them.

user> (def planar-tens (dtt/transpose test-tens [2 0 1]))
#'user/planar-tens
user> planar-tens
#tech.v2.tensor<uint8>[3 288 512]
[[[172 172 171 ... 24 24 24]
  [173 174 173 ... 23 23 23]
  [174 175 174 ... 23 22 22]
  ...
  [ 37  37  37 ... 55 54 55]
  [ 36  35  35 ... 52 50 53]
  [ 39  37  34 ... 51 49 53]]
 [[170 170 169 ... 18 18 18]
  [171 172 171 ... 17 17 17]
  [172 173 172 ... 17 16 16]
  ...
  [ 46  46  46 ... 51 50 51]
  [ 45  44  44 ... 51 49 52]
  [ 48  46  43 ... 50 48 52]]
 [[170 170 169 ... 23 23 23]
  [171 172 171 ... 22 22 22]
  [172 173 172 ... 22 21 21]
  ...
  [ 84  84  83 ... 56 55 56]
  [ 83  82  81 ... 55 53 56]
  [ 86  84  80 ... 54 52 56]]]
user> (require '[tech.v2.datatype.functional :as dfn])
nil
user> (map dfn/descriptive-stats planar-tens)
({:min 0.0,
  :mean 97.47846137154495,
  :ecount 147456,
  :standard-deviation 60.735870710272195,
  :median 97.0,
  :max 248.0}
 {:min 5.0,
  :mean 101.00441487631271,
  :ecount 147456,
  :standard-deviation 58.55138215866227,
  :median 102.0,
  :max 255.0}
 {:min 5.0,
  :mean 113.43905978729688,
  :ecount 147456,
  :standard-deviation 57.79730239195752,
  :median 115.0,
  :max 255.0})


;;Drawing images work well in order to copy parts of one:
(def new-img (bufimg/new-image 512 512 :int-argb))
#'user/new-img
user> (bufimg/draw-image! test-img new-img :dst-y-offset 128)
#object[java.awt.image.BufferedImage 0x1ec0f94c "BufferedImage@1ec0f94c: type = 2 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInterleavedRaster: width = 512 height = 512 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0"]

;;But so does selecting subrects of tensors

user> (def copy-tens (dtt/select (bufimg/as-ubyte-tensor new-img) (range 128 (+ 288 128)) :all [0 1 2]))
#'user/copy-tens
user> copy-tens
#tech.v2.tensor<uint8>[288 512 3]
[[[172 170 170]
  [172 170 170]
  [171 169 169]
  ...
  [ 24  18  23]
  [ 24  18  23]
  [ 24  18  23]]


user> (dtype/copy! test-img copy-tens)
#tech.v2.tensor<uint8>[288 512 3]
[[[172 170 170]
  [172 170 170]
  [171 169 169]
  ...
  [ 24  18  23]
  [ 24  18  23]
  [ 24  18  23]]
  ...

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close