I am looking to convert the following Python(Numpy and Scipy) code into C#. IronPython isn't an option in my case. The code here is for an image processing program, and is operating on a multidimensional array of floats that represent a grayscale image. It is looking for the cumulative differences between rows and columns and then checking for the 5th and 95th percentile of differences so that it can crop to that.
lower_percentile=5, upper_percentile=95
# row-wise differences
rw = np.cumsum(np.sum(np.abs(np.diff(image, axis=1)), axis=1))
# column-wise differences
cw = np.cumsum(np.sum(np.abs(np.diff(image, axis=0)), axis=0))
# compute percentiles
upper_column_limit = np.searchsorted(cw, np.percentile(cw, upper_percentile), side='left')
lower_column_limit = np.searchsorted(cw, np.percentile(cw, lower_percentile), side='right')
upper_row_limit = np.searchsorted(rw, np.percentile(rw, upper_percentile), side='left')
lower_row_limit = np.searchsorted(rw, np.percentile(rw, lower_percentile), side='right')
What I have so far is some C# code to get the multidimensional array, and I have looked at other solutions. This solution handles the np.diff operation but only for a 1D arrays. I have also looked at solutions for using nested loops operate on 2D arrays like this one. I know that I likely need to combine these approaches, but I am not sure how.
Ultimately, the goal here is to do a somewhat intelligent crop of a multidimensional array before continuing to process it. Looks like this could be used to do the crop once the important area of the array is defined. I am definitely open to other ways of getting there. I currently have the following C# code which returns a multidimensional array:
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Net;
namespace ImageTest
{
class Program
{
static void Main(string[] args)
{
Bitmap img;
WebClient client = new WebClient();
byte[] b = client.DownloadData("https://pixabay.com/static/uploads/photo/2012/11/28/08/56/mona-lisa-67506_960_720.jpg");
using (MemoryStream stream = new MemoryStream(b))
{
img = new Bitmap(Image.FromStream(stream));
}
img = MakeGrayscale(img);
var imgArray = FromGrayscaleToDoubles(img);
//THE CROP NEEDS TO HAPPEN HERE
}
public static Bitmap MakeGrayscale(Bitmap original)
{
//create a blank bitmap the same size as original
Bitmap newBitmap = new Bitmap(original.Width, original.Height);
//get a graphics object from the new image
Graphics g = Graphics.FromImage(newBitmap);
//create the grayscale ColorMatrix
ColorMatrix colorMatrix = new ColorMatrix(
new float[][]
{
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
});
//create some image attributes
ImageAttributes attributes = new ImageAttributes();
//set the color matrix attribute
attributes.SetColorMatrix(colorMatrix);
//draw the original image on the new image
//using the grayscale color matrix
g.DrawImage(original, new Rectangle(0, 0, original.Width, original.Height),
0, 0, original.Width, original.Height, GraphicsUnit.Pixel, attributes);
//dispose the Graphics object
g.Dispose();
return newBitmap;
}
public static double[,] FromGrayscaleToDoubles(Bitmap bitmap)
{
var result = new double[bitmap.Width, bitmap.Height];
for (int x = 0; x < bitmap.Width; x++)
for (int y = 0; y < bitmap.Height; y++)
result[x, y] = (double)bitmap.GetPixel(x, y).R / 255;
return result;
}
}
}