public static ImageBuffer Convolution(this ImageBuffer buffer, double[,] xKernel, double[,] yKernel, double factor = 1, int bias = 0) { byte[] source = buffer.Bytes; ImageBuffer output = buffer.CloneFormat(); byte[] target = output.Bytes; double blueX, greenX, redX, blueY, greenY, redY; double blueTotal, greenTotal, redTotal; int filterOffset = 1; int calcOffset = 0; int byteOffset = 0; for (int offsetY = filterOffset; offsetY < buffer.Height - filterOffset; offsetY++) { for (int offsetX = filterOffset; offsetX < buffer.Width - filterOffset; offsetX++) { blueX = greenX = redX = 0; blueY = greenY = redY = 0; blueTotal = greenTotal = redTotal = 0.0; byteOffset = offsetY * buffer.Stride + offsetX * 4; for (int filterY = -filterOffset; filterY <= filterOffset; filterY++) { for (int filterX = -filterOffset; filterX <= filterOffset; filterX++) { calcOffset = byteOffset + (filterX * 4) + (filterY * buffer.Stride); blueX += (double)(source[calcOffset + 0]) * xKernel[filterY + filterOffset, filterX + filterOffset]; greenX += (double)(source[calcOffset + 1]) * xKernel[filterY + filterOffset, filterX + filterOffset]; redX += (double)(source[calcOffset + 2]) * xKernel[filterY + filterOffset, filterX + filterOffset]; blueY += (double)(source[calcOffset + 0]) * yKernel[filterY + filterOffset, filterX + filterOffset]; greenY += (double)(source[calcOffset + 1]) * yKernel[filterY + filterOffset, filterX + filterOffset]; redY += (double)(source[calcOffset + 2]) * yKernel[filterY + filterOffset, filterX + filterOffset]; } } blueTotal = Math.Sqrt((blueX * blueX) + (blueY * blueY)); greenTotal = Math.Sqrt((greenX * greenX) + (greenY * greenY)); redTotal = Math.Sqrt((redX * redX) + (redY * redY)); target[byteOffset + 0] = ByteConversion.Bounded(blueTotal); target[byteOffset + 1] = ByteConversion.Bounded(greenTotal); target[byteOffset + 2] = ByteConversion.Bounded(redTotal); target[byteOffset + 3] = 255; } } return(output); }
// See also: http://matlabtricks.com/post-5/3x3-convolution-kernels-with-online-demo#demo public static ImageBuffer Convolution(this ImageBuffer buffer, double[,] kernel, double factor = 1, int bias = 0) { byte[] source = buffer.Bytes; ImageBuffer output = buffer.Fill(Color.Black); byte[] target = output.Bytes; double blue, green, red; int width = kernel.GetLength(0); //int height = kernel.GetLength(1); // ?? wordt (nog?) niet gebruikt (20150101 FH) int matrixOffset = (width - 1) / 2; int calcOffset, byteOffset; for (int offsetY = matrixOffset; offsetY < buffer.Height - matrixOffset; offsetY++) { for (int offsetX = matrixOffset; offsetX < buffer.Width - matrixOffset; offsetX++) { blue = 0; green = 0; red = 0; byteOffset = offsetY * buffer.Stride + offsetX * 4; for (int filterY = -matrixOffset; filterY <= matrixOffset; filterY++) { for (int filterX = -matrixOffset; filterX <= matrixOffset; filterX++) { calcOffset = byteOffset + (filterX * 4) + (filterY * buffer.Stride); blue += (double)(source[calcOffset + 0]) * kernel[filterY + matrixOffset, filterX + matrixOffset]; green += (double)(source[calcOffset + 1]) * kernel[filterY + matrixOffset, filterX + matrixOffset]; red += (double)(source[calcOffset + 2]) * kernel[filterY + matrixOffset, filterX + matrixOffset]; } } blue = factor * blue + bias; green = factor * green + bias; red = factor * red + bias; target[byteOffset + 0] = ByteConversion.Bounded(blue); target[byteOffset + 1] = ByteConversion.Bounded(green); target[byteOffset + 2] = ByteConversion.Bounded(red); target[byteOffset + 3] = 255; } } return(output); }