2012-04-21 13 views
5

Sto programmando un gioco e voglio raccogliere immagini con bordi trasparenti (sprite) su un cerchio.Individuazione dei pixel del bordo di un'immagine con circondamenti trasparenti (per il rilevamento delle colazioni)

È facile sapere se il cerchio si sovrappone all'immagine controllando la colezione con i pixel che non sono trasparenti.

Il problema che ho è conoscere l'angolo normale per fare un rimbalzo.

Avrei bisogno di una libreria (Java) o di un algoritmo che, data un'immagine, restituirebbe una matrice con i pixel che si trovano sul bordo dell'immagine in modo da trovare la pendenza tra due punti della superficie.

C'è uno snippet di libreria/algoritmo/codice da cui posso imparare?

La ringrazio molto

Lau.

risposta

8

Ecco un approccio semplice:

creare una maschera dall'immagine originale dove tutti i pixel trasparenti sono 0 e tutti i pixel non trasparenti sono 1

Poi, eseguire una semplice rilevamento dei bordi la maschera sottraendo ogni pixel (x,y), che sarà 0 o 1, dal pixel (x+1,y+1) e prendendo il valore assoluto.

Questo vi darà un 1 per i pixel sul bordo dell'immagine e uno 0 ovunque.

Nota: questo metodo è essenzialmente equivalente al trattamento dell'immagine come funzione 2D e al calcolo del suo gradiente. I bordi sono ripide parti della superficie di intensità (che corrispondono a grandi valori di sfumatura). Ecco ulteriori informazioni su gradient-based edge detection.


Ecco un'immagine esempio:

Original Test Image

prima maschera tutti i pixel non trasparenti:

Image Mask

Poi spostare l'immagine verso il basso e sopra un pixel e sottrarre da solo

Questo crea l'immagine qui sotto. Ora basta leggere gli indici di matrice con il valore 1.

Questa è la serie di pixel del bordo.

Edge Mask

Nota: se le immagini contengono pixel interne trasparenti, questa tecnica anche trovare bordi interni, che possono o non possono essere un problema per voi ...

3

Questo è ciò che I'v implementato nel tempo: (detectionStrength è meglio 10)

public static List<Pixel> getEdges(Image image, int detectionStrength) { 

    boolean[][] opaque = new boolean[image.getWidth(null)][image 
      .getHeight(null)]; 
    LinkedList<Pixel> edges = new LinkedList<Pixel>(); 
    int rgb; 

    /* 
    * convert to BufferedImage to get individual pixel colors 
    */ 
    BufferedImage bufferedImage; 
    if (image instanceof BufferedImage) 
     bufferedImage = (BufferedImage) image; 
    else { 
     bufferedImage = new BufferedImage(image.getWidth(null), 
       image.getHeight(null), BufferedImage.TYPE_INT_ARGB); 
     bufferedImage.createGraphics().drawImage(image, 0, 0, null); 
    } 

    for (int i = 0; i < opaque.length; i++) { 
     for (int j = 0; j < opaque[i].length; j++) { 
      rgb = bufferedImage.getRGB(i, j); 
      opaque[i][j] = (rgb >> 24 & 0xFF) > detectionStrength; // transparency 
     } 
    } 

    /* 
    * If a pixel is opaque, but is surrounded, with at least one 
    * transparent pixel, it is considered an edge. 
    */ 
    for (int x = 0; x < opaque.length; x++) { 
     for (int y = 0; y < opaque[x].length; y++) { 
      if ((x == 0) || (x == opaque.length - 1) || (y == 0) 
        || (y == opaque[x].length - 1)) { // border pixel 
       if (opaque[x][y]) // if opaque, it is automatically an edge, 
            // no matter its surrounding... 
        edges.add(new Pixel(x, y, new Color(bufferedImage 
          .getRGB(x, y)))); 

      } else { // not a border pixel 
       if (opaque[x][y] 
         && (!opaque[x - 1][y - 1] || !opaque[x][y - 1] 
           || !opaque[x + 1][y - 1] 
           || !opaque[x - 1][y] || !opaque[x + 1][y] 
           || !opaque[x - 1][y + 1] 
           || !opaque[x][y + 1] || !opaque[x + 1][y + 1])) 
        edges.add(new Pixel(x, y, new Color(bufferedImage 
          .getRGB(x, y)))); 
      } 
     } 
    } 

    return edges; 
} 

E la classe Pixel (solo una semplice estensione del Point):

public class Pixel extends Point implements Cloneable { 

    private static final long serialVersionUID = -9053911985748552077L; 

    public Color color; 

    public Pixel(int x, int y, Color c) { 
     super(x, y); 
     color = c; 
    } 

    public Pixel(Pixel other) { 
     super(other.x, other.y); 
     color = other.color; 
    } 

    public Color getColor() { 
     return color; 
    } 

    public void setColor(Color newColor) { 
     color = newColor; 
    } 

    public int hashCode() { 
     final int prime = 31; 
     int result = super.hashCode(); 
     result = prime * result + ((color == null) ? 0 : color.hashCode()); 
     return result; 
    } 

    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (!super.equals(obj)) 
      return false; 
     if (!(obj instanceof Pixel)) 
      return false; 
     Pixel other = (Pixel) obj; 
     if (color == null) { 
      if (other.color != null) 
       return false; 
     } else if (!color.equals(other.color)) 
      return false; 
     return true; 
    } 

    public Object clone() { 
     return new Pixel(x, y, color); 
    } 

    public String toString() { 
     return "Pixel [color=" + color + ", x=" + x + ", y=" + y + "]"; 
    } 
} 

Il immagine creata con l'algoritmo, sarà:

StackOverflow logo

Problemi correlati