Package utils.images

Source Code of utils.images.ImageUtils

package utils.images;

import ij.ImagePlus;
import ij.gui.Wand;
import ij.measure.Measurements;
import ij.measure.ResultsTable;
import ij.plugin.filter.ParticleAnalyzer;
import ij.process.ByteProcessor;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import javax.imageio.ImageIO;

import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;


/**
* La clase <code>ImageUtils</code> est� constituida por un conjunto de
* herramientas para procesamiento de im�genes. Una de estas funcionalidades
* es el reconocimiento de objetos seg�n color, lo cual es intensamente
* utilizado por los sistemas de posicionamiento basados en im�genes.<br>
* Tambi�n permite la conversi�n de im�genes entre los formatos AWT y SWT.
*
*/
public class ImageUtils
{
 
  // Constantes p�blicas
  public static final int          NORMAL_ACCURACY    = 1;
  public static final int          HIGH_ACCURACY    = 2;
 
  // Constantes privadas
  private static final int        MARGIN        = 30// TODO: ajustar
  private static final int        BINARY_THRESHOLD  = 150;

 
  // Atributos
  private ParticleAnalyzer         analizer;
  private ResultsTable          rt;
  private RecognizedShape[]        recognizedShapes;
  private ImagePlus            bwImage;
  private ByteProcessor          bwProcessor;
  private BufferedImage          sceneImage;
  private int[]              pixels;
  private Graphics2D            gc;
  private boolean              firstTime;

 
  /**
   * Crea una nueva instancia <code>ImageUtils</code> para
   * procesamiento de im�genes.
   */
  public ImageUtils()
  {
    firstTime = true;
  }
 
 
  private void buildAnalizer(int min, int max)
  {
    // Se construye el analizador
    rt = new ResultsTable();
    analizer = new ParticleAnalyzer(
        ParticleAnalyzer.SHOW_NONE | ParticleAnalyzer.FLOOD_FILL | ParticleAnalyzer.RECORD_STARTS,
        Measurements.CENTROID | Measurements.AREA | Measurements.RECT,
        rt,
        min,
        max);
  }

 
  /**
   * Establece la imagen a la cual se le aplicar�n los procesamientos.
   * @param image  imagen AWT a procesar.
   */
  public synchronized void setImage(Image image)
  {
    if ( firstTime )
    {
      int width   = image.getWidth(null);
      int height  = image.getHeight(null);
     
      pixels    = new int[ width * height ];

      sceneImage  = new BufferedImage( width, height, BufferedImage.TYPE_INT_RGB);
      pixels    = ((DataBufferInt)sceneImage.getRaster().getDataBuffer()).getData();
      gc      = sceneImage.createGraphics();
     
      bwImage    = new ImagePlus(null, bwProcessor = new ByteProcessor(width,height));
      //bwImage.trimProcessor();
     
      firstTime = false;
    }
   
    gc.drawImage(image, 0, 0, null);
  }
 
 
    private synchronized void extractColor(Color c) throws ImageUtilsException
    {
      if ( sceneImage == null  ||  bwProcessor == null  )
        throw new ImageUtilsException("There is not a loaded image.");
     
      int  auxR, auxG, auxB;
      int offset, i;
     
      int r       = c.getRed();
      int g       = c.getGreen();
      int b       = c.getBlue();
     
      int width     = sceneImage.getWidth(null);
        int height    = sceneImage.getHeight(null);
        byte[] bwPixels  = (byte[])bwProcessor.getPixels();
       
      for (int y=0; y<height; y++)
      {
        offset = y*width;
        for (int x=0; x<width; x++)
        {
          i = offset + x;

          auxR  = (pixels[i] & 0x00FF0000) >> 16;
          auxG  = (pixels[i] & 0x0000FF00) >>  8;
          auxB  =  pixels[i] & 0x000000FF;
         
         
        if (  (auxR < r-MARGIN) || (auxR > r+MARGIN||
            (auxG < g-MARGIN) || (auxG > g+MARGIN||
            (auxB < b-MARGIN) || (auxB > b+MARGIN)  )
          bwPixels[i] |= 0xFF// blanco
        else
          bwPixels[i] &= 0x00// negro
        }
      }
     
    }

   
  /**
   * Reconoce en la imagen cargada con <code>setImage()</code> las figuras
   * del color indicado por par�metro, cuyas �reas est�n comprendidas entre
   * <code>min</code> y <code>max</code>. Almacena un arreglo con informaci�n
   * de cada figura reconocida (centroide, �rea, v�rtices).<br>
   * Permite especificar la precisi�n con la que se har� el procesamiento
   * (en computo intensivo o tiempo real, utilizar el nivel normal para no
   * penalizar el desempe�o).
   * @param r            componente rojo.
   * @param g            componente verde.
   * @param b            componente azul.
   * @param min          tama�o m�nimo.
   * @param max          tama�o m�ximo.
   * @param accuracy        {@link #NORMAL_ACCURACY} o {@link #HIGH_ACCURACY}.
   * @throws ImageUtilsException  si se produce alg�n error en el proceso.
   */
  public synchronized RecognizedShape[] recognizeShapes(int r, int g, int b, int min, int max, int accuracy) throws ImageUtilsException
  {
   
    // Etapa de preprocesamiento
    Color color = new Color(r,g,b);
    extractColor( color );

   
    if ( accuracy == HIGH_ACCURACY )
    {
      // Si se utiliza "alta precisi�n", entonces se aplica
      // un filtrado ("median filter") que permite hacer un
      // mejor reconocimiento de �tems, a costa de un mayor
      // tiempo de procesamiento.
     
      int i,j;
     
        bwImage.trimProcessor();
        bwProcessor.medianFilter();
        bwProcessor.threshold(BINARY_THRESHOLD);
       
      // Se aplica una correcci�n a la imagen, para quitar el borde negro
      // delgado agregado por el filtro medianFilter().
      // TODO: ver c�mo solucionar esto de una forma "correcta"
          int w = bwImage.getWidth();
          int h = bwImage.getHeight();
         
          for (j=0; j<w; j++)
          {
            bwProcessor.putPixel(j, , 255);
            bwProcessor.putPixel(j, h-1, 255);
          }

          for (i=0; i<h; i++)
          {
            bwProcessor.putPixel(0,   i, 255);
            bwProcessor.putPixel(w-1, i, 255);
          }
    }
   
   
    // Etapa de an�lisis de la im�gen preprocesada
    buildAnalizer(min, max);
    rt.reset();
    if ( !analizer.analyze(bwImage) )
      throw new ImageUtilsException("The image couldn�t be analyzed.");
     
    int xColumn      = rt.getColumnIndex("X");
    int yColumn      = rt.getColumnIndex("Y");
    int bxColumn    = rt.getColumnIndex("BX");
    int byColumn    = rt.getColumnIndex("BY");
    int xStartColumn  = rt.getColumnIndex("XStart");
    int yStartColumn  = rt.getColumnIndex("YStart");
    int areaColumn    = rt.getColumnIndex("Area");
   
    float xCentroid[]  = rt.getColumn( xColumn  );
    float yCentroid[]  = rt.getColumn( yColumn  );
    float bx[]      = rt.getColumn( bxColumn );
    float by[]      = rt.getColumn( byColumn );
    float xStarts[]    = rt.getColumn( xStartColumn );
    float yStarts[]    = rt.getColumn( yStartColumn );
    float areas[]    = rt.getColumn( areaColumn );

    if xCentroid  == null  ||
        yCentroid  == null  ||
        bx      == null  ||
        by      == null  ||
        areas    == null  )
      throw new ImageUtilsException("The results table couldn't be read.");
   
    recognizedShapes = new RecognizedShape[ xCentroid.length ];
   
    // Aplicar "Wand Tool"
    Wand wandTool = new Wand( bwImage.getProcessor() );
    for (int i=0; i<xCentroid.length; i++)
    {

      wandTool.autoOutline( (int)xStarts[i] , (int)yStarts[i] );
     
      recognizedShapes[i] = new RecognizedShapexCentroid[i,
                            yCentroid[i,
                            bx[i]      ,
                            by[i]      ,
                            areas[i]    ,
                            color      ,
                            wandTool.xpoints,
                            wandTool.ypoints,
                            wandTool.npoints
                                  );
    }
   
    return recognizedShapes;
   
  }
 
 
  /**
   * Retorna el conjunto de figuras (objetos) reconocidos por
   * {@link #recognizedShapes}.
   * @return figuras reconocidas.
   */
  public synchronized RecognizedShape[] getRecognizedShapes()
  {
    return recognizedShapes;
  }
 

  /**
   * Convierte una imagen AWT en otra imagen SWT.
   * @param bufferedImage    imagen AWT.
   * @return          imagen SWT.
   */
  public static ImageData convertToSWT(BufferedImage bufferedImage)
  {
    if (bufferedImage.getColorModel() instanceof DirectColorModel)
    {
      DirectColorModel colorModel = (DirectColorModel) bufferedImage.getColorModel();
      PaletteData palette = new PaletteDatacolorModel.getRedMask(),
                          colorModel.getGreenMask(),
                          colorModel.getBlueMask());
      ImageData data = new ImageDatabufferedImage.getWidth(),
                      bufferedImage.getHeight(),
                      colorModel.getPixelSize(),
                      palette);
      WritableRaster raster = bufferedImage.getRaster();
     
      int[]  pixelArray  = new int[3];
      RGB    rgb      = new RGB(0,0,0);
     
      for (int y = 0; y < data.height; y++)
      {
        for (int x = 0; x < data.width; x++)
        {
          raster.getPixel(x, y, pixelArray);
         
          rgb.red    = pixelArray[0];
          rgb.green  = pixelArray[1];
          rgb.blue  = pixelArray[2];
         
          data.setPixel(x, y, palette.getPixel( rgb ) );
        }
      }
      return data;
    }
   
    return null;
  }
 
 
  /**
   * Almacena una imagen AWT en un archivo en disco. Este m�todo
   * suele utilizarse para fines de <i>debugging</i>, ya que no
   * presenta un buen desempe�o.
   * @param image  imagen AWT.
   * @param name  nombre del archivo en disco.
   */
  public static void saveImage(Image image, String name)
    {
    if ( image == null )
      return;
        int w = image.getWidth(null);
        int h = image.getHeight(null);
       
        BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = bi.createGraphics();
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
        try
        {
            ImageIO.write(bi, "jpg", new File(name));
        }
        catch(IOException e)
        { }
    }

 
  /**
   * Retorna el color promedio del �rea definida por el extremo superior
   * izquierdo en <i>(x,y)</i>, y de ancho y alto <i>w</i> y <i>h</i>,
   * respectivamente.
   * @param id  imagen SWT.
   * @param x    coordenada x del extremo superior izquierdo del �rea.
   * @param y    coordenada y del extremo superior izquierdo del �rea.
   * @param w    ancho del �rea.
   * @param h    alto del �rea.
   * @return    componentes RGB del color promedio.
   */
  public static int[] getAverageColor(ImageData id, int x, int y, int w, int h)
  {
    int[]  pixline  = new int[w];
    int[]  pixels  = new int[w*h];
    int    k    = 0;
   
    for (int line=y; line<y+h; line++)
    {
      id.getPixels(x, line, w, pixline, 0);
      for (int pix=0; pix<pixline.length; pix++, k++)
        pixels[k] = pixline[pix];
    }
   
    // Se busca la mediana
    Arrays.sort( pixels );
    RGB rgb = id.palette.getRGB( pixels[pixels.length/2] );

    return new int[] { rgb.red , rgb.green , rgb.blue };
  }

}
TOP

Related Classes of utils.images.ImageUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.