General convolution: doConvolve.
Edge magnitude: doEdgeMag.
The routine will return
horizontal edges (ex
), vertical edges (ey
) or, edge magnitude
(em
). Edge magnitude is calculated from
em = sqrt(ex2 + ey2)
For positive integers the code s>>3
is equivalent to s/8
For negative integers the results are generally different, as
shown by the example Java program test.java
Convolve.java
import java.awt.image.*; import java.awt.color.*; import java.io.*; import javax.imageio.*; import javax.swing.JFrame; public class Convolve { int mask[][]; int scl; boolean scale; int display_mode = 0; int edge_mode; int mr, mc; BufferedImage img; int h1, w1; public Convolve(int mask[][]) { this.mask = mask; mr = mask.length; mc = mask[0].length; scale = false; display_mode = 0; scl = 0; } public void setScale(int scl) { this.scl = scl; scale = true; } public void setDisplayMode(int mode) { display_mode = mode; } public void getLine( int row, int dst[]) { int v, r, g, b; //System.out.format("row %d%n",row); img.getRGB(0, row, w1, 1, dst, 0, w1); for (int i = 0; i < w1; i++) { v = dst[i]; r = (v >> 16) & 0xFF; g = (v >> 8) & 0xFF; b = v & 0xFF; v = (r + g + b) / 3; // gray by averaging the pixels dst[i] = v; } } public void showMatrix(int v[][], String cmt) { int i, j; int nrow = v.length; int ncol = v[0].length; System.out.format("%n%s%n%n",cmt); for (j=0; j<nrow; j++) { for (i=0; i<ncol; i++) { System.out.format("%3d ",v[j][i]); } System.out.format("%n"); } } public BufferedImage doConvolve(BufferedImage in) { int i, j, i1, j1, sum, v, midr, midc; int r, g, b, c; img = in; w1 = img.getWidth(); h1 = img.getHeight(); int maxr = h1 - 1; int maxc = w1 - 1; int type = BufferedImage.TYPE_INT_RGB; BufferedImage outp = new BufferedImage(w1, h1, type); int data[][] = new int[mr][w1]; int val[] = new int[w1]; midr = mr/2; midc = mc/2; for (j=midr; j<mr; j++) getLine(j-midr,data[j]); for (j=0; j<midr; j++) System.arraycopy(data[midr],0,data[j],0,data[j].length); //System.out.println("start main loop ..."); int row = mr - midr; for (j=0; j<h1; j++) { for (i=0; i<w1; i++) { sum = 0; for (j1=0; j1<mr; j1++) { for (i1=0; i1<mc; i1++) { c = i + i1 - midr; try { v = data[j1][c]; } catch(ArrayIndexOutOfBoundsException e) { if (c<0) v = data[j1][0]; else v = data[j1][maxc]; } sum = sum + mask[j1][i1]*v; } } if (scale) sum /= scl; if (display_mode==1) sum = (sum+256)/2; r = g = b = sum; if (display_mode==2) { v = sum; //g = data[midr][i]; g = 0; if (v>0) { r=v; b=0; } else { r=0; b=-v; }; } val[i] = 0xFF000000 | (r << 16) | (g << 8) | b; } outp.setRGB(0, j, w1, 1, val, 0, w1); int [] swp; swp = data[0]; for (j1=1; j1<mr; j1++) data[j1-1] = data[j1]; if (row<h1) { data[mr-1] = swp; getLine(row++,data[mr-1]); } } return outp; } public BufferedImage doEdgeMag(BufferedImage in) { int i, j, i1, j1, sumx, sumy, sum, midr, midc; int r, g, b, c; img = in; w1 = img.getWidth(); h1 = img.getHeight(); int maxr = h1 - 1; int maxc = w1 - 1; int type = BufferedImage.TYPE_INT_RGB; BufferedImage outp = new BufferedImage(w1, h1, type); int mr, mc; mr = mc = 3; int data[][] = new int[mr][w1]; int val[] = new int[w1]; midr = mr/2; midc = mc/2; for (j=midr; j<mr; j++) getLine(j-midr,data[j]); for (j=0; j<midr; j++) System.arraycopy(data[midr],0,data[j],0,data[j].length); int row = mr - midr; int p00,p01,p02,p10,p11,p12,p20,p21,p22; for (j=0; j<h1; j++) { p00 = p01 = data[0][0]; p02 = data[0][1]; p10 = p11 = data[1][0]; p12 = data[1][1]; p20 = p21 = data[2][0]; p22 = data[2][1]; c = 1; for (i=0; i<w1; i++) { sumx = (p02-p00 +((p12-p10)<<1) + p22-p20)/8; sumy = (p20-p00 +((p21-p01)<<1) + p22-p02)/8; if (edge_mode==0) sum = SquareRoot.sqrt(sumx*sumx+sumy*sumy); else if (edge_mode==1) sum = (sumx+256)>>1; else sum = (sumy+256)>>1; r = g = b = sum; val[i] = 0xFF000000 | (r << 16) | (g << 8) | b; p00 = p01; p01 = p02; SquareRoot.sqrt(sumx*sumx+sumy*sumy); p10 = p11; p11 = p12; p20 = p21; p21 = p22; c++; try { p02 = data[0][c]; p12 = data[1][c]; p22 = data[2][c]; } catch(ArrayIndexOutOfBoundsException e) { } } outp.setRGB(0, j, w1, 1, val, 0, w1); int [] swp; swp = data[0]; for (j1=1; j1<mr; j1++) data[j1-1] = data[j1]; if (row<h1) { data[mr-1] = swp; getLine(row++,data[mr-1]); } } return outp; } }
Maintained by John Loomis, updated Tue Oct 29 22:08:13 2013