See: Image convolution in spatial domain
The following code achieves Linear convolution in Spatial domain.
public static double[,] ConvolutionSpatial(double[,] paddedImage, double[,] mask, double offset)
{
double min = 0.0;
double max = 1.0;
double factor = GetFactor(mask);
int paddedImageWidth = paddedImage.GetLength(0);
int paddedImageHeight = paddedImage.GetLength(1);
int maskWidth = mask.GetLength(0);
int maskHeight = mask.GetLength(1);
int imageWidth = paddedImageWidth - maskWidth;
int imageHeight = paddedImageHeight - maskHeight;
double[,] convolve = new double[imageWidth, imageHeight];
for (int y = 0; y < imageHeight; y++)
{
for (int x = 0; x < imageWidth; x++)
{
double sum = Sum(paddedImage, mask, x, y);
convolve[x, y] = Math.Min(Math.Max((sum / factor) + offset, min), max);
string str = string.Empty;
}
}
return convolve;
}
public static double Sum(double[,] paddedImage1, double[,] mask1, int startX, int startY)
{
double sum = 0;
int maskWidth = mask1.GetLength(0);
int maskHeight = mask1.GetLength(1);
for (int y = startY; y < (startY + maskHeight); y++)
{
for (int x = startX; x < (startX + maskWidth); x++)
{
double img = paddedImage1[x, y];
double msk = mask1[maskWidth - x + startX - 1, maskHeight - y + startY - 1];
sum = sum + (img * msk);
}
}
return sum;
}
public static double GetFactor(double[,] kernel)
{
double sum = 0.0;
int width = kernel.GetLength(0);
int height = kernel.GetLength(1);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
sum += kernel[x, y];
}
}
return (sum == 0) ? 1 : sum;
}
Its performance is as follows:
image-size kernel-size time-elapsed
------------------------------------------
100x100 3x3 13ms
512x512 3x3 291ms
1018x1280 3x3 1687ms
100x100 100x100 4983ms
512x512 512x512 35624394ms
1018x1280 1018x1280 [practically unusable]
I have two questions:
- Does it look like a descent performance?
- If not, how can I increase performance?