Java 图像边缘检测算法:创建二维网格

Java 图像边缘检测算法:创建二维网格,java,c#,algorithm,image-processing,xna,Java,C#,Algorithm,Image Processing,Xna,让我们先从我想做的开始。我想能够采取一个透明的背景PNG文件,并找到从90到360点沿图像的主题边缘的任何地方。这里有一个粗略的例子来说明我的意思。鉴于Mario和Yoshi的这张照片: 我想画一个以图像中心为中心,直径略大于图像最大边的圆作为参考。然后,我想以设定的间隔绕着圆走,沿着中心画一条线,直到它碰到一个不透明的像素。下面是它的样子: 我尝试过几次,都失败了,我希望得到一些关于我做错了什么的指导或见解。下面是我在代码后面使用的数学图像(如果质量不好,很抱歉,我没有扫描仪): 线1是

让我们先从我想做的开始。我想能够采取一个透明的背景PNG文件,并找到从90到360点沿图像的主题边缘的任何地方。这里有一个粗略的例子来说明我的意思。鉴于Mario和Yoshi的这张照片:

我想画一个以图像中心为中心,直径略大于图像最大边的圆作为参考。然后,我想以设定的间隔绕着圆走,沿着中心画一条线,直到它碰到一个不透明的像素。下面是它的样子:

我尝试过几次,都失败了,我希望得到一些关于我做错了什么的指导或见解。下面是我在代码后面使用的数学图像(如果质量不好,很抱歉,我没有扫描仪):

线1是图像的上、下、左或右边缘,线2以给定角度穿过圆心。第1行和第2行相交的点应该在图像的边缘,并且是我们应该开始寻找图像主体边缘的位置

这是我从这个想法中得到的代码。我是用Java实现的,因为BuffereImage非常容易使用,但我将把它转换成C#(XNA)作为最终产品

public class Mesh {

private int angleA, angleB, angleC, angleD;
private BufferedImage image;
private Point center;
public ArrayList<Point> points = new ArrayList<>();

public Mesh(BufferedImage image) {
    center = new Point(image.getWidth() / 2, image.getHeight() / 2);
    angleA = (int) (Math.atan(center.y / center.x) * (180 / Math.PI));
    angleB = 180 - angleA;
    angleC = 180 + angleA;
    angleD = 360 - angleA;
    this.image = image;
    for(int angle = 0; angle <= 360; angle+=4){
        Point point = getNext(angle);
        if(point != null) points.add(point);
    }
}

private Point getNext(int angle) {
    double radians = angle * Math.PI / 180;
    double xStep = Math.cos(radians);
    double yStep = Math.sin(radians);
    int addX = angle >= 90 && angle <= 270 ? 1 : -1;
    int addY = angle >= 0 && angle <= 180 ? 1 : -1;
    double x, y;

    if (xStep != 0) {
        double slope = yStep / xStep;
        double intercept = center.y - (slope * center.x);
        if (angle >= angleA && angle <= angleB) {
            y = 0;
            x = -intercept / slope;
        } else if (angle > angleB && angle < angleC) {
            x = 0;
            y = intercept;
        } else if (angle >= angleC && angle <= angleD) {
            y = image.getHeight() - 1;
            x = (y - intercept) / slope;
        } else {
            x = image.getWidth() - 1;
            y = slope * x + intercept;
        }
    } else {
        x = center.x;
        y = angle <= angleB ? 0 : image.getHeight();
    }

    if (x < 0) x = 0;
    if (x > image.getWidth() - 1) x = image.getWidth() - 1;
    if (y < 0) y = 0;
    if (y > image.getHeight() - 1) y = image.getHeight() - 1;

    double distance = Math.sqrt(Math.pow(x - center.x, 2) + Math.pow(y - center.y, 2));
    double stepSize = Math.sqrt(Math.pow(xStep, 2) + Math.pow(yStep, 2));
    int totalSteps = (int) Math.floor(distance / stepSize);

    for (int step = 0; step < totalSteps; step++) {
        int xVal = (int) x;
        int yVal = (int) y;
        if(xVal < 0) xVal = 0;
        if(xVal > image.getWidth() -1) xVal = image.getWidth() -1;
        if(yVal < 0) yVal = 0;
        if(yVal > image.getHeight()-1) yVal = image.getHeight() -1;
        int pixel = image.getRGB(xVal, yVal);

        if ((pixel >> 24) == 0x00) {
            x += (Math.abs(xStep) * addX);
            y += (Math.abs(yStep) * addY);
        } else {
            return new Point(xVal, yVal);
        }
    }
    return null;
}
}
公共类网格{
私人int angleA、angleB、angleC、angleD;
私有缓冲图像;
私人点中心;
public ArrayList points=new ArrayList();
公共网格(BuffereImage图像){
中心=新点(image.getWidth()/2,image.getHeight()/2);
angleA=(int)(Math.atan(center.y/center.x)*(180/Math.PI));
角度b=180-角度a;
角度c=180+角度a;
角度=360-角度A;
这个图像=图像;
对于(内部角度=0;角度=90&&angle=0&&angle=angleA&&angle角度B&&angle=angleC&&angle image.getHeight()-1)y=image.getHeight()-1;
双距离=Math.sqrt(Math.pow(x-center.x,2)+Math.pow(y-center.y,2));
双步长=Math.sqrt(Math.pow(xStep,2)+Math.pow(yStep,2));
int totalSteps=(int)数学楼层(距离/步长);
对于(int step=0;stepimage.getWidth()-1)xVal=image.getWidth()-1;
如果(yVal<0)yVal=0;
如果(yVal>image.getHeight()-1)yVal=image.getHeight()-1;
int pixel=image.getRGB(xVal,yVal);
如果((像素>>24)=0x00){
x+=(Math.abs(xStep)*addX);
y+=(数学绝对值(yStep)*addY);
}否则{
返回新点(xVal,yVal);
}
}
返回null;
}
}

该算法应该返回所有按逆时针方向旋转(且不重叠)排序的正点,但我未能获得所需的输出(这是我最近的一次尝试),因此,重申一下这个问题,是否有一种形式化的方法可以做到这一点,或者有人能找到我在逻辑中犯的错误。对于视觉参考,Mario和Yoshi跟踪的图像在某种程度上是最终输出的样子,但具有更多的点(这将为网格提供更多细节)。

问题是否与边界圆的确定或会聚光线的跟踪有关?对于第二部分,你应该考虑使用BReSENAMM线绘制算法。我希望光线在边界圆上开始,然后在图像主体的边缘结束。我们希望这些点都是有序的,这样它们就可以成为图像的网格。这是在你的帖子中说的,你不回答我的问题。找到圆不是问题,我很难找到“网格”,有时点是负数或穿过中心,它不是看起来像一个轮廓线,是与边界圆的确定或会聚光线的跟踪有关的问题吗?对于第二部分,你应该考虑使用BReSENAMM线绘制算法。我希望光线在边界圆上开始,然后在图像主体的边缘结束。我们希望这些点都是有序的,这样它们就可以成为图像的网格。这是在你的帖子中说的,你不回答我的问题。找到圆不是问题,我很难找到“网格”,有时这些点是负数或穿过中心,它看起来不像一个轮廓