Java 将图像/图形转换为形状
我想知道是否有办法将图像/图形转换为Java 将图像/图形转换为形状,java,image,image-processing,awt,shape,Java,Image,Image Processing,Awt,Shape,我想知道是否有办法将图像/图形转换为形状?例如,我可以将摩托车形状的轮廓转换为形状,以便在Java中使用它吗?我知道你可以用普通的正方形,圆角,多边形等来做,但是有没有办法做一个自定义的形状呢 摩托车.jpg 摩托车-03.png ImageOutline.java 这段代码需要一些耐心(运行时) import java.awt.*; 导入java.awt.image.buffereImage; 导入java.awt.geom.Area; 导入javax.imageio.imageio; 导
形状
?例如,我可以将摩托车形状的轮廓转换为形状
,以便在Java中使用它吗?我知道你可以用普通的正方形,圆角,多边形等来做,但是有没有办法做一个自定义的形状呢 摩托车.jpg
摩托车-03.png
ImageOutline.java
这段代码需要一些耐心(运行时)
import java.awt.*;
导入java.awt.image.buffereImage;
导入java.awt.geom.Area;
导入javax.imageio.imageio;
导入java.io.File;
导入java.util.Date;
导入javax.swing.*;
/*ShutterStock提供的摩托车图像
http://www.shutterstock.com/pic-13585165/stock-vector-travel-motorcycle-silhouette.html */
课堂教学大纲{
公共静态区域getOutline(BuffereImage图像、颜色、布尔包含、整数容差){
面积=新面积();
for(intx=0;x函数getArea\u FastHack
是基于Andrew Thompsons的工作构建的,这非常有帮助。
但是,我的速度应该更快:
(//编辑:还有sloppier)
import java.awt.*;
导入java.awt.geom.Area;
导入java.awt.image.buffereImage;
导入javax.imageio.imageio;
导入java.io.File;
导入java.io.IOException;
/**
*自定义形状
*基于安德鲁·汤普森的课程*
*资料来源:http://stackoverflow.com/questions/7052422/image-graphic-into-a-shape-in-java/7059497#7059497
*@作者塞缪尔·施耐德、安德鲁·汤普森
*
*
*/
类自定义形状{
私有缓冲区映像=空;
/**
*创建具有像素完美精度的区域
*@param color用于绘制自定义形状的颜色
*@param公差颜色公差
*@返回区
*/
公共区域getArea(颜色、整数公差){
if(image==null)返回null;
面积=新面积();
对于(intx=0;x,这里有一些更快但不太准确的东西,对碰撞检查或2D物理很有用
Point[] MakePoly(BufferedImage spr,int d,int angle){
//creates an outline of a transparent image, points are stored in an array
//arg0 - BufferedImage source image
//arg1 - Int detail (lower = better)
//arg2 - Int angle threshold in degrees (will remove points with angle differences below this level; 15 is a good value)
// making this larger will make the body faster but less accurate;
int w= spr.getWidth(null); int h= spr.getHeight(null);
// increase array size from 255 if needed
int[] vertex_x=new int[255], vertex_y=new int[255], vertex_k=new int[255];
int numPoints=0, tx=0,ty=0,fy=-1,lx=0,ly=0; vertex_x[0]=0; vertex_y[0]=0; vertex_k[0]=1;
for (tx=0;tx<w;tx+=d) for (ty=0;ty<h;ty+=1) if((spr.getRGB(tx,ty)>>24) != 0x00 )
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints++; if (fy<0) fy=ty; lx=tx; ly=ty; break; }
for (ty=0;ty<h;ty+=d) for (tx=w-1;tx>=0;tx-=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && ty > ly)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints++; lx=tx; ly=ty; break; }
for (tx=w-1;tx>=0;tx-=d) for (ty=h-1;ty>=0;ty-=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && tx < lx)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints ++; lx=tx; ly=ty; break; }
for (ty=h-1;ty>=0;ty-=d) for (tx=0;tx<w;tx+=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && ty < ly && ty > fy)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints ++; lx=tx; ly=ty; break; }
double ang1,ang2; for (int i=0;i<numPoints-2;i++) {
ang1 = PointDirection(vertex_x[i],vertex_y[i], vertex_x[i+1],vertex_y[i+1]);
ang2 = PointDirection(vertex_x[i+1],vertex_y[i+1], vertex_x[i+2],vertex_y[i+2]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[i+1] = 0; }
ang1 = PointDirection(vertex_x[numPoints-2],vertex_y[numPoints-2], vertex_x[numPoints-1],vertex_y[numPoints-1]);
ang2 = PointDirection(vertex_x[numPoints-1],vertex_y[numPoints-1], vertex_x[0],vertex_y[0]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[numPoints-1] = 0;
ang1 = PointDirection(vertex_x[numPoints-1],vertex_y[numPoints-1], vertex_x[0],vertex_y[0]);
ang2 = PointDirection(vertex_x[0],vertex_y[0], vertex_x[1],vertex_y[1]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[0] = 0;
int n=0;for (int i=0;i<numPoints;i++)if(vertex_k[i]==1)n++;
Point[] poly= new Point[n]; n=0; for (int i=0;i<numPoints;i++) if (vertex_k[i]==1)
{ poly[n]=new Point(); poly[n].x=vertex_x[i]; poly[n].y=h-vertex_y[i];n++;} return poly;
}
double PointDirection(double xfrom,double yfrom,double xto,double yto){
return Math.atan2(yto-yfrom,xto-xfrom)*180/Math.PI ;
}
Point[]MakePoly(buffereImage spr、int d、int angle){
//创建透明图像的轮廓,点存储在阵列中
//arg0-缓冲区映像源映像
//arg1-整数详细信息(较低=较好)
//arg2-整数角度阈值(以度为单位)(将删除角度差低于此级别的点;15是一个好值)
//把这个变大会使身体更快,但精确度更低;
int w=spr.getWidth(null);int h=spr.getHeight(null);
//如果需要,将数组大小从255增加
int[]顶点x=new int[255],顶点y=new int[255],顶点k=new int[255];
int numPoints=0,tx=0,ty=0,fy=-1,lx=0,ly=0;顶点x[0]=0;顶点y[0]=0;顶点k[0]=1;
对于(tx=0;tx24)!=0x00)
{vertex_x[numPoints]=tx;vertex_y[numPoints]=h-ty;vertex_k[numPoints]=1;numPoints++;if(fy>24)!=0x00&&ty>ly)
{vertex_x[numPoints]=tx;vertex_y[numPoints]=h-ty;vertex_k[numPoints]=1;numPoints++;lx=tx;ly=ty;break;}
对于(tx=w-1;tx>=0;tx-=d)对于(ty=h-1;ty>=0;ty-=1)如果((spr.getRGB(tx,ty)>>24)!=0x00&&tx=0;ty-=d)对于(tx=0;tx>24)!=0x00&&tyfy)
{vertex_x[numPoints]=tx;vertex_y[numPoints]=h-ty;vertex_k[numPoints]=1;numPoints++;lx=tx;ly=ty;break;}
双ang1,ang2;用于(int i=0;我能上传一个示例图像并告诉我们在哪里可以看到它吗?最好不要太大的字节或像素大小。如中所示。你是说从光栅位图转换为矢量图形吗?如果你在谷歌搜索“光栅矢量转换算法”,它会给你一些指示。这不容易。你可以uld通过指定几何路径,使用java.awt.geom.Path2D创建您自己的形状,但您的摩托车最终可能看起来像猫或水壶。事实上,我找到了一个。我认为这与我上面描述的相同,但至少您可以看到您在做什么。您可能还可以对程序进行黑客攻击,使其背景更清晰你可以追踪的图像。+1:很酷的解决方案。你提到运行时需要耐心。你知道运行缓慢的主要原因吗?如果是由于创建的区域数量,可以通过采用“扫描线”方法创建更少的矩形来优化它(每个矩形都是包含像素的水平线)?@Adamski上有一个改进(更快)的版本。试试看,看看你的表现如何。
import java.awt.*;
import java.awt.geom.Area;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
/**
* CustomShape
* based on a Class from Andrew Thompson *
* Source: http://stackoverflow.com/questions/7052422/image-graphic-into-a-shape-in-java/7059497#7059497
* @author Samuel Schneider, Andrew Thompson
*
*
*/
class CustomShape {
private BufferedImage image=null;
/**
* Creates an Area with PixelPerfect precision
* @param color The color that is draws the Custom Shape
* @param tolerance The color tolerance
* @return Area
*/
public Area getArea(Color color, int tolerance) {
if(image==null) return null;
Area area = new Area();
for (int x=0; x<image.getWidth(); x++) {
for (int y=0; y<image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x,y));
if (isIncluded(color, pixel, tolerance)) {
Rectangle r = new Rectangle(x,y,1,1);
area.add(new Area(r));
}
}
}
return area;
}
public Area getArea_FastHack() {
//Assumes Black as Shape Color
if(image==null) return null;
Area area = new Area();
Rectangle r;
int y1,y2;
for (int x=0; x<image.getWidth(); x++) {
y1=99;
y2=-1;
for (int y=0; y<image.getHeight(); y++) {
Color pixel = new Color(image.getRGB(x,y));
//-16777216 entspricht RGB(0,0,0)
if (pixel.getRGB()==-16777216) {
if(y1==99) {y1=y;y2=y;}
if(y>(y2+1)) {
r = new Rectangle(x,y1,1,y2-y1);
area.add(new Area(r));
y1=y;y2=y;
}
y2=y;
}
}
if((y2-y1)>=0) {
r = new Rectangle(x,y1,1,y2-y1);
area.add(new Area(r));
}
}
return area;
}
public static boolean isIncluded(Color target, Color pixel, int tolerance) {
int rT = target.getRed();
int gT = target.getGreen();
int bT = target.getBlue();
int rP = pixel.getRed();
int gP = pixel.getGreen();
int bP = pixel.getBlue();
return(
(rP-tolerance<=rT) && (rT<=rP+tolerance) &&
(gP-tolerance<=gT) && (gT<=gP+tolerance) &&
(bP-tolerance<=bT) && (bT<=bP+tolerance) );
}
public CustomShape(String path) {
try {
BufferedImage image = ImageIO.read(new File(path));
this.image = image;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Point[] MakePoly(BufferedImage spr,int d,int angle){
//creates an outline of a transparent image, points are stored in an array
//arg0 - BufferedImage source image
//arg1 - Int detail (lower = better)
//arg2 - Int angle threshold in degrees (will remove points with angle differences below this level; 15 is a good value)
// making this larger will make the body faster but less accurate;
int w= spr.getWidth(null); int h= spr.getHeight(null);
// increase array size from 255 if needed
int[] vertex_x=new int[255], vertex_y=new int[255], vertex_k=new int[255];
int numPoints=0, tx=0,ty=0,fy=-1,lx=0,ly=0; vertex_x[0]=0; vertex_y[0]=0; vertex_k[0]=1;
for (tx=0;tx<w;tx+=d) for (ty=0;ty<h;ty+=1) if((spr.getRGB(tx,ty)>>24) != 0x00 )
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints++; if (fy<0) fy=ty; lx=tx; ly=ty; break; }
for (ty=0;ty<h;ty+=d) for (tx=w-1;tx>=0;tx-=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && ty > ly)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints++; lx=tx; ly=ty; break; }
for (tx=w-1;tx>=0;tx-=d) for (ty=h-1;ty>=0;ty-=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && tx < lx)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints ++; lx=tx; ly=ty; break; }
for (ty=h-1;ty>=0;ty-=d) for (tx=0;tx<w;tx+=1) if((spr.getRGB(tx,ty)>>24) != 0x00 && ty < ly && ty > fy)
{vertex_x[numPoints]=tx; vertex_y[numPoints]=h-ty; vertex_k[numPoints]=1; numPoints ++; lx=tx; ly=ty; break; }
double ang1,ang2; for (int i=0;i<numPoints-2;i++) {
ang1 = PointDirection(vertex_x[i],vertex_y[i], vertex_x[i+1],vertex_y[i+1]);
ang2 = PointDirection(vertex_x[i+1],vertex_y[i+1], vertex_x[i+2],vertex_y[i+2]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[i+1] = 0; }
ang1 = PointDirection(vertex_x[numPoints-2],vertex_y[numPoints-2], vertex_x[numPoints-1],vertex_y[numPoints-1]);
ang2 = PointDirection(vertex_x[numPoints-1],vertex_y[numPoints-1], vertex_x[0],vertex_y[0]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[numPoints-1] = 0;
ang1 = PointDirection(vertex_x[numPoints-1],vertex_y[numPoints-1], vertex_x[0],vertex_y[0]);
ang2 = PointDirection(vertex_x[0],vertex_y[0], vertex_x[1],vertex_y[1]);
if (Math.abs(ang1-ang2) <= angle) vertex_k[0] = 0;
int n=0;for (int i=0;i<numPoints;i++)if(vertex_k[i]==1)n++;
Point[] poly= new Point[n]; n=0; for (int i=0;i<numPoints;i++) if (vertex_k[i]==1)
{ poly[n]=new Point(); poly[n].x=vertex_x[i]; poly[n].y=h-vertex_y[i];n++;} return poly;
}
double PointDirection(double xfrom,double yfrom,double xto,double yto){
return Math.atan2(yto-yfrom,xto-xfrom)*180/Math.PI ;
}