public void nonMax() { nonMax = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); Graphics2D g = nonMax.createGraphics(); g.setColor(new Color(0, 0, 0, 0)); g.fillRect(0, 0, width, height); g.dispose(); magnitude = new int[height * width]; for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { double xGrad = sX[y][x]; double yGrad = sY[y][x]; double gradMag = Math.hypot(xGrad, yGrad); // perform non-maximal supression double nMag = Math.hypot(sX[y - 1][x], sY[y - 1][x]); double sMag = Math.hypot(sX[y + 1][x], sY[y + 1][x]); double wMag = Math.hypot(sX[y][x - 1], sY[y][x - 1]); double eMag = Math.hypot(sX[y][x + 1], sY[y][x + 1]); double neMag = Math.hypot(sX[y - 1][x + 1], sY[y - 1][x + 1]); double seMag = Math.hypot(sX[y + 1][x + 1], sY[y + 1][x + 1]); double swMag = Math.hypot(sX[y + 1][x - 1], sY[y + 1][x - 1]); double nwMag = Math.hypot(sX[y - 1][x - 1], sY[y - 1][x - 1]); double tmp; /* * An explanation of what's happening here, for those who want * to understand the source: This performs the "non-maximal * supression" phase of the Canny edge detection in which we * need to compare the gradient magnitude to that in the * direction of the gradient; only if the value is a local * maximum do we consider the point as an edge candidate. * * We need to break the comparison into a number of different * cases depending on the gradient direction so that the * appropriate values can be used. To avoid computing the * gradient direction, we use two simple comparisons: first we * check that the partial derivatives have the same sign (1) * and then we check which is larger (2). As a consequence, we * have reduced the problem to one of four identical cases that * each test the central gradient magnitude against the values at * two points with 'identical support'; what this means is that * the geometry required to accurately interpolate the magnitude * of gradient function at those points has an identical * geometry (upto right-angled-rotation/reflection). * * When comparing the central gradient to the two interpolated * values, we avoid performing any divisions by multiplying both * sides of each inequality by the greater of the two partial * derivatives. The common comparand is stored in a temporary * variable (3) and reused in the mirror case (4). * */ if (xGrad * yGrad <= (float) 0 /*(1)*/ ? Math.abs(xGrad) >= Math.abs(yGrad) /*(2)*/ ? (tmp = Math.abs(xGrad * gradMag)) >= Math.abs(yGrad * neMag - (xGrad + yGrad) * eMag) /*(3)*/ && tmp > Math.abs(yGrad * swMag - (xGrad + yGrad) * wMag) /*(4)*/ : (tmp = Math.abs(yGrad * gradMag)) >= Math.abs(xGrad * neMag - (yGrad + xGrad) * nMag) /*(3)*/ && tmp > Math.abs(xGrad * swMag - (yGrad + xGrad) * sMag) /*(4)*/ : Math.abs(xGrad) >= Math.abs(yGrad) /*(2)*/ ? (tmp = Math.abs(xGrad * gradMag)) >= Math.abs(yGrad * seMag + (xGrad - yGrad) * eMag) /*(3)*/ && tmp > Math.abs(yGrad * nwMag + (xGrad - yGrad) * wMag) /*(4)*/ : (tmp = Math.abs(yGrad * gradMag)) >= Math.abs(xGrad * seMag + (yGrad - xGrad) * sMag) /*(3)*/ && tmp > Math.abs(xGrad * nwMag + (yGrad - xGrad) * nMag) /*(4)*/) { magnitude[y * width + x] = gradMag >= MAGNITUDE_LIMIT ? MAGNITUDE_MAX : (int) (MAGNITUDE_SCALE * gradMag); // NOTE: The orientation of the edge is not employed by this // implementation. It is a simple matter to compute it at // this point as: Math.atan2(yGrad, xGrad); } else { magnitude[y * width + x] = 0; } } } ImageIcon icon2 = new ImageIcon(nonMax); lbl2.setIcon(icon2); }