Skip to content

BufferedImage's .getRaster .getNumBands can be used in figuring out the shape #133

Description

@daslu

The namespace tech.v3.libs.buffered-image extends BufferedImage with certain protocols, including the extraction of shape (tech.v3.datatype/shape):
https://github.com/cnuernber/dtype-next/blob/9170e69/src/tech/v3/libs/buffered_image.clj#L160

In unknown image types, it is assumed only one band:
https://github.com/cnuernber/dtype-next/blob/9170e69/src/tech/v3/libs/buffered_image.clj#L177

However, the number of bands can be extracted using .getRaster .getNumBands, as @larzeitlin does in an upcoming tutorial about Cloud Optimized GeoTiff:
https://github.com/ClojureCivitas/clojurecivitas.github.io/blob/be26c88/src/gis/geotiff.clj#L135

Example test file: https://github.com/ClojureCivitas/clojurecivitas.github.io/blob/be26c887796258f9ae31756cc3da7b654cf8d11c/src/gis/resources/example_geotiff_medium.tif

You can download it, and use the following code from @larzeitlin's tutorial to read it and extract the number of bands:

(import '[java.awt.image BufferedImage]
        '[java.io File]
        '[javax.imageio ImageIO]
        '[javax.imageio.stream FileImageInputStream])

(defn tiff-reader []
  (let [readers (ImageIO/getImageReadersByFormatName "tiff")]
    (.next readers)))

(defn read-tiff [file-path]
  (let [file (File. file-path)
        reader (tiff-reader)]
    (with-open [stream (FileImageInputStream. file)]
      (.setInput reader stream)
      (let [images (doall
                    ;; A single TIFF can store multiple images.
                    ;; This will be significant when we come to
                    ;; GeoTIFFs because of resolution pyramids.
                    ;; See below.
                    (for [i (range (.getNumImages reader true))]
                      (let [metadata (.getImageMetadata reader i)
                            native-format (.getNativeMetadataFormatName metadata)]
                        {:index i
                         :native-format native-format
                         :width (.getWidth reader i)
                         :height (.getHeight reader i)
                         :image (.read reader i)
                         :metadata metadata})))]
        {:images images
         :reader-format (.getFormatName reader)}))))

(-> "example_geotiff_medium.tif"
    read-tiff
    :images
    first
    :image
    .getRaster
    .getNumBands)

This will also affect tech.v3.tensor/as-tensor and allow it to come up with the right shape of output, this allowing to turn any Raster image to a tensor -- quite important for working with multispectral images.

Zulip discussion with @harold: #tech.ml.dataset.dev > shape of an image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions