public GaussFilter(int size, float sigma, ISet <ColorChannelEnum> colorChannelsToFilter) { this.size = size; this.sigma = sigma; this.colorChannelsToFilter = colorChannelsToFilter; convolutionMatrix = FilterBankUtil.generateNormalizedGaussConvolutionMatrix(sigma, size); }
public virtual ImageDescription filter(ImageDescription inputImage) { inputImage.computeGrayscale(); int imageSizeX = inputImage.sizeX; int imageSizeY = inputImage.sizeY; byte[,] inputGray = inputImage.gray; byte[,] outputGray = new byte[imageSizeY, imageSizeX]; // 1. Gauss float[,] gaussConvolutionMatrix = FilterBankUtil.generateNormalizedGaussConvolutionMatrix(sigma, 5); float[,] gaussResult = ImageDescriptionUtil.mirroredMarginConvolution(inputGray, gaussConvolutionMatrix); // 2. Gradient float[,] dx = ImageDescriptionUtil.mirroredMarginConvolution(gaussResult, FilterBankUtil.normalizedSobelX); float[,] dy = ImageDescriptionUtil.mirroredMarginConvolution(gaussResult, FilterBankUtil.normalizedSobelY); // 3. Gradient Amplitude float[,] amplitudeResult = new float[imageSizeY, imageSizeX]; for (int i = 0; i < imageSizeY; i++) { for (int j = 0; j < imageSizeX; j++) { amplitudeResult[i, j] = (float)Math.Sqrt(dx[i, j] * dx[i, j] + dy[i, j] * dy[i, j]); } } for (var i = 0; i < imageSizeY; i++) { for (var j = 0; j < imageSizeX; j++) { if (amplitudeResult[i, j] < 255) { outputGray[i, j] = (byte)(amplitudeResult[i, j] + 0.5f); } else { outputGray[i, j] = 255; } } } ImageDescription outputImage = new ImageDescription(); outputImage.sizeX = imageSizeX; outputImage.sizeY = imageSizeY; foreach (ColorChannelEnum colorChannel in Enum.GetValues(typeof(ColorChannelEnum))) { outputImage.setColorChannel(colorChannel, inputImage.getColorChannel(colorChannel)); } outputImage.setColorChannel(ColorChannelEnum.Sobel, outputGray); return(outputImage); }
public virtual ImageDescription filter(ImageDescription inputImage) { inputImage.computeGrayscale(); int imageSizeX = inputImage.sizeX; int imageSizeY = inputImage.sizeY; byte[,] inputGray = inputImage.gray; byte[,] outputGray = new byte[imageSizeY, imageSizeX]; float[,] gaussConvolutionMatrix = FilterBankUtil.generateNormalizedGaussConvolutionMatrix(sigma, 7); float[,] gaussResult = ImageDescriptionUtil.mirroredMarginConvolution(inputGray, gaussConvolutionMatrix); List <float[, ]> templates = FilterBankUtil.normalizedKirschTemplates; List <float[, ]> results = new List <float[, ]>(templates.Count); foreach (float[,] template in templates) { results.Add(ImageDescriptionUtil.mirroredMarginConvolution(gaussResult, template)); } float[,] amplitudeResult = new float[imageSizeY, imageSizeX]; int[,] anglesResult = new int[imageSizeY, imageSizeX]; for (int i = 0; i < imageSizeY; i++) { for (int j = 0; j < imageSizeX; j++) { int direction = 0; float maxValue = 0; for (int templateIndex = 0; templateIndex < templates.Count; templateIndex++) { float value = results[templateIndex][i, j]; if (value > maxValue) { maxValue = value; direction = templateIndex; } } amplitudeResult[i, j] = maxValue; anglesResult[i, j] = direction; } } if (!applyNms) { for (var i = 0; i < imageSizeY; i++) { for (var j = 0; j < imageSizeX; j++) { if (amplitudeResult[i, j] < 255) { outputGray[i, j] = (byte)(amplitudeResult[i, j] + 0.5f); } else { outputGray[i, j] = 255; } } } } else { float[,] nmsResult = new float[imageSizeY, imageSizeX]; for (int i = 0; i < imageSizeY; i++) { for (int j = 0; j < imageSizeX; j++) { int angle = anglesResult[i, j]; if (angle == 2 || angle == 6) { if ((i == 0 || amplitudeResult[i, j] >= amplitudeResult[i - 1, j]) && (i == imageSizeY - 1 || amplitudeResult[i, j] > amplitudeResult[i + 1, j])) { nmsResult[i, j] = amplitudeResult[i, j]; } } else { if (angle == 1 || angle == 5) { if ((i == 0 || j == imageSizeX - 1 || amplitudeResult[i, j] >= amplitudeResult[i - 1, j + 1]) && (i == imageSizeY - 1 || j == 0 || amplitudeResult[i, j] > amplitudeResult[i + 1, j - 1])) { nmsResult[i, j] = amplitudeResult[i, j]; } } else { if (angle == 3 || angle == 7) { if ((i == 0 || j == 0 || amplitudeResult[i, j] >= amplitudeResult[i - 1, j - 1]) && (i == imageSizeY - 1 || j == imageSizeX - 1 || amplitudeResult[i, j] > amplitudeResult[i + 1, j + 1])) { nmsResult[i, j] = amplitudeResult[i, j]; } } else { if ((j == 0 || amplitudeResult[i, j] >= amplitudeResult[i, j - 1]) && (j == imageSizeX - 1 || amplitudeResult[i, j] > amplitudeResult[i, j + 1])) { nmsResult[i, j] = amplitudeResult[i, j]; } } } } } } float[,] hysteresisResult = new float[imageSizeY, imageSizeX]; bool[,] retainedPositions = applyHysteresisThreshold(nmsResult, imageSizeX, imageSizeY); for (var i = 0; i < imageSizeY; i++) { for (var j = 0; j < imageSizeX; j++) { if (retainedPositions[i, j]) { hysteresisResult[i, j] = nmsResult[i, j]; } } } for (var i = 0; i < imageSizeY; i++) { for (var j = 0; j < imageSizeX; j++) { if (hysteresisResult[i, j] < 255) { outputGray[i, j] = (byte)(hysteresisResult[i, j] + 0.5f); } else { outputGray[i, j] = 255; } } } } ImageDescription outputImage = new ImageDescription(); outputImage.sizeX = imageSizeX; outputImage.sizeY = imageSizeY; foreach (ColorChannelEnum colorChannel in Enum.GetValues(typeof(ColorChannelEnum))) { outputImage.setColorChannel(colorChannel, inputImage.getColorChannel(colorChannel)); } outputImage.setColorChannel(ColorChannelEnum.Kirsch, outputGray); return(outputImage); }
public virtual ImageDescription filter(ImageDescription inputImage) { inputImage.computeGrayscale(); int imageSizeX = inputImage.sizeX; int imageSizeY = inputImage.sizeY; byte[,] inputGray = inputImage.gray; byte[,] outputGray = new byte[imageSizeY, imageSizeX]; // 1. Gauss float[,] gaussConvolutionMatrix = FilterBankUtil.generateNormalizedGaussConvolutionMatrix(sigma, 5); float[,] gaussResult = ImageDescriptionUtil.mirroredMarginConvolution(inputGray, gaussConvolutionMatrix); // 2. Gradient float[,] dx = ImageDescriptionUtil.mirroredMarginConvolution(gaussResult, FilterBankUtil.normalizedSobelX); float[,] dy = ImageDescriptionUtil.mirroredMarginConvolution(gaussResult, FilterBankUtil.normalizedSobelY); // 3. Gradient Amplitude float[,] amplitudeResult = new float[imageSizeY, imageSizeX]; for (int i = 0; i < imageSizeY; i++) { for (int j = 0; j < imageSizeX; j++) { amplitudeResult[i, j] = (float)Math.Sqrt(dx[i, j] * dx[i, j] + dy[i, j] * dy[i, j]); } } // 4. Angle of gradient float[,] anglesResult = new float[imageSizeY, imageSizeX]; for (int i = 0; i < imageSizeY; i++) { for (int j = 0; j < imageSizeX; j++) { anglesResult[i, j] = (float)Math.Atan2(dx[i, j], dy[i, j]); } } // 5. Non maximal suppresion float[,] nmsResult = new float[imageSizeY, imageSizeX]; for (int i = 1; i < imageSizeY - 1; i++) { for (int j = 1; j < imageSizeX - 1; j++) { float angle = anglesResult[i, j]; if ((angle <= (5 * Math.PI) / 8 && angle > (3 * Math.PI) / 8) || (angle > -(5 * Math.PI) / 8 && angle <= -(3 * Math.PI) / 8)) { if (amplitudeResult[i, j] > amplitudeResult[i - 1, j] && amplitudeResult[i, j] > amplitudeResult[i + 1, j]) { nmsResult[i, j] = amplitudeResult[i, j]; } } else { if (angle <= (3 * Math.PI) / 8 && angle > Math.PI / 8 || angle > -(7 * Math.PI) / 8 && angle <= -(5 * Math.PI) / 8) { if (amplitudeResult[i, j] > amplitudeResult[i - 1, j + 1] && amplitudeResult[i, j] > amplitudeResult[i + 1, j - 1]) { nmsResult[i, j] = amplitudeResult[i, j]; } } else { if (angle <= (7 * Math.PI / 8) && angle > (5 * Math.PI / 8) || angle > -(3 * Math.PI) / 8 && angle < -(Math.PI / 8)) { if (amplitudeResult[i, j] > amplitudeResult[i - 1, j - 1] && amplitudeResult[i, j] > amplitudeResult[i + 1, j + 1]) { nmsResult[i, j] = amplitudeResult[i, j]; } } else { if (amplitudeResult[i, j] > amplitudeResult[i, j - 1] && amplitudeResult[i, j] > amplitudeResult[i, j + 1]) { nmsResult[i, j] = amplitudeResult[i, j]; } } } } } } // 6. Hysteresis thresolding float[,] hysteresisResult = new float[imageSizeY, imageSizeX]; bool[,] retainedPositions = applyHysteresisThreshold(nmsResult, imageSizeX, imageSizeY); for (var i = 0; i < imageSizeY; i++) { for (var j = 0; j < imageSizeX; j++) { if (retainedPositions[i, j]) { hysteresisResult[i, j] = nmsResult[i, j]; } } } for (var i = 0; i < imageSizeY; i++) { for (var j = 0; j < imageSizeX; j++) { if (hysteresisResult[i, j] < 255) { outputGray[i, j] = (byte)(hysteresisResult[i, j] + 0.5f); } else { outputGray[i, j] = 255; } } } ImageDescription outputImage = new ImageDescription(); outputImage.sizeX = imageSizeX; outputImage.sizeY = imageSizeY; foreach (ColorChannelEnum colorChannel in Enum.GetValues(typeof(ColorChannelEnum))) { outputImage.setColorChannel(colorChannel, inputImage.getColorChannel(colorChannel)); } outputImage.setColorChannel(ColorChannelEnum.Canny, outputGray); return(outputImage); }