我正在编写游戏,我想用透明边框(精灵)对着圆圈碰撞图像。
通过检查与不透明的像素的碰撞,很容易知道圆是否与图像重叠。
我遇到的问题是要知道正常角度才能弹跳。
我需要一个库(Java)或给定图像的算法,它会返回一个像素位于图像边界的数组,这样我就可以找到表面两点之间的斜率。
我可以从中学习任何库/算法/代码片段吗?
答案 0 :(得分:8)
这是一个简单的方法:
从原始图像创建遮罩,其中所有透明像素均为0
,所有非透明像素均为1
然后,通过从像素(x,y)
中减去每个像素0
(1
或(x+1,y+1)
)并取绝对值,对遮罩执行简单的边缘检测
这会在图片边缘为您提供1
像素,在其他地方为0
。
注意:此方法基本上等同于将图像视为2d函数并计算其渐变。边缘是强度表面的陡峭部分(对应于大的梯度值)。以下是有关gradient-based edge detection的更多信息。
以下是一个示例图片:
首先屏蔽所有非透明像素:
然后将图像向下移动一个像素并从中减去它。
这会创建下面的图像。现在只需读取值为1
的矩阵索引。
这是你的边缘像素数组。
注意:如果您的图片包含内部透明像素,此技术也会找到内部边缘,这对您来说可能是也可能不是问题......
答案 1 :(得分:3)
这是我实施的:(detectionStrength最好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;
}
Pixel类(只是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 + "]";
}
}
使用算法创建的图像将是: