I have image in C# and I created array of that but
for filtering and mask the picture I need 2 dimensional Array of image
thank for your help!
Creating a 2d array from your image, or from your 1d array, is pretty straightforward. Here is the way to do it from your 1d array, although this can be easily translated directly to your image code:
int[][] To2dArray(int[] source, int width)
{
int height = source.Length / width;
int[][] result = new int[height][width];
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
result[i][j] = source[i * width + j];
}
}
return result;
}
Related
I have a 2D short array coming from a C++ library. The array contains the pixels of a 16 bit grayscale image. I am trying to convert it to Base64 to display it. My C# code is as follows:
string picture_path = "~/Picture/CT_Axial_Z/CT_Axial-Z_0111.png";
string path = System.Web.Hosting.HostingEnvironment.MapPath(picture_path);
if (File.Exists(path))
{
IntPtr gpget = Open16BitGrayImage(path);
CImage_DLL gget = (CImage_DLL)Marshal.PtrToStructure(gpget, typeof(CImage_DLL));
int short_size = sizeof(short);
int p_s_cursor = 0;
Array pshImageData = Array.CreateInstance(typeof(short), gget.m_nH, gget.m_nW);
for (int i = 0; i < gget.m_nH; i++)
{
for (int j = 0; j < gget.m_nW; j++)
{
short data = (short)Marshal.PtrToStructure(gget.pshImageData + p_s_cursor, typeof(short));
pshImageData.SetValue(data, i, j);
p_s_cursor += short_size;
}
}
}
I need to convert it to Base64 and display it on a canvas. How should I do it?
I am trying to get the max intensity value and min intensity from an image called btm to get the average from the "max, min", then use this average as a threshold to convert image to binary image.
So I used histogram class from aforge library which takes an int array, so I am trying to convert my image btm to the array but the function ImageToByteArray that I used to convert image return array from byte data type.
System.Drawing.Image img = (System.Drawing.Image)btm;
byte[] imgarr = ImageToByteArray(img);
Histogram h = new Histogram(imgarr);
int Maxval= h.max();
int Minval= h.min();
.
public static byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
using (var ms = new MemoryStream())
{
imageIn.Save(ms, imageIn.RawFormat);
return ms.ToArray();
}
}
I am posting two routines. You can examine them to get an idea regarding how to achieve your task.
Step 1. Convert Bitmap to int[,]:
public static int[,] ToInteger(Bitmap input)
{
//// We are presuming that the image is grayscale.
//// A color image is impossible to convert to 2D.
int Width = input.Width;
int Height = input.Height;
int[,] array2d = new int[Width, Height];
for (int y = 0; y < Height; y++)
{
for (int x = 0; x < Width; x++)
{
Color cl = input.GetPixel(x, y);
// image is Grayscale
// three elements are averaged.
int gray = (int)Convert.ChangeType(cl.R * 0.3 + cl.G * 0.59 + cl.B * 0.11, typeof(int));
array2d[x, y] = gray;
}
}
return array2d;
}
Step 2. Seach for Max and Min.
public int Max(int[,] values)
{
int max = 0;
for (int i = 1; i < values.GetLength(0); i++)
{
for (int j = 1; j < values.GetLength(1); j++)
{
if (values[i,j] > 0)
{
max = values[i, j];
}
}
}
return max;
}
public int Min(int[,] values)
{
... ... ...
if (values[i,j] < 0)
{
min = values[i];
}
... ... ...
return min;
}
You can combine last two.
Hope you get the idea.
Really I'm trying to apply 3X3 Median Filtering by C# and depending on my understanding the concepts of Median Filtering I wrote the following code but when I'm running it the Form hangs. I think have some problem in the last nested for loop but i don't know where is the error or the wrong in applying the Median concepts!
public static Bitmap MedianFiltering(Bitmap bm)
{
List<int> termsList = new List<int>();
Bitmap res, temp;
Color c;
int counter = 0;
//Convert to Grayscale
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
c = bm.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
bm.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
}
}
temp = bm;
//applying Median Filtering
for (int i = 0; i <= temp.Width - 3; i++)
for (int j = 0; j <= temp.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
c = temp.GetPixel(x, y);
termsList.Add(c.R);
counter++;
}
int[] terms = termsList.ToArray();
Array.Sort<int>(terms);
Array.Reverse(terms);
int color = terms[4];
temp.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
counter = 0;
}
res = temp;
return res;
}
Thanks.
You are not clearing the termsList after each pixel processing. This is causing the list to keep growing. Sorting and reversing the list will keep taking longer and longer times. This will also cause incorrect results since you only want to get the median of the 9 pixels related to the current pixel.
Simply clear the list like this:
...
int[] terms = termsList.ToArray();
termsList.Clear();
...
UPDATE:
I did more optimization for the code:
public static void MedianFiltering(Bitmap bm)
{
List<byte> termsList = new List<byte>();
byte[,] image = new byte[bm.Width,bm.Height];
//Convert to Grayscale
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
var c = bm.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
image[i, j] = gray;
}
}
//applying Median Filtering
for (int i = 0; i <= bm.Width - 3; i++)
for (int j = 0; j <= bm.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
termsList.Add(image[x, y]);
}
byte[] terms = termsList.ToArray();
termsList.Clear();
Array.Sort<byte>(terms);
Array.Reverse(terms);
byte color = terms[4];
bm.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
}
}
Please note that in your original method, you returned a Bitmap. I removed this.
Please note that temp = bm; does not create a copy of the Bitmap. It is just pointing the temp variable to the same object (that is pointed by bm). So in your original method, you returned the exact object that is passed in the method parameter. To use the new method pass the Bitmap and then the bitmap it self will be modified (this is also true for your method).
This enhanced performance 4 times on my machine.
What I did is mainly read the bitmap data into a byte array instead of using the Bitmap it self to read/write data multiple times.
If you need to further enhance the performance, take a look at this question.
I find myself converting 1D byte and single arrays to 2D by doing the following. I suspect it is probably as fast as other methods, but perhaps there is a cleaner simpler paradigm? (Linq?)
private static byte[,] byte2D(byte[] input, int height, int width)
{
byte[,] output = new byte[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = input[i * width + j];
}
}
return output;
}
private static Single[,] single2D(byte[] input, int height, int width)
{
Single[,] output = new Single[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = (Single)input[i * width + j];
}
}
return output;
}
This doesn't help with making the code inside the methods cleaner, but I noticed that you have 2 basically identical methods that differ only in their types. I suggest using generics.
This would let you define your method only once. Using the where keyword, you can even limit the kind of types you allow your method to work on.
private static T[,] Make2DArray<T>(T[] input, int height, int width)
{
T[,] output = new T[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
output[i, j] = input[i * width + j];
}
}
return output;
}
You would call this method like this
int[] a; //or any other array.
var twoDArray = Make2DArray(a, height, width);
Buffer.BlockCopy(input, 0, output, 0, input.Length); is faster, but fastest is to not copy the array at all.
If you don't really need a separate 2D array, you can just access your 1D array like a 2D array trough a function, property, or custom type. For example:
class D2<T> {
T[] input;
int lenght0;
public d2(T[] input, int lenght0) {
this.input = input;
this.lenght0 = lenght0;
}
public T this[int index0, int index1] {
get { return input[index0 * this.lenght0 + index1]; }
set { input[index0 * this.lenght0 + index1] = value; }
}
}
...
byte[] input = { 1, 2, 3, 4 };
var output = new D2<byte>(input, 2);
output[1, 1] = 0; // now input is { 1, 2, 3, 0 };
Also, in .NET access to multidimensional arrays is a bit slower than access to jagged arrays
Generic function:
private static b[,] to2D<a, b>(a source, valueAt: Func<a, int, b>, int height, int width)
{
var result = new b[height, width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
result[i, j] = valueAt(source, i * width + j);
}
}
return result;
}
var bytes = to2D<byte[], byte>([], (bytes, at) => bytes[at], 10, 20);
I know I am late to the party, but if you want to access a 1d array, list, etc. like it were an n-dimensional array (without copying) you can use https://github.com/henon/SliceAndDice to do so without copying.
// create a 2D array of bytes from a byte[]
var a = new ArraySlice<byte>( new byte[100], new Shape(10,10));
// now access with 2d coordinates
a[7,9]=(byte)56;
Of course, everyone can do it for simple 2d, 3d, ... nd volumes easily. But this lib also allows to do slicing of n-dimensional arrays without copying.
I have an array that takes a 2D array as input, and flips it. For example:
The input:
0 1 0
0 2 0
0 3 4
The output:
0 3 4
0 2 0
0 1 0
Attached is the method
static double[,] flipArray(double[,] inputArray) {
for (int i = 0; i < (inputArray.Length / 2); i++) {
double temp = inputArray[i,0];
inputArray[i, 0] = inputArray[inputArray.GetLength(0)-i-1,0];
inputArray[inputArray.GetLength(0)-i-1,0] = temp;
}
return inputArray;
}
The error I receive as a result is this:
I am effectively taking the first row, and reversing the order of that, and returning the reversed-row array. Perhaps it is my misunderstanding of some basic syntax of C# as I am primarily a Java developer. Thank you!
Second Edit:
public static void flipInPlace(Object[][] theArray) {
for(int i = 0; i < (theArray.length / 2); i++) {
Object[] temp = theArray[i];
theArray[i] = theArray[theArray.length - i - 1];
theArray[theArray.length - i - 1] = temp;
}
}
The method above was adapted from the above Java method from this thread.
double[,] indicates an array, but you only need to store a single value. Make temp a simple double:
static double[,] flipArray(double[,] inputArray) {
for (int i = 0; i < (inputArray.Length / 2); i++) {
double temp = inputArray[i,0];
inputArray[inputArray.Length - i - 1,0] = temp;
}
return inputArray;
}
But you still have more issues in your code. You'll have to loop through both the rows an the columns. Plus, you'll need to use GetLength(n) instead of just Length. In the end, it should look a bit like this:
static double[,] flipArray(double[,] inputArray) {
int height = inputArray.GetLength(0);
int width = inputArray.GetLength(1);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height / 2; j++) {
double temp = inputArray[j, i];
inputArray[j, i] = inputArray[height - j - 1, i];
inputArray[height - j - 1, i] = temp;
}
}
return inputArray;
}
To get the described result, I would think you'd want something to the effect of this, grabbing each each sub-array rather than an individual element, and remembering to set the value at inputArray[i] as well as inputArray[inputArray.Length - i - 1]:
static double[,] flipArray(double[,] inputArray) {
for (int i = 0; i < (inputArray.Length / 2); i++) {
double[] temp = inputArray[i];
inputArray[i] = inputArray[inputArray.Length - i - 1];
inputArray[inputArray.Length - i - 1] = temp;
}
return inputArray;
}