imglib2 is a library that I keep coming back to for image manipulation. It's very powerful but way, Way, WAY over abstracted. The documentation for it is just terrible; figuring out how to do simple things is much, much harder than it really needs to be. So, I'm adding a few notes for how to do the simple things.
For the examples below I used
Scala and
SBT. If you use Java the code is very similar and you can use
Maven with the same dependencies. You will need the following dependencies in your project:
"net.imglib2" % "imglib2" % "2.0.0-beta-26",
"net.imglib2" % "imglib2-ij" % "2.0.0-beta-26",
"io.scif" % "scifio" % "0.16.2-SNAPSHOT"
Reading images
The correct way(s) to read images with imglib2 seems to change every time I revisit the library. I
think the correct way is to use
SCIFIO to read images as ImgPlus objects. You can do this like so:
import io.scif.img.IO
import scala.collection.JavaConverters._
...
// Open the image as ImgPlus
val imgs = IO.openImgs(myImagePath).asScala // openImgs returns a java list, convert to scala
val imgPlus = imgs.head // Only 1 item in list so take it.
Getting the Image size
First step is to get the number of dimensions in the image.
val img = imgPlus.getImg // imgPlus wraps An Img object which contains the data
val dims = img.numDimensions // Returns dimensions
If
myImagePath pointed to a typically PNG or JPEG then img will be an
ArrayImg object with 3 dimensions in the order of HEIGHT, WIDTH, # COLOR CHANNELS (i.e. 3 for RGB). So to get the size of the image, I iterate over each dimension asking for it's size. In Scala, this is done like so:
// My example RGB image was 2448 pixels wide by 3264 pixels tall. So size
// here would be in the order of (height, width, colorChannels) or (3264, 2448, 3)
val size = for (i <- 0 until dims) yield img.dimension(i)
Navigating over the pixels
imglib2 provides cursors for iterating over the pixels. While this is very fast, the order of iteration is unknown to the programmer. I often want to access a specific pixel in a specific order. The way to do this is to grab a reference to some random access type pointing to the image data and use that to navigate to pixels.
val cursor = img.randomAcess()
// Here we'll walk over all the pixels in the first color channel (which
// I assume is Red, as in RGB, but I haven't verified that yet)
for {
w <- 0 until img.dimension(1).toInt // dimensions return longs not ints
h <- 0 until img.dimension(0).toInt
} {
val idx = Array(h, w, c)
cursor.setPosition(idx) // Navigate to desired pixel
val v = cursor.get // read pixel value
}
0 comments:
Post a Comment