Skip to content

Instantly share code, notes, and snippets.

@lobrien
Last active December 19, 2015 14:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lobrien/5971032 to your computer and use it in GitHub Desktop.
Save lobrien/5971032 to your computer and use it in GitHub Desktop.
Simple convolution filter: First convert byte[,] to double[,] using .ToRangePlusOrMinusOne() and then use Convolve3x3(). Then convert back to byte[,] using ToBytes()
public static double[,] ToRangePlusOrMinusOne(this byte[,] self)
{
var ySize = self.GetLength(1);
var xSize = self.GetLength(0);
var dArr = new double[ySize, xSize];
for(var y = 0; y < ySize; y++)
{
for(var x = 0; x < xSize; x++)
{
dArr[y, x] = self[y, x].ToRangePlusOrMinusOne();
}
}
return dArr;
}
public static double[] ToRangePlusOrMinusOne(this byte[] self)
{
var newArray = new double[self.Length];
for(int i = 0; i < self.Length; i++)
{
newArray[i] = self[i].ToRangePlusOrMinusOne();
}
return newArray;
}
public static double ToRangePlusOrMinusOne(this byte self)
{
var percent = self * 1.0 / byte.MaxValue;
return 2.0 * (percent - 0.5);
}
/* Convolutes whole array -- copies edge-values to the off-by-one external location
*/
public static double[,] Convolve3x3(this double[,] self, double[,] kernel)
{
var xSize = self.GetLength(1);
var ySize = self.GetLength(0);
var newBlock = new double[ySize, xSize];
for(var y = 0; y < ySize; y++)
{
for(var x = 0; x < xSize; x++)
{
var upY = y == 0 ? y : y - 1;
var leftX = x == 0 ? x : x - 1;
var downY = y == ySize - 1 ? y : y + 1;
var rightX = x == xSize - 1 ? x : x + 1;
double upLeftK = kernel[0, 0] * self[upY, leftX];
double upK = kernel[0, 1] * self[upY, x];
double upRightK = kernel[0, 2] * self[upY, rightX];
double leftK = kernel[1, 0] * self[y, leftX];
double centerK = kernel[1, 1] * self[y, x];
double rightK = kernel[1, 2] * self[y, rightX];
double downLeftK = kernel[2, 0] * self[downY, leftX];
double downK = kernel[2, 1] * self[downY, x];
double downRightK = kernel[2, 2] * self[downY, rightX];
var sum = upLeftK + upK + upRightK + leftK + centerK + rightK + downLeftK + downK + downRightK;
var avg = sum / 9;
avg = avg < 0 ? 0 : avg > 255.0 ? 255 : avg;
newBlock[y, x] = (double)avg;
}
}
return newBlock;
}
/*
Grrr... Can't Range<U,T> because no generic extensions and can't Range<T> because no T - T
How much lovelier would be:
from s in self select low + ((high -low) * (s - Min(self)) / (Max(self) - Min(self)));
*/
public static byte[,] ToBytes(this double[,] self)
{
//No Min and Max extension methods for rect arrays
var selfMin = double.MaxValue;
var selfMax = double.MinValue;
for(var y = 0; y < self.GetLength(0); y++)
{
for(var x = 0; x < self.GetLength(1); x++)
{
if(self[y, x] < selfMin)
{
selfMin = self[y, x];
}
if(self[y, x] > selfMax)
{
selfMax = self[y, x];
}
}
}
var range = byte.MaxValue;
var ary = new byte[self.GetLength(0), self.GetLength(1)];
for(var y = 0; y < self.GetLength(0); y++)
{
for(var x = 0; x < self.GetLength(1); x++)
{
var c = ((range) * (self[y, x] - selfMin) / (selfMax - selfMin));
if(c < byte.MinValue)
{
c = byte.MinValue;
}
if(c > byte.MaxValue)
{
c = byte.MaxValue;
}
ary[y, x] = (byte)c;
}
}
return ary;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment