9 votos

Como leer cada pixel de cada banda de una multibanda GeoTiff con GeoTools Java

Soy nuevo a trabajar con Raster en GeoTools-experiencia en java. Mi objetivo es leer en un geotiff que tiene varias bandas, a continuación, crear un HashMap para cada píxel, donde la clave es simplemente la lat/lon de los píxeles, y el valor es un sortedMap en el que la clave es el nombre de la banda, y el valor es el valor real de los píxeles de esa banda. Yo soy, a continuación, vamos a hacer algunas cosas fascinantes con ese mapa. Así que en términos básicos, tengo que leer en un tif, obtener de cada banda, de acceso y, a continuación, pixel del lat lon en cada banda. Tengo un lugar patético intento de leer en un tiff de abajo, pero no puedo encontrar cualquier manera sencilla en línea para llegar a cada banda, y cada píxel. Ningún tipo de ayuda sería muy apreciada.

GridCoverage2D g;// = new GridCoverage2D(null, null);

      GeoTiffReader r = new GeoTiffReader(new File("c;\\temp\\thetiff.tif"));
      GridEnvelope originalGridRange = r.getOriginalGridRange();

ACTUALIZACIÓN: Así que ahora puedo leer el archivo con el siguiente código:

     public static void main(String[] args) {
        try {
          AbstractGridCoverage2DReader reader = new GeoTiffReader(new FileInputStream(new File("C:\\my.TIF")));//...; // Creating a reader
          String[] coverageNames = reader.getGridCoverageNames();
          // At this point, coverageNames may contain, as an instance, "pressure,temperature,humidity"

          String requestedCoverageName = coverageNames[0]; // e..g, "temperature"

          // Getting the coverage's properties
          final GeneralEnvelope envelope = reader.getOriginalEnvelope();
          final GridEnvelope gridRange = reader.getOriginalGridRange();

          // reading the coverage
//FAILS HERE
          GridCoverage2D coverage = (GridCoverage2D) reader.read(requestedCoverageName, null);
          System.out.println("test");
        } catch (Exception ex) {
          Logger.getLogger(GeoTiffvectorizer.class.getName()).log(Level.SEVERE, null, ex);
        }
      }

el problema ahora es que yo sé que la imagen tiene 8 bandas, pero yo sólo tengo un artículo en coverageNames[] y me da el siguiente stacktrace de error

Error: One factory fails for the operation "ImageRead"
Occurs in: javax.media.jai.ThreadSafeOperationRegistry
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
    at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
    at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
    at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
    at javax.media.jai.RenderedOp.getWidth(RenderedOp.java:2179)
    at org.geotools.gce.geotiff.GeoTiffReader.read(GeoTiffReader.java:560)
    at org.geotools.coverage.grid.io.AbstractGridCoverage2DReader.read(AbstractGridCoverage2DReader.java:239)
    at dgi.vectorspaceclustering.GeoTiffvectorizer.main(GeoTiffvectorizer.java:38)
Caused by: java.lang.RuntimeException: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:317)
    ... 14 more
Caused by: javax.imageio.IIOException: I/O error reading header!
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:458)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:465)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.seekToImage(TIFFImageReader.java:589)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.getImageTypes(TIFFImageReader.java:1104)
    at javax.imageio.ImageReader.getRawImageType(ImageReader.java:681)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.layoutHelper(ImageReadOpImage.java:228)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.<init>(ImageReadOpImage.java:473)
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:309)
    ... 14 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:404)
    ... 21 more
2014-07-14T16:30:36.845-0400  SEVERE  null
javax.media.jai.util.ImagingException: All factories fail for the operation "ImageRead"
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1687)
    at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
    at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
    at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
    at javax.media.jai.RenderedOp.getWidth(RenderedOp.java:2179)
    at org.geotools.gce.geotiff.GeoTiffReader.read(GeoTiffReader.java:560)
    at org.geotools.coverage.grid.io.AbstractGridCoverage2DReader.read(AbstractGridCoverage2DReader.java:239)
    at dgi.vectorspaceclustering.GeoTiffvectorizer.main(GeoTiffvectorizer.java:38)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
    ... 8 more
Caused by: java.lang.RuntimeException: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:317)
    ... 14 more
Caused by: javax.imageio.IIOException: I/O error reading header!
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:458)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:465)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.seekToImage(TIFFImageReader.java:589)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.getImageTypes(TIFFImageReader.java:1104)
    at javax.imageio.ImageReader.getRawImageType(ImageReader.java:681)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.layoutHelper(ImageReadOpImage.java:228)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.<init>(ImageReadOpImage.java:473)
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:309)
    ... 14 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:404)
    ... 21 more
Caused by:
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at javax.media.jai.FactoryCache.invoke(FactoryCache.java:122)
    at javax.media.jai.OperationRegistry.invokeFactory(OperationRegistry.java:1674)
    at javax.media.jai.ThreadSafeOperationRegistry.invokeFactory(ThreadSafeOperationRegistry.java:473)
    at javax.media.jai.registry.RIFRegistry.create(RIFRegistry.java:332)
    at javax.media.jai.RenderedOp.createInstance(RenderedOp.java:819)
    at javax.media.jai.RenderedOp.createRendering(RenderedOp.java:867)
    at javax.media.jai.RenderedOp.getWidth(RenderedOp.java:2179)
    at org.geotools.gce.geotiff.GeoTiffReader.read(GeoTiffReader.java:560)
    at org.geotools.coverage.grid.io.AbstractGridCoverage2DReader.read(AbstractGridCoverage2DReader.java:239)
    at dgi.vectorspaceclustering.GeoTiffvectorizer.main(GeoTiffvectorizer.java:38)
Caused by: java.lang.RuntimeException: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:317)
    ... 14 more
Caused by: javax.imageio.IIOException: I/O error reading header!
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:458)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:465)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.seekToImage(TIFFImageReader.java:589)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.getImageTypes(TIFFImageReader.java:1104)
    at javax.imageio.ImageReader.getRawImageType(ImageReader.java:681)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.layoutHelper(ImageReadOpImage.java:228)
    at com.sun.media.jai.imageioimpl.ImageReadOpImage.<init>(ImageReadOpImage.java:473)
    at com.sun.media.jai.imageioimpl.ImageReadCRIF.create(ImageReadCRIF.java:309)
    ... 14 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at it.geosolutions.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:404)
    ... 21 more

7voto

Román Puntos 800

¡Respuesta de Marcos es genial! Realmente me ayudó a salir.

Aquí es una versión ligeramente modificada del código de marca. La principal diferencia es que este código no se basan en el paquete java.awt.image para calcular el tamaño de la imagen, el número de bandas, o valores de los píxeles. En su lugar, utiliza la API de cobertura de GeoTools.

import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.coverage.grid.*;
import org.opengis.coverage.grid.*;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;


public class Test {
    public static void test(java.io.File file) throws Exception {

        ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY.createValue();
        policy.setValue(OverviewPolicy.IGNORE);

        //this will basically read 4 tiles worth of data at once from the disk...
        ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();

        //Setting read type: use JAI ImageRead (true) or ImageReaders read methods (false)
        ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
        useJaiRead.setValue(true);


        GridCoverage2DReader reader = new GeoTiffReader(file);
        GridEnvelope dimensions = reader.getOriginalGridRange();
        GridCoordinates maxDimensions = dimensions.getHigh();
        int w = maxDimensions.getCoordinateValue(0)+1;
        int h = maxDimensions.getCoordinateValue(1)+1;
        int numBands = reader.getGridCoverageCount();

        GridCoverage2D coverage = reader.read(
            new GeneralParameterValue[]{policy, gridsize, useJaiRead}
        );
        GridGeometry2D geometry = coverage.getGridGeometry();


        for (int i=0; i<w; i++) {
            for (int j=0; j<h; j++) {

                org.geotools.geometry.Envelope2D pixelEnvelop =
                geometry.gridToWorld(new GridEnvelope2D(i, j, 1, 1));

                double lat = pixelEnvelop.getCenterY();
                double lon = pixelEnvelop.getCenterX();

                double[] vals = new double[numBands];
                coverage.evaluate(new GridCoordinates2D(i, j), vals);

                //Do something!

            }
        }

    }
}

6voto

markg Puntos 173

Finalmente pensé que lo... este código asume que el geotif está en wgs84 (4326) Proy, pero funciona bien para conseguir la lat para cada píxel y los valores de banda para cada pixel (el formato de un csv aquí). Espero que esto ayude.

import com.spatial4j.core.io.GeohashUtils;
import java.awt.geom.Rectangle2D;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.grid.io.AbstractGridFormat;
import org.geotools.coverage.grid.io.OverviewPolicy;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.parameter.ParameterValue;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.Serializable;


public class PixelExtractor implements Serializable {

  /**
   * returns a pixel as a string with teh following format String outString =
   * geoHash + "@" + name + "@" + date + "@" + originalBands
   *
   * @param f the geotif file
   * @param name the name of the file
   * @param date the date of information (when the image was captured)
   * @param collector
   * @throws Exception
   */
  public void extract(File f, String name, String date) throws Exception {
    ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY
            .createValue();
    policy.setValue(OverviewPolicy.IGNORE);

    // this will basically read 4 tiles worth of data at once from the disk...
    ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();
    //gridsize.setValue(512 * 4 + "," + 512);

    // Setting read type: use JAI ImageRead (true) or ImageReaders read methods (false)
    ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
    useJaiRead.setValue(true);

    //reader.read(new GeneralParameterValue[] { policy, gridsize, useJaiRead });
    GridCoverage2D image
            = new GeoTiffReader(f).read(new GeneralParameterValue[]{policy, gridsize, useJaiRead});
    Rectangle2D bounds2D = image.getEnvelope2D().getBounds2D();
  bounds2D.getCenterX();
    // calculate zoom level for the image
    GridGeometry2D geometry = image.getGridGeometry();



    BufferedImage img = ImageIO.read(f);
    // ColorModel colorModel = img.getColorModel(      
    WritableRaster raster = img.getRaster();

    int numBands = raster.getNumBands();

    int w = img.getWidth();
    int h = img.getHeight();
    outer:
    for (int i = 0; i < w; i++) {//width...

      for (int j = 0; j < h; j++) {

        double[] latlon = geo(geometry, i, j);
        double lat = latlon[0];
        double lon = latlon[1];

        Double s = 0d;

        String originalBands = "";
        for (int k = 0; k < numBands; k++) {
          double d = raster.getSampleDouble(i, j, k);
          originalBands += d + ",";
          s += d;
        }

        originalBands = originalBands.substring(0, originalBands.length() - 1);
        if (s.compareTo(0d) == 0) {
          continue;
        }
        String geoHash = GeohashUtils.encodeLatLon(lat, lon);
//here do something with the bands, lat, long, geohash, etc....

      }

    }

  }

  private static double[] geo(GridGeometry2D geometry, int x, int y) throws Exception {

    //int zoomlevel = 1;
    Envelope2D pixelEnvelop = geometry.gridToWorld(new GridEnvelope2D(x, y, 1, 1));

    // pixelEnvelop.getCoordinateReferenceSystem().getName().getCodeSpace();
    return new double[]{pixelEnvelop.getCenterY(), pixelEnvelop.getCenterX()};

  }

}

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X