matlab bwmorph(img,thin';)在Java中的实现出错

matlab bwmorph(img,thin';)在Java中的实现出错,java,matlab,image-processing,imagej,Java,Matlab,Image Processing,Imagej,我正在Java ImageJ中实现matlab的“bwmorph(img,'thin')”算法。我在网上搜索了很多,发现了一些类似的实现,它们工作得更好,但我在代码中找不到问题所在。有什么想法吗 我的代码: public void run(ImageProcessor ip) { MakeBinary(ip); int sum2 = processThin(ip); int sum = -1; while (sum2 !=

我正在Java ImageJ中实现matlab的“bwmorph(img,'thin')”算法。我在网上搜索了很多,发现了一些类似的实现,它们工作得更好,但我在代码中找不到问题所在。有什么想法吗

我的代码:

    public void run(ImageProcessor ip) {
        MakeBinary(ip);
        int sum2 = processThin(ip);
        int sum = -1;
        while (sum2 != sum) {
            sum = sum2;
            sum2 = processThin(ip);
        }
    }

    public int processThin(ImageProcessor ipOriginal) {
        int sum = 0;
        // first iteration
        ImageProcessor ip = ipOriginal.duplicate();
        for (int i = 1; i < ip.getWidth() -1; i++)
            for (int j = 1; j < ip.getHeight() -1; j++) {
                int[] neighbors = selectNeighbors(ip, i, j);
                if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3(neighbors) == 0)
                    ip.putPixel(i,j, 0);
            }
        // second iteration
        for (int i = 1; i < ip.getWidth() -1; i++)
            for (int j = 1; j < ip.getHeight()-1; j++) {
                int[] neighbors = selectNeighbors(ip, i, j);
                if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3prime(neighbors) == 0)
                    ip.putPixel(i,j, 0);
            }

        for(int i = 0; i < ip.getWidth(); i++)
            for(int j = 0; j < ip.getHeight(); j++) {
                if (ip.getPixel(i,j) != 0) sum++;
                ipOriginal.putPixel(i, j, ip.getPixel(i, j));
            }
        return sum;
    }

    private int G1(int[] input) {
        int xh = 0;
        for (int i = 1; i <= 4; i++) {
            if (input[2 * i - 1] == 0 && (input[2 * i] == 1 || (2 * i + 1 <= 8 ? input[2 * i + 1] == 1 : input[1] == 1)))
                xh += 1;
        }
        return xh;
    }

    private int G2(int[] input) {
        int n1 = 0, n2 = 0;
        n1 = toInt(toBool(input[4]) || toBool(input[3])) + toInt(toBool(input[1]) || toBool(input[2])) +
                toInt(toBool(input[8]) || toBool(input[7])) + toInt(toBool(input[6]) || toBool(input[5]));
        n2 = toInt(toBool(input[2]) || toBool(input[3])) + toInt(toBool(input[1]) || toBool(input[8])) +
                toInt(toBool(input[6]) || toBool(input[7])) + toInt(toBool(input[4]) || toBool(input[5]));
        return Math.min(n1,n2);
    }

    private int G3 (int[] input){
        return toInt((toBool(input[2]) || toBool(input[3]) || !toBool(input[8])) && toBool(input[1]));
    }

    private int G3prime (int[] input){
        return toInt((toBool(input[6]) || toBool(input[7]) || !toBool(input[4])) && toBool(input[5]));
    }

    private boolean toBool(int i ){
        return i == 1;
    }
    private int toInt(boolean i) {
        return i ? 1 : 0;
    }
    private int[] selectNeighbors(ImageProcessor ip, int i, int j) {
        int[] result = new int[9];
        result[1] = ip.getPixel(i+1,j);
        result[2] = ip.getPixel(i+1,j+1);
        result[3] = ip.getPixel(i,j+1);
        result[4] = ip.getPixel(i-1,j+1);
        result[5] = ip.getPixel(i-1,j);
        result[6] = ip.getPixel(i-1,j-1);
        result[7] = ip.getPixel(i,j-1);
        result[8] = ip.getPixel(i+1,j-1);

        for (int x = 0; x < result.length; x++)
            if (result[x] != 0) result[x] = 1;
        return result;
    }

原始代码中的问题是您将代码写入了输入图像。在第一次迭代中,从左向右移动,删除连续的像素,因为在修改前一个像素后,每个像素都有一个背景像素作为邻居

实现细化操作有不同的方法,但最简单的方法(如您的代码)需要在细化的每次迭代中通过两次图像:

  • 浏览图像并标记所有候选像素。这些是具有背景邻居的像素。标记像素可以简单到将像素值设置为给定常数,例如42(假设背景为0,前景为1或255,或您决定的任何值)

  • 再次浏览图像,对于每个标记的像素,确定移除它是否会改变前景的几何结构。如果没有,请将其拆下。在此测试中,将尚未删除的标记像素作为前景


  • 您可以在输入图像中写入内容。因此,在第一次迭代中,从左向右移动,删除连续的像素,因为在修改前一个像素后,每个像素都有一个背景像素作为邻居。要在适当的位置工作,请在一个过程中标记要删除的每个像素,然后在第二个过程中将其设置为背景值。然后重复这个直到幂等。否则,请在每次迭代后写入不同的映像并交换输入/输出缓冲区。@CrisLuengo,谢谢您的回复。这很有帮助!编辑之后,我更接近我想要的。不过,现在我似乎丢失了一些中间像素。你能再看一次吗?我现在将编辑我的问题啊,是的,当决定是否删除一个像素时,你需要查看如果删除所有标记的像素,将保留的像素集。那么:像素在原始图像中是否有背景邻居?如果是,它是否保留了输出图像中的连接?@CrisLuengo,非常感谢!你愿意留下一个答案,我把它标为正确答案吗?
    public int processThin(ImageProcessor ip) {
            int sum = 0;
            // first iteration
            int[][] mask = new int[ip.getWidth()][ip.getHeight()];
            for (int i = 1; i < ip.getWidth() -1; i++)
                for (int j = 1; j < ip.getHeight() -1; j++) {
                    int[] neighbors = selectNeighbors(ip, i, j);
                    if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3(neighbors) == 0)
                        mask[i][j]++;
                }
            // second iteration
            for (int i = 1; i < ip.getWidth() -1; i++)
                for (int j = 1; j < ip.getHeight()-1; j++) {
                    int[] neighbors = selectNeighbors(ip, i, j);
                    if (G1(neighbors) == 1 && G2(neighbors) >= 2 && G2(neighbors) <= 3 && G3prime(neighbors) == 0)
                        mask[i][j]++;
                }
    
            for(int i = 0; i < ip.getWidth(); i++)
                for(int j = 0; j < ip.getHeight(); j++) {
                    if (mask[i][j] != 0) sum++;
                    ip.putPixel(i, j, mask[i][j] > 0 ? 0 : ip.getPixel(i,j));
                }
            return sum;
        }