Problem with TensorFloat .netcore (CustomVision) - c#

Well i've been doing some work with AI and object detection and have recently encounter somewhat of a problem with a model that i exported from CustomVision.
For the ones who know what i'm talking about, when you export a model from CustomVision you get a .cs file included that represents the class with everything you need to use the model.
And there starts all my problems.. first and most important one is that in one of the methods, specifically in the "ExtractBoxes" method receives a TensorFloat object and a float array of anchors.
Anyways.. inside this method there's 4 variables called "channels", "height" and "width" that come from a list inside of the TensorFloat object called "shape".
Given all this.. my question resides in the TensorFloat object, more specifically in how can i get the values for the variables "channels", "height" and "width" without having a TensorFloat object.
Below im going to include the code from the .cs file that im talking about.
Thanks in advance!
public async Task<IList<PredictionModel>> PredictImageAsync(VideoFrame image)
{
var imageWidth = image.SoftwareBitmap.PixelWidth;
var imageHeight = image.SoftwareBitmap.PixelHeight;
double ratio = Math.Sqrt((double)imageInputSize / (double)imageWidth / (double)imageHeight);
int targetWidth = 32 * (int)Math.Round(imageWidth * ratio / 32);
int targetHeight = 32 * (int)Math.Round(imageHeight * ratio / 32);
using (var resizedBitmap = await ResizeBitmap(image.SoftwareBitmap, targetWidth, targetHeight))
using (VideoFrame resizedVideoFrame = VideoFrame.CreateWithSoftwareBitmap(resizedBitmap))
{
var imageFeature = ImageFeatureValue.CreateFromVideoFrame(resizedVideoFrame);
var bindings = new LearningModelBinding(this.session);
bindings.Bind("input", imageFeature);
var result = await this.session.EvaluateAsync(bindings, "");
return Postprocess(result.Outputs["output"] as TensorFloat);
}
}
private List<PredictionModel> Postprocess(TensorFloat predictionOutputs)
{
var extractedBoxes = this.ExtractBoxes(predictionOutputs, ObjectDetection.Anchors);
return this.SuppressNonMaximum(extractedBoxes);
}
private ExtractedBoxes ExtractBoxes(TensorFloat predictionOutput, float[] anchors)
{
var shape = predictionOutput.Shape;
Debug.Assert(shape.Count == 4, "The model output has unexpected shape");
Debug.Assert(shape[0] == 1, "The batch size must be 1");
IReadOnlyList<float> outputs = predictionOutput.GetAsVectorView();
var numAnchor = anchors.Length / 2;
var channels = shape[1];
var height = shape[2];
var width = shape[3];
Debug.Assert(channels % numAnchor == 0);
var numClass = (channels / numAnchor) - 5;
Debug.Assert(numClass == this.labels.Count);
var boxes = new List<BoundingBox>();
var probs = new List<float[]>();
for (int gridY = 0; gridY < height; gridY++)
{
for (int gridX = 0; gridX < width; gridX++)
{
int offset = 0;
int stride = (int)(height * width);
int baseOffset = gridX + gridY * (int)width;
for (int i = 0; i < numAnchor; i++)
{
var x = (Logistic(outputs[baseOffset + (offset++ * stride)]) + gridX) / width;
var y = (Logistic(outputs[baseOffset + (offset++ * stride)]) + gridY) / height;
var w = (float)Math.Exp(outputs[baseOffset + (offset++ * stride)]) * anchors[i * 2] / width;
var h = (float)Math.Exp(outputs[baseOffset + (offset++ * stride)]) * anchors[i * 2 + 1] / height;
x = x - (w / 2);
y = y - (h / 2);
var objectness = Logistic(outputs[baseOffset + (offset++ * stride)]);
var classProbabilities = new float[numClass];
for (int j = 0; j < numClass; j++)
{
classProbabilities[j] = outputs[baseOffset + (offset++ * stride)];
}
var max = classProbabilities.Max();
for (int j = 0; j < numClass; j++)
{
classProbabilities[j] = (float)Math.Exp(classProbabilities[j] - max);
}
var sum = classProbabilities.Sum();
for (int j = 0; j < numClass; j++)
{
classProbabilities[j] *= objectness / sum;
}
if (classProbabilities.Max() > this.probabilityThreshold)
{
boxes.Add(new BoundingBox(x, y, w, h));
probs.Add(classProbabilities);
}
}
Debug.Assert(offset == channels);
}
}
Debug.Assert(boxes.Count == probs.Count);
return new ExtractedBoxes(boxes, probs);
}

Related

How to optimize copying of a pointer array to another array?

I have one pointer array of bytes with length(4325376) and i am trying to copy the values of first array to another one,
but the speed of copying is slow even with pointers: ~50ms.
The question is: How to increase the speed of copying?
I know there is a copy function to copy the entire array but i don't know if in my case it's possible to use it.
Here is my code:
var mapSource = device.ImmediateContext.MapSubresource(screenTexture, 0, MapMode.Read, SharpDX.Direct3D11.MapFlags.None);
byte[] rgbaValues = new byte[width * height * 4];
var curRowOffs = 0;
var stride = width * 4;
unsafe
{
byte* srcPtr = (byte *)mapSource.DataPointer;
Stopwatch sw = Stopwatch.StartNew();
fixed (byte* pDest = rgbaValues)
{
for (uint y = 0; y < height; y++)
{
var index2 = curRowOffs;
var index = y * mapSource.RowPitch;
for (uint x = 0; x < width; x++)
{
pDest[index2] = srcPtr[index + x * 4 + 0];
pDest[index2 + 1] = srcPtr[index + x * 4 + 1];
pDest[index2 + 2] = srcPtr[index + x * 4 + 2];
pDest[index2 + 3] = srcPtr[index + x * 4 + 3];
index2 += 4;
}
curRowOffs += stride;
}
}
sw.Stop();
Console.WriteLine("{0:N0} Milliseconds", sw.Elapsed.Milliseconds);
}
Udate:
The solution was to use Buffer.CopyMemory method, it gave me ~2ms, Awesome!
for (uint y = 0; y < height; y++)
{
System.Buffer.MemoryCopy(srcPtr, destPtr, width * 4, width * 4);
srcPtr = &srcPtr[mapSource.RowPitch];
destPtr = &destPtr[mapDest.Stride];
}

LiveCharts Line Graph style based on point value

I draw a bunch of line graphs using LiveCharts and WPF, where the contents and the number of line charts are determined at run time. So I don't know in advance how many LineSeries will be there, and what their values will be. However, I know the good range for each LineSeries. For example, one series, let's call it S1 has a good range of 2+/-1. So anything between 1 and 3 are considered to be good. Similarly there can be another, say S2 where range is 30+/-2, so anything between 28 and 32 is good.
I would like to draw the line graph so that sections that are within range are drawn as a solid line, but if a section is outside the range, it would be a dotted/dash line. Since I have multiple LineSeries in one, I have plotted each in its own Y-axis. My XAML and code looks like this:
<Grid>
<lvc:CartesianChart Name="MyChart" Margin="4"
Series="{Binding SeriesCollection}"/>
</Grid>
Code behind:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public SeriesCollection SeriesCollection { get; set; }
public MainWindow()
{
InitializeComponent();
PlotGraph();
}
private void PlotGraph()
{
SeriesCollection = new SeriesCollection();
var lineSeries1 = new LineSeries
{
Title = "S1",
Values = new ChartValues<double>() { 2.3, 2.0, 3.1, 1.3, 0.5, 3.8, 7.3, 2.4, 1.2, 0.1 },
DataLabels = true,
Stroke = Brushes.Green,
Fill = Brushes.Transparent,
ScalesYAt = 0
};
var lineSeries2 = new LineSeries
{
Title = "S2",
Values = new ChartValues<double>() { 32.5, 34.5, 29.5, 26.0, 25.8, 30.5, 32.1, 36.5, 32.4, 24.5 },
DataLabels = true,
Stroke = Brushes.HotPink,
Fill = Brushes.Transparent,
ScalesYAt = 1
};
SeriesCollection.Add(lineSeries1);
SeriesCollection.Add(lineSeries2);
MyChart.AxisY.Add(new Axis());
MyChart.AxisY.Add(new Axis());
DataContext = this;
}
}
I found an example here that the PointState is colored based on values, but it doesn't work for me because I draw multiple series in one. Also, my graph has thousands of points so I have disabled PointGeometry since if I enable them they will be very hard to see anyway.
Is what I want possible at all?
i have found a solution, in fact 2: either you customize livechart to your problem or you recalculate the differents points like i do below:
its just a way, an idea to answer to your question, all things are possible, but need some line of codes....
the plotgraph method
private void PlotGraph()
{
var points = new List<Point>() { new Point(0, 2.3), new Point(1, 2.0),
new Point(2, 3.1), new Point(3, 1.3),
new Point(4, 0.5), new Point(5, 3.8),
new Point(6, 7.3), new Point(7, 2.4),
new Point(8, 1.2), new Point(9, 0.1)};
var range1 = new double[] { 1d, 3d };
var otherpoints = CurvesMath.GetInterpolatedCubicSplinedCurve(points);
var pointscurve = otherpoints.Select(p => p.Y).ToArray();
SeriesCollection = new SeriesCollection();
var lineSeries1 = new LineSeries
{
Title = "S1",
Values = new ChartValues<double>(pointscurve),
DataLabels = false,
Stroke = Brushes.Transparent,
Fill = Brushes.Transparent,
ScalesYAt = 0,
PointGeometrySize = 2,
Configuration = Mappers.Xy<double>()
.X((value, index) => index)
.Y((value, index) => value)
.Stroke((value, index) => value <= range1[0] || value >= range1[1] ? Brushes.Red : Brushes.Blue)
.Fill((value, index) => value <= range1[0] || value >= range1[1] ? Brushes.Red : Brushes.Blue)
};
points = new List<Point>() { new Point(0, 32.5), new Point(1, 34.5),
new Point(2, 29.5), new Point(3, 26.0),
new Point(4, 25.8), new Point(5, 30.5),
new Point(6, 32.1), new Point(7, 36.5),
new Point(8, 32.4), new Point(9, 24.5)};
var range2 = new double[] { 28d, 32d };
otherpoints = CurvesMath.GetInterpolatedCubicSplinedCurve(points);
pointscurve = otherpoints.Select(p => p.Y).ToArray();
var lineSeries2 = new LineSeries
{
Title = "S2",
Values = new ChartValues<double>(pointscurve),
DataLabels = false,
Stroke = Brushes.Transparent,
Fill = Brushes.Transparent,
ScalesYAt = 1,
PointGeometrySize = 2,
Configuration = Mappers.Xy<double>()
.X((value, index) => index)
.Y((value, index) => value)
.Stroke((value, index) => value <= range2[0] || value >= range2[1] ? Brushes.Red : Brushes.Green)
.Fill((value, index) => value <= range2[0] || value >= range2[1] ? Brushes.Red : Brushes.Green)
};
SeriesCollection.Add(lineSeries1);
SeriesCollection.Add(lineSeries2);
MyChart.AxisY.Add(new Axis());
MyChart.AxisY.Add(new Axis());
DataContext = this;
}
the xaml file:
<Grid>
<lvc:CartesianChart Name="MyChart" Margin="4"
Series="{Binding SeriesCollection}" >
</lvc:CartesianChart>
</Grid>
the interpolation cubic spline (or bezier)
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace WpfApp2
{
public static class CurvesMath
{
private const int precision = 80;
public static List<Point> GetInterpolatedCubicSplinedCurve(IList<Point> points)
{
var output = new List<Point>();
int np = points.Count; // number of points
double[] yCoords = new double[np]; // Newton form coefficients
double[] xCoords = new double[np]; // x-coordinates of nodes
double y;
double x;
if (np > 0)
{
for (int i = 0; i < np; i++)
{
var p = points[i];
xCoords[i] = p.X;
yCoords[i] = p.Y;
}
if (np > 1)
{
double[] a = new double[np];
double x1;
double x2;
double[] h = new double[np];
for (int i = 1; i <= np - 1; i++)
{
h[i] = xCoords[i] - xCoords[i - 1];
}
if (np > 2)
{
double[] sub = new double[np - 1];
double[] diag = new double[np - 1];
double[] sup = new double[np - 1];
for (int i = 1; i <= np - 2; i++)
{
diag[i] = (h[i] + h[i + 1]) / 3;
sup[i] = h[i + 1] / 6;
sub[i] = h[i] / 6;
a[i] = (yCoords[i + 1] - yCoords[i]) / h[i + 1] - (yCoords[i] - yCoords[i - 1]) / h[i];
}
SolveTridiag(sub, diag, sup, ref a, np - 2);
}
output.Add(points.First());
for (int i = 1; i <= np - 1; i++)
{
// loop over intervals between nodes
for (int j = 1; j <= precision; j++)
{
x1 = (h[i] * j) / precision;
x2 = h[i] - x1;
y = ((-a[i - 1] / 6 * (x2 + h[i]) * x1 + yCoords[i - 1]) * x2 +
(-a[i] / 6 * (x1 + h[i]) * x2 + yCoords[i]) * x1) / h[i];
x = xCoords[i - 1] + x1;
output.Add(new Point(x, y));
}
}
}
}
return output;
}
public static double SolveCubicSpline(IList<Point> knownSamples, double z)
{
int np = knownSamples.Count;
if (np > 1)
{
if (knownSamples[0].X == z) return knownSamples[0].Y;
double[] a = new double[np];
double x1;
double x2;
double y;
double[] h = new double[np];
for (int i = 1; i <= np - 1; i++)
{
h[i] = knownSamples[i].X - knownSamples[i - 1].X;
}
if (np > 2)
{
double[] sub = new double[np - 1];
double[] diag = new double[np - 1];
double[] sup = new double[np - 1];
for (int i = 1; i <= np - 2; i++)
{
diag[i] = (h[i] + h[i + 1]) / 3;
sup[i] = h[i + 1] / 6;
sub[i] = h[i] / 6;
a[i] = (knownSamples[i + 1].Y - knownSamples[i].Y) / h[i + 1] -
(knownSamples[i].Y - knownSamples[i - 1].Y) / h[i];
}
// SolveTridiag is a support function, see Marco Roello's original code
// for more information at
// http://www.codeproject.com/useritems/SplineInterpolation.asp
SolveTridiag(sub, diag, sup, ref a, np - 2);
}
int gap = 0;
double previous = double.MinValue;
// At the end of this iteration, "gap" will contain the index of the interval
// between two known values, which contains the unknown z, and "previous" will
// contain the biggest z value among the known samples, left of the unknown z
for (int i = 0; i < knownSamples.Count; i++)
{
if (knownSamples[i].X < z && knownSamples[i].X > previous)
{
previous = knownSamples[i].X;
gap = i + 1;
}
}
x1 = z - previous;
if (gap > h.Length - 1)
return z;
x2 = h[gap] - x1;
if (gap == 0)
return 0.0;
y = ((-a[gap - 1] / 6 * (x2 + h[gap]) * x1 + knownSamples[gap - 1].Y) * x2 +
(-a[gap] / 6 * (x1 + h[gap]) * x2 + knownSamples[gap].Y) * x1) / h[gap];
return y;
}
return 0;
}
private static void SolveTridiag(double[] sub, double[] diag, double[] sup, ref double[] b, int n)
{
/* solve linear system with tridiagonal n by n matrix a
using Gaussian elimination *without* pivoting
where a(i,i-1) = sub[i] for 2<=i<=n
a(i,i) = diag[i] for 1<=i<=n
a(i,i+1) = sup[i] for 1<=i<=n-1
(the values sub[1], sup[n] are ignored)
right hand side vector b[1:n] is overwritten with solution
NOTE: 1...n is used in all arrays, 0 is unused */
int i;
/* factorization and forward substitution */
for (i = 2; i <= n; i++)
{
sub[i] = sub[i] / diag[i - 1];
diag[i] = diag[i] - sub[i] * sup[i - 1];
b[i] = b[i] - sub[i] * b[i - 1];
}
b[n] = b[n] / diag[n];
for (i = n - 1; i >= 1; i--)
{
b[i] = (b[i] - sup[i] * b[i + 1]) / diag[i];
}
}
}
}
in the result you see all bad parts with the color RED

I'm trying to do edge detection. But it works on just one image

I'm trying to create a simple edge detection filter. And as I said it works with only one image. I'm trying to create this filter with 2 steps.
Blurring image (with meanfilter)
Calculate ( Original image-Blurring image)
The first step works well. And code of second one is simple like first one. But I see an error message:
System.ArgumentOutOfRangeException: 'Parameter must be positive and < Height.
Parameter name: y'
Working image:https://i.hizliresim.com/dLXkbn.png
My code:
public void edgedetectionfilter( )
{
Bitmap InputPicture,BlurredPicture, OutputPicture;
InputPicture = new Bitmap(pBox_SOURCE.Image);
BlurredPicture = new Bitmap(pBox_PROCESSED.Image);
int PicWidth = InputPicture.Width;
int PicHeight= InputPicture.Height;
OutputPicture = new Bitmap(PicWidth, PicHeight);
OutputPicture = InputPicture;
int x, y, difR, difG, difB;
Color OrgPicColoValue,BluredPicColorValue;
for (x = 0; x < PicWidth; x++)
{
for (y = 0; y < PicWidth; y++)
{
BluredPicColorValue = BlurredPicture.GetPixel(x, y);
OrgPicColoValue = InputPicture.GetPixel(x, y); //ERROR LINE
difR = Convert.ToInt16(OrgPicColoValue.R -BluredPicColorValue.R);
difG = Convert.ToInt16(OrgPicColoValue.G- BluredPicColorValue.G );
difB = Convert.ToInt16(OrgPicColoValue.B- BluredPicColorValue.B);
if (difR > 255) difR = 255;
if (difG > 255) difG = 255;
if (difB > 255) difB = 255;
if (difR < 0) difR = 0;
if (difG < 0) difG = 0;
if (difB < 0) difB = 0;
OutputPicture.SetPixel(x, y, Color.FromArgb(difR, difG, difB));
}
}
pBoxMedian.Image = OutputPicture;
}
public void meanfilter(int p)
//KERNELSIZE=P
{
if (sliderKernel.Value % 2 == 0)
{
MessageBox.Show("Enter an odd number");
return;
}
Color ColorValue;
Bitmap InputPicture, OutputPicture;
InputPicture = new Bitmap(pBox_SOURCE.Image);
int PicWidth = InputPicture.Width;
int PicHeight= InputPicture.Height;
OutputPicture = new Bitmap(PicWidth, PicHeight);
OutputPicture = InputPicture;
int x, y, i, j, sumR, sumG, sumB, avgR, avgG, avgB;
for (x = (KernelSize - 1) / 2; x < PicWidth - (KernelSize - 1) / 2; x++)
{
for (y = (KernelSize - 1) / 2; y < PicHeight - (KernelSize- 1) / 2; y++)
{
toplamR = 0;
toplamG = 0;
toplamB = 0;
for (i = -((KernelSize - 1) / 2); i <= (KernelSize - 1) / 2; i++)
{
for (j = -((KernelSize - 1) / 2); j <= (KernelSize - 1) / 2; j++)
{
ColorValue= InputPicture.GetPixel(x + i, y + j);
sumR = sumR + ColorValue.R;
sumG = sumG + ColorValue.G;
sumB = sumB + ColorValue.B;
}
}
avgR = sumR / (KernelSize * KernelSize );
avgG = sumG / (KernelSize *KernelSize );
avgB = sumB / (KernelSize * KernelSize );
OutputPicture.SetPixel(x, y, Color.FromArgb(avgR, avgG, avgB));
}
}
pBox_PROCESSED.Image = OutputPicture;
}
You compare y < PicWidth, whereas you probably want y < PicHeight. Is the image it worked on square, by chance?

Calculate values of the spectrum with FFT

I have to calculate the spectrum values of an audio.
I used aForge's FFT in Sources/Math/FourierTransform.cs and I used an example of sampling with 16 samples as used in this video to check the results with excel (I tested the results in a spreadsheet like in the video).
FFT:
public enum Direction
{
Forward = 1,
Backward = -1
};
private const int minLength = 2;
private const int maxLength = 16384;
private const int minBits = 1;
private const int maxBits = 14;
private static int[][] reversedBits = new int[maxBits][];
private static Complex[,][] complexRotation = new Complex[maxBits, 2][];
static void Main(string[] args)
{
var Data = new Complex[16];
Data[0] = new Complex(0, 0);
Data[1] = new Complex((float)0.998027, 0);
Data[2] = new Complex((float)0.125333, 0);
Data[3] = new Complex((float)-0.98229, 0);
Data[4] = new Complex((float)-0.24869, 0);
Data[5] = new Complex((float)0.951057, 0);
Data[6] = new Complex((float)0.368125, 0);
Data[7] = new Complex((float)-0.90483, 0);
Data[8] = new Complex((float)-0.48175, 0);
Data[9] = new Complex((float)0.844328, 0);
Data[10] = new Complex((float)0.587785, 0);
Data[11] = new Complex((float)-0.77051, 0);
Data[12] = new Complex((float)-0.68455, 0);
Data[13] = new Complex((float)0.684547, 0);
Data[14] = new Complex((float)0.770513, 0);
Data[15] = new Complex((float)-0.58779, 0);
FFT(Data, Direction.Forward);
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Re.ToString());
}
Console.ReadLine();
}
public static void FFT(Complex[] data, Direction direction)
{
int n = data.Length;
int m = Tools.Log2(n);
// reorder data first
ReorderData(data);
// compute FFT
int tn = 1, tm;
for (int k = 1; k <= m; k++)
{
Complex[] rotation = GetComplexRotation(k, direction);
tm = tn;
tn <<= 1;
for (int i = 0; i < tm; i++)
{
Complex t = rotation[i];
for (int even = i; even < n; even += tn)
{
int odd = even + tm;
Complex ce = data[even];
Complex co = data[odd];
double tr = co.Re * t.Re - co.Im * t.Im;
double ti = co.Re * t.Im + co.Im * t.Re;
data[even].Re += tr;
data[even].Im += ti;
data[odd].Re = ce.Re - tr;
data[odd].Im = ce.Im - ti;
}
}
}
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
}
private static int[] GetReversedBits(int numberOfBits)
{
if ((numberOfBits < minBits) || (numberOfBits > maxBits))
throw new ArgumentOutOfRangeException();
// check if the array is already calculated
if (reversedBits[numberOfBits - 1] == null)
{
int n = Tools.Pow2(numberOfBits);
int[] rBits = new int[n];
// calculate the array
for (int i = 0; i < n; i++)
{
int oldBits = i;
int newBits = 0;
for (int j = 0; j < numberOfBits; j++)
{
newBits = (newBits << 1) | (oldBits & 1);
oldBits = (oldBits >> 1);
}
rBits[i] = newBits;
}
reversedBits[numberOfBits - 1] = rBits;
}
return reversedBits[numberOfBits - 1];
}
private static Complex[] GetComplexRotation(int numberOfBits, Direction direction)
{
int directionIndex = (direction == Direction.Forward) ? 0 : 1;
// check if the array is already calculated
if (complexRotation[numberOfBits - 1, directionIndex] == null)
{
int n = 1 << (numberOfBits - 1);
double uR = 1.0;
double uI = 0.0;
double angle = System.Math.PI / n * (int)direction;
double wR = System.Math.Cos(angle);
double wI = System.Math.Sin(angle);
double t;
Complex[] rotation = new Complex[n];
for (int i = 0; i < n; i++)
{
rotation[i] = new Complex(uR, uI);
t = uR * wI + uI * wR;
uR = uR * wR - uI * wI;
uI = t;
}
complexRotation[numberOfBits - 1, directionIndex] = rotation;
}
return complexRotation[numberOfBits - 1, directionIndex];
}
// Reorder data for FFT using
private static void ReorderData(Complex[] data)
{
int len = data.Length;
// check data length
if ((len < minLength) || (len > maxLength) || (!Tools.IsPowerOf2(len)))
throw new ArgumentException("Incorrect data length.");
int[] rBits = GetReversedBits(Tools.Log2(len));
for (int i = 0; i < len; i++)
{
int s = rBits[i];
if (s > i)
{
Complex t = data[i];
data[i] = data[s];
data[s] = t;
}
}
}
These are the results after the transformation:
Output FFT results: Excel FFT results:
0,0418315622955561 0,669305
0,0533257974328085 0,716163407
0,137615673627316 0,908647001
0,114642731070279 1,673453043
0,234673940537634 7,474988602
0,0811255020953362 0,880988382
0,138088891589122 0,406276784
0,0623766891658306 0,248854492
0,0272978749126196 0,204227
0,0124250144575261 0,248854492
0,053787064184711 0,406276784
0,00783331226557493 0,880988382
0,0884368745610118 7,474988602
0,0155431246384978 1,673453043
0,0301093757152557 0,908647001
0 0,716163407
The results are not at all similar. Where is it wrong?
Is the implementation of complex (Data) wrong or is the FFT method wrong or other?
Thanks in advance!
First, the resulting FFT is a complex function in general. You're only displaying the real parts in your code but the thing you're comparing to is displaying the magnitudes, so of course they're going to be different: you're comparing apples to oranges.
When you use magnitudes and compare apples to apples, you should get this:
for (int a = 0; a <= Data.Length - 1; a++)
{
Console.WriteLine(Data[a].Magnitude.ToString());
}
...
0.0418315622955561
0.0447602132472683
0.0567904388057513
0.104590813761862
0.46718679147454
0.0550617784710375
0.025392294285886
0.0155534081359397
0.0127641875296831
0.0155534081359397
0.025392294285886
0.0550617784710375
0.46718679147454
0.104590813761862
0.0567904388057513
0.0447602132472683
That looks a little better -- it has the same symmetry property as the Excel output and there appear to be peaks in the same locations.
It almost looks like the scale is off. If I divide each element by the corresponding element from the Excel output, I get:
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
16
So your results are pretty much correct, just off by a scaling factor.
You're dividing everything by n in the last step of your FFT:
if (direction == Direction.Forward)
{
for (int i = 0; i < n; i++)
{
data[i].Re /= (double)n;
data[i].Im /= (double)n;
}
}
This is conventionally done for the inverse transform, not the forward transform.
In summary, changing the output from Data[a].Re to Data[a].Magnitude and changing the condition at the end of FFT from if (direction == Direction.Forward) to if (direction == Direction.Backward), I get this output:
0.669304996728897
0.716163411956293
0.908647020892022
1.67345302018979
7.47498866359264
0.880988455536601
0.406276708574176
0.248854530175035
0.20422700047493
0.248854530175035
0.406276708574176
0.880988455536601
7.47498866359264
1.67345302018979
0.908647020892022
0.716163411956293
which matches the Excel output.

Different output between Emulator and Samsung Galaxy S3 with Xamarin

I am having issues with the output of the the result of a math calculation. I have a basic average of an array of double and I assign the result to a Label object, using the ToString() method. When I emulate the average, the label shows the correct value of 15.96 for example, but the same average of the same array, on my Galaxy S3 shows 159.6.
Is there anyone who know what's up and what can I do to make the S3 show the correct value?
Thank you all!
EDIT: passing the result to a label and adding the label to the grid:
double result = Math.Round(NP122.DoAverage(parameters), 2);
CustomLabel label = new CustomLabel();
label.ColNo = grid.ColumnDefinitions.IndexOf(c);
label.FontSize = 25;
label.TextColor = Color.Green;
if (result.ToString() == "NaN")
label.Text = "0";
else
label.Text = result.ToString();
label.IsVisible = true;
for (int i = 0; i < numberOfRows.Length + 2; i++) {
if(i == numberOfRows.Length +1)
Grid.SetRow(label, i);
}
Grid.SetColumn(label, grid.ColumnDefinitions.IndexOf(c));
listaRez.Add(label);
foreach (CustomLabel a in listaRez)
{
if (a.ColNo == grid.ColumnDefinitions.IndexOf(c))
{
grid.Children.Add(a);
}
}
EDIT 2: Custom function for NP122.DoAverage:
public static class NP122
{
public static double Vx, sx, Xm, kn, Xkinf, Xksup;
public static double sum;
public static double sumaProvizorie;
public static double[] valoriKn = new double[25];
public static double ValoareCaracteristicaSuperioara(double[] l)
{
Vx = 0;
sx = 0;
Xm = 0;
kn = 0;
Xkinf = 0;
Xksup = 0;
sum = 0;
sumaProvizorie = 0;
valoriKn[0] = 0;
//more here
valoriKn[24] = 0.35;
if (l.Length < 2 )
{
Xksup = 0;
Xkinf = 0;
}
else
{
Xm = (l.Sum()) / (l.Length);
for (int j = 0; j < l.Length; j++)
{
sumaProvizorie = Math.Round(Math.Pow((l[j] - Xm), 2), 2);
sum += sumaProvizorie;
}
kn = valoriKn[l.Length - 1];
double elements = (1.00 / (l.Length - 1));
double putere = sum;
sx = Math.Round(Math.Sqrt(elements * putere), 4);
Vx = sx / Xm;
Xksup = Xm * (1 + kn * Vx);
Xkinf = Xm * (1 - kn * Vx);
}
return Xksup;

Categories

Resources