split a splitted string - c#

I wanted to split a splitted string in C#.
Basically, I want to save an image in a form of numbers, here are the code to save it to a number in C# using GetPixel
TextWriter textWriter = new StreamWriter(fileName);
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Color pixel = bmp.GetPixel(x, y);
textWriter.Write(pixel.R + "," + pixel.G + "," + pixel.B + " ");
}
}
and here is a possible result: 252,255,192 252,255,192 252,255,192.
The pixel is separated by a space, and the rgb is separated by a comma.
the problem is when i tried to convert this again into an image, here is my current code to get the rgb of a pixel.
TextReader textReader = new StreamReader(fileName);
string allLine = textReader.ReadLine();
string[] splitPixel = allLine.Split(' ');
string[] splitRGB = null;
for (int i=0; i<splitPixel.Length; i++) {
splitRGB[i] = splitPixel[i].Split(',');
}
and here is the code to set the pixel color
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
byte tempR, tempG, tempB = 0;
tempR = Convert.ToByte(splitRGB[x]);
tempG = Convert.ToByte(splitRGB[x+1]);
tempB = Convert.ToByte(splitRGB[x+2]);
Color pixel = Color.FromArgb(tempR,tempG,tempB);
bmp.SetPixel(x, y, pixel);
}
}
Right now it's only telling me this error "Cannot implicitly convert type 'string[]' to 'string'" for the
splitRGB[i] = splitPixel[i].Split(',')

string[] splitPixel = allLine.Split(' ');
string[] splitRGB = new string[splitPixel.Length * 3];
for (int i=0; i<splitRGB.Length; i+=3) {
string[] splitted = splitPixel[i].Split(',');
splitRGB[i] = splitted[0];
splitRGB[i + 1] = splitted[1];
splitRGB[i + 2] = splitted[2];
}
EDIT: Here is a better version:
You should save the width and height of your image in the file (ie: 2x2 images have the same file format as 4*1 images), here I suggest that you save them in the first line as width height
using (TextReader textReader = new StreamReader(fileName)){
string sizeLine = textReader.ReadLine();
if (sizeLine == null)
throw new /*UnexpectedData*/Exception("invalid file!");
string[] widthHeightStr = sizeLine.Split(' ');
if (widthHeightStr.Length != 2)
throw new /*UnexpectedData*/Exception("invalid file!");
int width = int.Parse(widthHeightStr[0]);
int height = int.Parse(widthHeightStr[1]);
string pixelsLine = textReader.ReadLine();
if (onlyLine == null)
throw new /*UnexpectedData*/Exception("invalid file!");
string[] splitPixel = pixelsLine.Split(' ');
var bmp = new Bitmap(width, height);
for (int i=0; i<splitPixel.Length; i++) {
string[] splitted = splitPixel[i].Split(',');
if (splitted.Length != 3)
throw new /*UnexpectedData*/Exception("invalid file!");
int tempR = int.Parse(splitted[0]);
int tempG = int.Parse(splitted[1]);
int tempB = int.Parse(splitted[2]);
Color pixel = Color.FromArgb(tempR,tempG,tempB);
bmp.SetPixel(i / width, i % width, pixel);
}
}
EDIT:
using (TextWriter textWriter = new StreamWriter(fileName){
textWriter.WriteLine(bmp.Width + " " + bmp.Height);
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
Color pixel = bmp.GetPixel(x, y);
textWriter.Write(pixel.R + "," + pixel.G + "," + pixel.B + " ");
}
}
}

the error is simply explained you are trying to put an array (since split returns an array) in a string since splitRGB[i] is a string where as splitRGB[] = splitPixel[i].Split(','); or splitRGB[i][] = splitPixel[i].Split(','); <- where splitRGB[][] = new splitRGB[10][3] would work
so your code:
for (int i=0; i<splitPixel.Length; i++)
{
splitRGB[i] = splitPixel[i].Split(',');
}
if you want to put an array in a array you need multi-dimensional arrays like so:
string[][] splitRGB = new string[splitPixel.Length][3];
and the for loop to get your RGB values in
for (int i=0; i
for (int x = 0; x < bmp.Width; x++)
{
for (int y = 0; y < bmp.Height; y++)
{
byte tempR, tempG, tempB = 0;
tempR = Convert.ToByte(splitRGB[x][0]);
tempG = Convert.ToByte(splitRGB[x][1]);
tempB = Convert.ToByte(splitRGB[x][2]);
Color pixel = Color.FromArgb(tempR,tempG,tempB);
bmp.SetPixel(x, y, pixel);
}
}
the changes are very subtle and i've got the feeling i have made a mistake my self (i never use multi dimensional arrays i create arrays of structs or classes as much as i can)

Since i dont know what you do with the bitmap,i present you with another way to get the bitmap data to file and back in one go(you can split this to acomodate your needs).
I replace setPixel and GetPixel because they are too slow of a way to access the data,this will provide much faster outcome:
//assume you have a class member variable of type bitmap called sourceBitmap.
BitmapData sourceData = sourceBitmap.LockBits(new Rectangle(0, 0,
sourceBitmap.Width, sourceBitmap.Height),
ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
File.WriteAllBytes(#"C:\..\..\test.txt", pixelBuffer);
//here is where you can split the code...
byte[] fs = File.ReadAllBytes(#"C:\..\..\test.txt");
Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle(0, 0,
resultBitmap.Width, resultBitmap.Height),
ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(fs, 0, resultData.Scan0, fs.Length);
resultBitmap.UnlockBits(resultData);
pictureBox1.Image = resultBitmap;

Related

Parallize elementwise matrix (2dArray) calculations

This is my first question and I'm relatively new to C#. (Excuse my bad English)
I'm writing a template matching algorithm in C# using the .NET Framework with a WindowsForms Application in Visual Studio. Sadly the new indices and ranges functions from C#8.0, especially the range operator (..), didn't get implemented in the .NET Framework. I know there is a workaround for this as you can see in this thread but it is not supported by Microsoft. So I'm searching for another way to parallelize my elementwise 2dArray (matrix) calculations to make my program faster.
In my program, I'm calculating the differential square (ds) of an area (with the size of my template) inside a 2dArray (my image) and a 2dArray (my template). These values a written to a new 2dAary (DS) which holds all differential squares in the corresponding positions to the image. I can search the indices of DS where the differential square is minimal which is equal to the matching position (highest correspondence between template and image) of the template inside the image.
In python the calculation of DS is very quick using the index range operator (:) and will look like this:
H,W = I.shape # read out Height H & Width W from Image I
h,w = T.shape # read out Height h & Width w from Template T
for i in range(H-h+1):
for j in range(W-w+1):
DS[i,j] = np.sum((I[i:i+h,j:j+w] - T)**2)
But in C# I have to make the calculation of DS elementwise therefore it looks like this and takes for ever:
int Tw = template.Width;
int Th = template.Height;
int Iw = image.Width;
int Ih = image.Height;
int d = 0;
int[,] ds = new int[Tw, Th];
int[,] DS = new int[Iw - Tw + 1, Ih - Th + 1];
for (int y = 0; y < Ih - Th + 1; y++)
{
for (int x = 0; x < Iw - Tw + 1; x++)
{
for (int yT = 0; yT < Th; yT++)
{
for (int xT = 0; xT < Tw; xT++)
{
d = I[x + xT, y + yT] - T[xT, yT];
ds[xt, yt] = d * d;
}
}
int sum = ds.Cast<int>().Sum();
DS[x, y] = sum;
}
}
I know that I could use threads but that would be a little complex for me.
Or maybe I could use CUDA with my Nvidia GPU to speed things up a little.
But I am asking you and myself is there another way to parallelize (optimize) my elementwise 2dArray calculations?
I look forward to any help.
Many thanks in advance!!!
EDIT:
Here I have a working example of my code for a .NET Framework Console App. As you can see I make a lot of elementwise 2d and 3d Array calculations which I would like to process in parallel (or perform them faster in any other way):
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TemplateMatcher_Console
{
class Program
{
public static int[,,] bitmapToMatrix(Bitmap bmp)
{
int[,,] I = new int[bmp.Width, bmp.Height, 3];
for (int y = 0; y < bmp.Height; y++)
{
for (int x = 0; x < bmp.Width; x++)
{
Color pix = bmp.GetPixel(x, y);
I[x, y, 0] = Convert.ToInt32(pix.R);
I[x, y, 1] = Convert.ToInt32(pix.G);
I[x, y, 2] = Convert.ToInt32(pix.B);
}
}
return I;
}
public static int[] indexOfMiniumValue(int[,] matrix)
{
int value = 0;
int minValue = 999999999;
int minFirstIndex = 0;
int minSecondIndex = 0;
int[] ij = new int[2];
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
value = matrix[i, j];
if (value < minValue)
{
minValue = value;
minFirstIndex = i;
minSecondIndex = j;
}
}
}
ij[0] = minFirstIndex;
ij[1] = minSecondIndex;
return ij;
}
public static void Print2DArray<T>(T[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
Console.Write(matrix[i, j] + "\t");
}
Console.WriteLine();
}
}
static void Main(string[] args)
{
// Deklaration & Eingabe
Console.WriteLine("Type the filepath for your image and then press Enter");
string im = Console.ReadLine();
Console.WriteLine("\nType the filepath for your template and then press Enter");
string temp = Console.ReadLine();
Bitmap template = new Bitmap(#temp);
Bitmap image = new Bitmap(#im);
int Tw = template.Width;
int Th = template.Height;
int Iw = image.Width;
int Ih = image.Height;
int[,] ds = new int[Tw, Th];
int[,] DS = new int[Iw - Tw + 1, Ih - Th + 1];
int[,,] DS_rgb = new int[Iw - Tw + 1, Ih - Th + 1, 3];
int[] xy = new int[2];
// Verarbeitung
// int[,,] I = Array.ConvertAll(image_I, new Converter<byte, int>(Convert.ToInt32));
int[,,] I = bitmapToMatrix(image);
int[,,] T = bitmapToMatrix(template);
for (int rgb = 0; rgb < 3; rgb++)
{
for (int y = 0; y < Ih - Th + 1; y++)
{
for (int x = 0; x < Iw - Tw + 1; x++)
{
//DS_rgb[x, y, rgb] = (I[x .. x + template.Width, y .. y + template.Height, rgb] - T[0 .. template.Width, 0 .. template.Height, rgb]);
for (int yT = 0; yT < Th; yT++)
{
for (int xT = 0; xT < Tw; xT++)
{
ds[xT, yT] = (I[x + xT, y + yT, rgb] - T[xT, yT, rgb]) * (I[x + xT, y + yT, rgb] - T[xT, yT, rgb]);
}
}
int sum = ds.Cast<int>().Sum();
DS_rgb[x, y, rgb] = sum;
}
}
}
//DS[.., ..] = DS_rgb[.., .., 0] + DS_rgb[.., .., 1] + DS_rgb[.., .., 2];
for (int y = 0; y < Ih - Th + 1; y++)
{
for (int x = 0; x < Iw - Tw + 1; x++)
{
DS[x, y] = DS_rgb[x, y, 0] + DS_rgb[x, y, 1] + DS_rgb[x, y, 2];
}
}
//xy = DS.FindIndex(z => z == Math.Min(DS));
xy = indexOfMiniumValue(DS);
// Ausgabe
// Ausgeben der Matrix DS
/*
Console.WriteLine("\nMatrix with all differtial squares:");
Print2DArray(DS);
*/
Console.WriteLine($"\nPosition of your template in your image (upper left corner): ({xy[0]}, {xy[1]})");
Console.Write("\nPress any key to close the TemplateMatcher console app...");
Console.ReadKey();
}
}
}

Get frequency spectrum lines of a .wav file C#

I want to display the frequency spectrum of a .wav file.
I don’t know how to do it right. I use C# with naudio nuget to handle the audio data.
When I Insert all spec_data points I only have one-col filled with data. (Picture 1)
what it looks like now (Picture 1)
how it should look like at the end
How can I get all spectrum points of the audio file?
var buffer = new byte[fft_size];
int bytes_read = fileStream.Read(buffer, 0, buffer.Length);
int BYTES_PER_POINT = fileStream.WaveFormat.BitsPerSample / 8; //8Bit = 1Byte
short[] values = new short[buffer.Length / BYTES_PER_POINT];
for (int n = 0; n < BYTES_PER_POINT; n++)
{
for (int i = 0; i < bytes_read; i += BYTES_PER_POINT)
{
values[i / BYTES_PER_POINT] = (short)((buffer[i + 1] << 8) | buffer[i + 0]);
}
}
neanalizir_values.AddRange(values);
short[] data = new short[fft_size];
data = neanalizir_values.GetRange(0, fft_size).ToArray();
spec_data.RemoveAt(0);
List<double> new_data = new List<double>();
Complex[] fft_buffer = new Complex[fft_size];
for (int i = 0; i < fft_size; i++)
{
fft_buffer[i].X = (float)(neanalizir_values[i] * FastFourierTransform.HammingWindow(i, fft_size));
fft_buffer[i].Y = 0;
}
FastFourierTransform.FFT(true, (int)Math.Log(fft_size, 2.0), fft_buffer);
for (int i = 0; i < spec_data[spec_data.Count - 1].Count; i++)
{
double val;
val = (double)fft_buffer[i].X + (double)fft_buffer[i].Y;
val = Math.Abs(val);
new_data.Add(val);
}
new_data.Reverse();
spec_data.Insert(spec_data.Count, new_data);
neanalizir_values.RemoveRange(0, fft_size / pixelsPerBuffer);
Bitmap bitmap = new Bitmap(spec_data.Count, spec_data[0].Count, PixelFormat.Format8bppIndexed);
ColorPalette pal = bitmap.Palette;
for (int i = 0; i < 256; i++)
pal.Entries[i] = Color.FromArgb(255, i, i, i);
bitmap.Palette = pal;
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
byte[] pixels = new byte[bitmapData.Stride * bitmap.Height];
for (int col = 0; col < spec_data.Count; col++)
{
double scaleFactor = 40;
for (int row = 0; row < spec_data[col].Count; row++)
{
int bytePosition = row * bitmapData.Stride + col;
double pixelVal = spec_data[col][row] * scaleFactor;
pixelVal = Math.Max(0, pixelVal);
pixelVal = Math.Min(255, pixelVal);
pixels[bytePosition] = (byte)(pixelVal);
}
}
Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);
bitmap.UnlockBits(bitmapData);
pictureBox1.Image = bitmap;

how to convert matlab to c# when the output is array?

i try to take surf algorithm in matlab and to convert it in c#.
The algorithm in matlab returns array of coordinates. The size of the array is [10,4].
In c# i wrote a code that doesnt returns the right information in the array.
Am i missed something when i converted this code?
private static void Main(string[] args)
{
Bitmap img1 = new Bitmap(Image.FromFile(#"C:\Users\cbencham\source\repos\3.jpg"));
Bitmap img2 = new Bitmap(Image.FromFile(#"C:\Users\cbencham\source\repos\4.jpg"));
//Get image dimensions
int width = img1.Width;
int height = img1.Height;
//Declare the double array of grayscale values to be read from "bitmap"
double[,] im1 = new double[width, height];
//Loop to read the data from the Bitmap image into the double array
int i, j;
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
Color pixelColor = img1.GetPixel(i, j);
double b = pixelColor.GetBrightness(); //the Brightness component
//Note that rows in C# correspond to columns in MWarray
im1.SetValue(b, i, j);
}
}
//Get image dimensions
width = img2.Width;
height = img2.Height;
//Declare the double array of grayscale values to be read from "bitmap"
double[,] im2 = new double[width, height];
//Loop to read the data from the Bitmap image into the double array
for (i = 0; i < width; i++)
{
for (j = 0; j < height; j++)
{
Color pixelColor = img2.GetPixel(i, j);
double b = pixelColor.GetBrightness(); //the Brightness component
//Note that rows in C# correspond to columns in MWarray
im2.SetValue(b, i, j);
}
}
MLApp.MLApp matlab = new MLApp.MLApp();
matlab.Execute(#"cd C:\Users\cbencham\source\repos");
object result = null;
matlab.Feval("surf", 1, out result, im1, im2);
// TODO: convert result to double Array [10,4]
for (i = 0; i < 10; i++)
{
for (j = 0; j < 4; j++)
{
Console.Write(arr[i, j]);
}
Console.WriteLine();
}
Console.ReadLine();
}
}
}
You can't convert an object array to a double array. But for your purpose you don't need to. You just need to cast it to and object array and print its contents.
var arr = result as object[,];
or
if (result is object[,] arr)
{
for (i = 0; i < arr.GetLength(0); i++)
{
for (j = 0; j < arr.GetLength(1); j++)
{
Console.Write(arr[i, j]);
}
Console.WriteLine();
}
Console.ReadLine();
}

throwing Argument Exception during manipulation of a bitmap

I have been trying to create a grayscale bitmap which it's pixels are filled by my own array of colors. This two dimensional array comes from a process that gets and manipulates every single pixel of an colored image. In other words i am trying to prepare a method to convert a colored one to it's grayscale.
This is How i get the pixel's values and calculate the average
for (var i = 0; i < SharedImg.ImgBitmap.Width;i++)
{
for (var j = 0; j < SharedImg.ImgBitmap.Height; j++)
{
var pix= SharedImg.ImgBitmap.GetPixel(i, j);
var red = (int) pix.R;
var green = (int) pix.G;
var blue = (int) pix.B;
var avrg = (red + green + blue)/3;
var rgb = Color.FromArgb(avrg, avrg, avrg);
arrColors[i, j] = rgb;
}
}
Now it fills the new bitmap with the array
var imgBitmap=new Bitmap(width,height,PixelFormat.Format16bppGrayScale);
for(var i=0 ; i<width;i++)
for (var j = 0; j < height; j++)
{
try
{
imgBitmap.SetPixel(i, j, arrColors[i, j]);
}
catch (Exception exception)
{
mainForm.UpdateNewLine(new SystemResponse(){Color = Color.Red,State = exception.ToString()});
}
}
When it reaches the SetPixel method it throws an ArgumentException.
Any idea or tip ?

C# and matlab give different image means?

I am calculating the average of the RGB channels of images in C# and matlab and getting slightly different result?? (am using 0-255 pixel values...)
The difference is not large but I just can't seem to understand the reason...
Is this common?? Or is it due to bitmap implementation of image?? Or precision issue?? Or does it mean their is something wrong with my code??
Code:
Matlab
I = imread('Photos\hv2512.jpg');
Ir=double(I(:,:,1));
Ig=double(I(:,:,2));
Ib=double(I(:,:,3));
avRed=mean2(Ir)
avGn=mean2(Ig)
avBl=mean2(Ib)
C#
Bitmap bmp= new Bitmap(open.FileName)
double[,] Red = new double[bmp.Width, bmp.Height];
double[,] Green = new double[bmp.Width, bmp.Height];
double[,] Blue = new double[bmp.Width, bmp.Height];
int PixelSize = 3;
BitmapData bmData = null;
if (Safe)
{
Color c;
for (int j = 0; j < bmp.Height; j++)
{
for (int i = 0; i < bmp.Width; i++)
{
c = bmp.GetPixel(i, j);
Red[i, j] = (double) c.R;
Green[i, j] = (double) c.G;
Blue[i, j] = (double) c.B;
}
}
}
double avRed = 0, avGrn = 0, avBlue = 0;
double sumRed = 0, sumGrn = 0, sumBlue = 0;
int cnt = 0;
for (int rws = 0; rws < Red.GetLength(0); rws++)
for (int clms = 0; clms < Red.GetLength(1); clms++)
{
sumRed = sumRed + Red[rws, clms];
sumGrn = sumGrn + Green[rws, clms];
sumBlue = sumBlue + Blue[rws, clms];
cnt++;
}
avRed = sumRed / cnt;
avGrn = sumGrn / cnt;
avBlue = sumBlue / cnt;
This is the image I am using

Categories