ZedGraph C# Serial data plot - c#

I am new to C# and graphing world. I am trying to plot serial data coming from Arduino as double datatype on ZedGraph in C#. I am unable to plot it. The graph is appearing with only the scale Y axis scale setting itself to the output value but nothing else. I shall be grateful for your help!! Thanks. Below is my code
PS: I put a message box to see the output and it is showing the correct output from the Arduino.
using System;
using System.Drawing;
using System.Windows.Forms;
using ZedGraph;
using System.IO.Ports;
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
static string indata;
double x;
double d;
public Form1()
{
InitializeComponent();
PlotSerial();
// DrawGraph();
}
private void PlotSerial()
{
SerialPort sprt;
sprt = new SerialPort("COM4");
sprt.BaudRate = 115200;
try
{
sprt.Open();
}
catch (Exception)
{
MessageBox.Show("Check port");
}
// initializing zed graph
GraphPane pane = zedGraph.GraphPane;
PointPairList list2 = new PointPairList();
pane.YAxisList.Clear();
//X-Axis Settings
pane.XAxis.Scale.MinorStep = 1;
pane.XAxis.Scale.MajorStep = 5;
XDate time = new XDate(DateTime.Now.ToOADate());
pane.XAxis.Type = AxisType.Date;
pane.XAxis.Scale.Format = "ss";
pane.XAxis.Scale.Min = new XDate(DateTime.Now);
pane.XAxis.Scale.Max = new XDate(DateTime.Now.AddSeconds(25));
pane.XAxis.Scale.MinorUnit = DateUnit.Second;
pane.XAxis.Scale.MajorUnit = DateUnit.Second;
indata = sprt.ReadLine();
MessageBox.Show(indata);
bool result = Double.TryParse(indata, out d);
// double xmin = -50;
//double xmax = 50;
//for x = 0 To 36
//for (double x = xmin; x <= xmax; x += 1)
//for (int i = 1; i < 20; i++)
{
list2.Add(x, d);
}
Scale xScale1 = zedGraph.MasterPane.PaneList[0].XAxis.Scale;
if (time.XLDate > xScale1.Max)
{
xScale1.Max = (XDate)(DateTime.Now.AddSeconds(1));
xScale1.Min = (XDate)(DateTime.Now.AddSeconds(-40));
}
/*
// byte[] buffer = new byte[20];
indata = (byte)sprt.ReadByte();
//MessageBox.Show(indata);
//double xmin = -2;
//double xmax = 2;
// for (= xmin; x <= xmax; x +=1)
list2.Add(x, indata);
*/
pane.XAxis.Title.Text = "X Axis";
int axis2 = pane.AddYAxis("Y Axis");
LineItem myCurve2 = pane.AddCurve("Serialport_Curve", list2, Color.Blue, SymbolType.Diamond);
myCurve2.YAxisIndex = axis2;
pane.YAxisList[axis2].Title.FontSpec.FontColor = Color.Black;
zedGraph.AxisChange();
zedGraph.Invalidate();
}
private double f1(double x)
{
if (x == 0)
{
return 1;
}
return Math.Sin(x) / x;
}
private double f2(double x)
{
if (x == 0)
{
return 1;
}
return 10 * Math.Sin(x * 0.5) / x;
}
private double f3(double x)
{
if (x == 0)
{
return 1;
}
return 0.1 * Math.Sin(x * 2) / x;
}
}
}

Related

Remove gray from the photo c# windows forms

I want to remove grayness from the picture in pictureBox1, as in the first photo below. The second photo shows the formulas that can be used to do this. I wrote an approximate code, but the compiler throws an error, that variables red1, green1 and blue1 cannot be written to Color newPixel due to type incompatibility. Please help me fixing my code.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void pictureBox1_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Відкрити зображення";
dlg.Filter = "jpg files (*.jpg)|*.jpg|All filles (*.*)|*.*";
if (dlg.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = new Bitmap(dlg.OpenFile());
pictureBox1.Height = pictureBox1.Image.Height;
pictureBox1.Width = pictureBox1.Image.Width;
}
dlg.Dispose();
label1.Visible = false;
}
private void button1_Click(object sender, EventArgs e)
{
Bitmap input = new Bitmap(pictureBox1.Image);
Bitmap output = new Bitmap(input.Width, input.Height);
int[] red = new int[256];
int[] green = new int[256];
int[] blue = new int[256];
for (int x = 0; x < input.Width; x++)
{
for (int y = 0; y < input.Height; y++)
{
Color pixel = ((Bitmap)pictureBox1.Image).GetPixel(x, y);
red[pixel.R]++;
green[pixel.G]++;
blue[pixel.B]++;
double Ri = red.Average();
double Gi = green.Average();
double Bi = blue.Average();
double Avg = (Ri+Bi+Gi)/3;
double red1 = red (Avg/Ri);
double green1 = green(Avg / Gi);
double blue1 = blue(Avg / Bi);
Color newPixel = ((Color)red1| (Color)green1 | (Color)blue1);
output.SetPixel(x, y, Color.((int)newPixel));
}
}
pictureBox2.Image = output;
}
}
}
You should use Color.FromArgb() to create the new color. However, this method expects 3 int as input and not double, so you need to convert your doubles to integers.
Simple type cast - (int)someDouble
This solution will simply remove any decimals from the double value (1.9 => 1):
double red1 = 123.45;
double green1 = 12.345;
double blue1 = 234.56;
Color newPixel = Color.FromArgb((int)red1, (int)green1, (int)blue1);
// R=123, G=12, B=234
Math.Round(someDouble)
This solution will round the double value to the nearest integer (1.5 => 2 and 1.49 => 1):
int red1 = (int)Math.Round(123.45);
int green1 = (int)Math.Round(12.345);
int blue1 = (int)Math.Round(234.56);
Color newPixel = Color.FromArgb(red1, green1, blue1);
// R=123, G=12, B=235
You misinterpreted the formula. N in the formula specifies the total number of the pixels in the image. The overlined letters means the average channel value over the image. These variable should be the type of double. I called them redAverage, greenAverage and blueAverage, respectively. And as you
already know, Avg is the average of these variables. Finally, R', G', B' are the new channel values calculated using the old values.
using System.Drawing.Imaging;
namespace Convert2Gray
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private Bitmap m_inputImage;
private Bitmap m_outputImage;
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
m_inputImage = (Bitmap)Image.FromFile("sample.png");
m_outputImage = new Bitmap(m_inputImage.Width, m_inputImage.Height, m_inputImage.PixelFormat);
pictureBox1.Image = m_inputImage;
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
DoConversion();
pictureBox2.Image = m_outputImage;
pictureBox2.SizeMode = PictureBoxSizeMode.AutoSize;
}
private unsafe void DoConversion()
{
BitmapData inputBitmapData = m_inputImage.LockBits(new Rectangle(0, 0, m_inputImage.Width, m_inputImage.Height), ImageLockMode.ReadWrite, m_inputImage.PixelFormat);
BitmapData outputBitmapData = m_outputImage.LockBits(new Rectangle(0, 0, m_outputImage.Width, m_outputImage.Height), ImageLockMode.ReadWrite, m_outputImage.PixelFormat);
byte* inputScan0 = (byte*)inputBitmapData.Scan0;
byte* outputScan0 = (byte*)outputBitmapData.Scan0;
int inputStride = inputBitmapData.Stride;
int outputStride = outputBitmapData.Stride;
int bytesPerPixel = Image.GetPixelFormatSize(m_inputImage.PixelFormat) / 8;
double redAverage = 0.0;
double greenAverage = 0.0;
double blueAverage = 0.0;
double average = 0.0;
int pixelCount = m_inputImage.Width * m_inputImage.Height;
for (int y = 0; y < m_inputImage.Height; y++)
{
byte* inputCurrentRow = inputScan0 + y * inputStride;
byte* outputCurrentRow = outputScan0 + y * outputStride;
for (int x = 0; x < m_inputImage.Width; x++)
{
ColorBgr* inputColor = (ColorBgr*)(inputCurrentRow + x * bytesPerPixel);
redAverage += inputColor->R;
greenAverage += inputColor->G;
blueAverage += inputColor->B;
}
}
redAverage /= pixelCount;
greenAverage /= pixelCount;
blueAverage /= pixelCount;
average = (redAverage + greenAverage + blueAverage) / 3;
for (int y = 0; y < m_inputImage.Height; y++)
{
byte* inputCurrentRow = inputScan0 + y * inputStride;
byte* outputCurrentRow = outputScan0 + y * outputStride;
for (int x = 0; x < m_inputImage.Width; x++)
{
ColorBgr* inputColor = (ColorBgr*)(inputCurrentRow + x * bytesPerPixel);
ColorBgr* outputColor = (ColorBgr*)(outputCurrentRow + x * bytesPerPixel);
outputColor->R = (byte)(inputColor->R * average / redAverage);
outputColor->G = (byte)(inputColor->G * average / greenAverage);
outputColor->B = (byte)(inputColor->B * average / blueAverage);
}
}
m_inputImage.UnlockBits(inputBitmapData);
m_outputImage.UnlockBits(outputBitmapData);
}
private struct ColorBgr : IEquatable<ColorBgr>
{
public byte B;
public byte G;
public byte R;
public ColorBgr(byte b, byte g, byte r)
{
B = b;
G = g;
R = r;
}
public static bool operator ==(ColorBgr left, ColorBgr right)
{
return left.Equals(right);
}
public static bool operator !=(ColorBgr left, ColorBgr right)
{
return !(left == right);
}
public bool Equals(ColorBgr other)
{
return this.B == other.B && this.G == other.G && this.R == other.R;
}
public override bool Equals(object? obj)
{
if (obj is ColorBgr)
return Equals((ColorBgr)obj);
return false;
}
public override int GetHashCode()
{
return new byte[] { B, G, R }.GetHashCode();
}
}
}
}

How to solve the Fatal Execution Engine Error in OpenTK?

I am trying to develop a program using OpenTK. The purpose of this program is to load a STL (stereolithography) file in ASCII format, then render it in OpenTK, and keep track of the selected object using name stack. In this program, I use the mouse right click to get the selected object.
The brief explanation of STL file is here:
https://en.wikipedia.org/wiki/STL_(file_format)
In my code, I am using 2 STL files. The first STL file is a simple geometry (file size 8 kb). The second STL file is a complex geometry (file size 1167 kb). When I used the first STL file and run my code, it just worked fine when I use my mouse right click function.
However, when I used second STL file and run my code (follow by mouse right click), I got this Fatal Execution Engine Error Exception. I am not sure why I get this error. Is it because of the file size is too big? But I can render this second file into OpenTK. Is it because I have to set a large enough buff size here to avoid this exception?
Do you have any idea why this is happening? Is there any method to avoid this error/exception?
The link for these two STL files are here:
https://drive.google.com/drive/folders/1v9bUzqVx1a1_KbnSXCQ5LREoQaAFUn2D?usp=sharing
Here are my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;
namespace OpenTK3D
{
public class Game3D
{
private GameWindow window;
private float zoom;
private bool hasRotationStarted;
private int startX;
private int startY;
private float xRotAngle;
private float yRotAngle;
private bool hasPanningStarted;
private float xTrans;
private float yTrans;
private int BUFSIZE = 512;
private string filePath = #"C:\Users\mpelmt\Desktop\ISF forming direction optimization\verify_65_40_yForming_noFlange.STL";
private double angleLimit = 60;
public Game3D(GameWindow wd)
{
this.window = wd;
var zBoundary = zBoundaryValue(filePath);
hasRotationStarted = false;
startX = 0;
startY = 0;
xRotAngle = 28;
yRotAngle = -45;
zoom = -(float)zBoundary;
hasPanningStarted = false;
xTrans = 0;
yTrans = 0;
start();
}
public void start()
{
window.Load += loaded;
window.Resize += resize;
window.RenderFrame += renderFrame;
window.MouseDown += mouseLeftPress;
window.MouseUp += mouseRelease;
window.MouseMove += mouseDragEvent;
window.MouseWheel += MouseWheelHandler;
window.MouseDown += wheelPressEvent;
window.MouseUp += wheelReleaseEvent;
window.MouseMove += wheelDragEvent;
window.MouseDown += select;
window.Run(1.0 / 60.0);
}
private List<double> getAllSTLData(string path)
{
string[] text = System.IO.File.ReadAllLines(path);
List<double> allData = new List<double>();
foreach (var line in text)
{
if (line.Contains("facet normal"))
{
var normal = Array.ConvertAll(line.Remove(0, 16).Split(' '), double.Parse);
allData.AddRange(normal);
}
if (line.Contains("vertex"))
{
var position = Array.ConvertAll(line.Remove(0, 16).Split(' '), double.Parse);
allData.AddRange(position);
}
}
return allData;
}
private Dictionary<int, List<double>> getAllFacets(string path)
{
var allSTLData = getAllSTLData(path);
var allFacet = new Dictionary<int, List<double>>();
for (int i = 0; i < (allSTLData.Count) / 12; i++)
{
allFacet.Add(i + 1, allSTLData.GetRange(12 * i, 12));
}
return allFacet;
}
private double yBoundaryValue(string path)
{
var allFacets = getAllFacets(path);
var listOfY = new List<double>();
foreach (KeyValuePair<int, List<double>> kp in allFacets)
{
var vertex = kp.Value.GetRange(3, 9);
listOfY.Add(vertex[1]);
listOfY.Add(vertex[4]);
listOfY.Add(vertex[7]);
}
return listOfY.Max() - listOfY.Min();
}
private double xBoundaryValue(string path)
{
var allFacets = getAllFacets(path);
var listOfX = new List<double>();
foreach (KeyValuePair<int, List<double>> kp in allFacets)
{
var vertex = kp.Value.GetRange(3, 9);
listOfX.Add(vertex[0]);
listOfX.Add(vertex[3]);
listOfX.Add(vertex[6]);
}
return listOfX.Max() - listOfX.Min();
}
private double zBoundaryValue(string path)
{
var allFacets = getAllFacets(path);
var listOfZ = new List<double>();
foreach (KeyValuePair<int, List<double>> kp in allFacets)
{
var vertex = kp.Value.GetRange(3, 9);
listOfZ.Add(vertex[2]);
listOfZ.Add(vertex[5]);
listOfZ.Add(vertex[8]);
}
return listOfZ.Max() - listOfZ.Min();
}
private List<double> getAngleRangeWithinLimit(double angleLimit)
{
var result = new List<double>();
var section = (int)angleLimit / 5;
var remain = angleLimit % 5;
for (int i = 0; i < section; i++)
{
result.Add(5 * i);
result.Add(5 * i + 5);
}
if (remain != 0)
{
result.Add(result.Last());
result.Add(result.Last() + remain);
}
return result;
}
public Dictionary<int, List<double>> pickSelectFacetsByAngleInYForm(string path, double angleLimit)
{
var result = new Dictionary<int, List<double>>();
var allFacets = getAllFacets(path);
var angleRange = getAngleRangeWithinLimit(angleLimit);
foreach (KeyValuePair<int, List<double>> kp in allFacets)
{
var data = kp.Value;
var id = kp.Key;
var tempList = new List<double>();
var angle = Math.Acos(Math.Abs(data[1])) * 180 / (Math.PI);
for (int i = 0; i < angleRange.Count / 2; i++)
{
if (angle >= angleLimit)
{
tempList.AddRange(data);
tempList.Add(angleLimit + 1);
break;
}
else if (angle >= angleRange[2 * i] && angle <= angleRange[2 * i + 1])
{
tempList.AddRange(data);
tempList.Add(angleRange[2 * i + 1]);
break;
}
}
result.Add(id, tempList);
}
return result;
}
public void renderColorPlotYForm(string path, double angleLimit)
{
var plotData = pickSelectFacetsByAngleInYForm(path, angleLimit);
foreach (KeyValuePair<int, List<double>> kv in plotData)
{
var id = kv.Key;
var data = kv.Value;
GL.Begin(BeginMode.Triangles);
var colorRange = data.Last();
if (colorRange == 5)
{
// green
GL.Color3(0.0, 1.0, 0.0);
}
if (colorRange == angleLimit + 1)
{
//red
GL.Color3(1.0, 0.0, 0.0);
}
if (colorRange == 30)
{
// yellow
GL.Color3(1.0, 1.0, 0.0);
}
if (colorRange < 30 && colorRange > 5)
{
var diff = 30 - colorRange;
var ratio = diff / 25;
GL.Color3(1 - ratio, 1, 0);
}
if (colorRange > 30 && colorRange < angleLimit + 1)
{
var ratio = (angleLimit - colorRange) / angleLimit;
GL.Color3(1, 1 - ratio, 0);
}
var listOfVertex = data.GetRange(3, 9);
for (int i = 0; i < 3; i++)
{
var vertex = listOfVertex.GetRange(3 * i, 3);
GL.Vertex3(vertex[0], vertex[1], vertex[2]);
}
GL.End();
}
}
public void pickSelectColorPlotYForm(string path, double angleLimit)
{
var plotData = pickSelectFacetsByAngleInYForm(path, angleLimit);
foreach (KeyValuePair<int, List<double>> kv in plotData)
{
var id = kv.Key;
var data = kv.Value;
GL.LoadName(id);
GL.Begin(BeginMode.Triangles);
var colorRange = data.Last();
if (colorRange == 5)
{
// green
GL.Color3(0.0, 1.0, 0.0);
}
if (colorRange == angleLimit + 1)
{
//red
GL.Color3(1.0, 0.0, 0.0);
}
if (colorRange == 30)
{
// yellow
GL.Color3(1.0, 1.0, 0.0);
}
if (colorRange < 30 && colorRange > 5)
{
var diff = 30 - colorRange;
var ratio = diff / 25;
GL.Color3(1 - ratio, 1, 0);
}
if (colorRange > 30 && colorRange < angleLimit + 1)
{
var ratio = (angleLimit - colorRange) / angleLimit;
GL.Color3(1, 1 - ratio, 0);
}
var listOfVertex = data.GetRange(3, 9);
for (int i = 0; i < 3; i++)
{
var vertex = listOfVertex.GetRange(3 * i, 3);
GL.Vertex3(vertex[0], vertex[1], vertex[2]);
}
GL.End();
}
}
public void loaded(object o, EventArgs e)
{
GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL.Enable(EnableCap.DepthTest);
}
public void renderFrame(object o, EventArgs e)
{
var xBoundary = xBoundaryValue(filePath);
var yBoundary = yBoundaryValue(filePath);
var zBoundary = zBoundaryValue(filePath);
var xCen = xBoundary / 2;
var yCen = yBoundary / 2;
var zCen = zBoundary / 2;
GL.LoadIdentity();
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.Translate(xTrans, yTrans, zoom*3);
GL.Rotate(xRotAngle, 1.0, 0, 0);
GL.Rotate(yRotAngle, 0, 1, 0);
renderColorPlotYForm(filePath, angleLimit);
window.SwapBuffers();
}
public void resize(object o, EventArgs e)
{
var zBoundary = zBoundaryValue(filePath);
GL.Viewport(0, 0, window.Width, window.Height);
GL.MatrixMode(MatrixMode.Projection);
GL.LoadIdentity();
// the fov must be radian
var matrix = Matrix4.CreatePerspectiveFieldOfView(45.0f*(MathHelper.Pi)/180, window.Width / window.Height, 1.0f, (float)zBoundary * (float)zBoundary);
GL.LoadMatrix(ref matrix);
GL.MatrixMode(MatrixMode.Modelview);
}
private void processHits(int hits, int[] buffer)
{
Console.WriteLine("hit: {0}", hits);
if (hits > 0)
{
int choose = buffer[3];
int depth = buffer[1];
for (int i = 0; i < hits; i++)
{
if (buffer[i * 4 + 1] < depth)
{
choose = buffer[i * 4 + 3];
depth = buffer[i * 4 + 1];
}
}
Console.WriteLine("choosen: {0}", choose);
}
}
private void GluPickMatrix(double x, double y, double deltax, double deltay, int[] viewport)
{
if (deltax <= 0 || deltay <= 0)
{
return;
}
GL.Translate((viewport[2] - 2 * (x - viewport[0])) / deltax, (viewport[3] - 2 * (y - viewport[1])) / deltay, 0);
GL.Scale(viewport[2] / deltax, viewport[3] / deltay, 1.0);
}
public void select(object o, MouseEventArgs e)
{
var zBoundary = zBoundaryValue(filePath);
var mouse = Mouse.GetState();
if (mouse[MouseButton.Right])
{
var buffer = new int[BUFSIZE];
var viewPort = new int[4];
int hits;
GL.GetInteger(GetPName.Viewport, viewPort);
GL.SelectBuffer(BUFSIZE, buffer);
GL.RenderMode(RenderingMode.Select);
GL.InitNames();
GL.PushName(0);
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GluPickMatrix(e.Mouse.X, viewPort[3] - e.Mouse.Y, 5.0, 5.0, viewPort);
var matrix = Matrix4.CreatePerspectiveFieldOfView(45.0f * (MathHelper.Pi) / 180, window.Width / window.Height, 1.0f, (float)zBoundary * (float)zBoundary);
GL.MultMatrix(ref matrix);
GL.MatrixMode(MatrixMode.Modelview);
pickSelectColorPlotYForm(filePath, angleLimit);
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.Flush();
hits = GL.RenderMode(RenderingMode.Render);
processHits(hits, buffer);
}
}
public void mouseLeftPress(object sender, MouseEventArgs e)
{
if (e.Mouse.LeftButton == ButtonState.Pressed)
{
hasRotationStarted = true;
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
public void mouseRelease(object sender, MouseEventArgs e)
{
if (e.Mouse.LeftButton == ButtonState.Released)
{
hasRotationStarted = false;
}
}
public void mouseDragEvent(object sender, MouseEventArgs e)
{
if (hasRotationStarted == true && e.Mouse.X != e.Mouse.Y)
{
xRotAngle = xRotAngle + (e.Mouse.Y - startY);
yRotAngle = yRotAngle + (e.Mouse.X - startX);
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
public void MouseWheelHandler(object sender, MouseWheelEventArgs e)
{
var xBoundary = xBoundaryValue(filePath);
if (e.Delta > 0)
{
zoom += 0.1f * (float)xBoundary;
}
if (e.Delta < 0)
{
zoom -= 0.1f * (float)xBoundary;
}
}
public void wheelPressEvent(object sender, MouseEventArgs e)
{
if (e.Mouse.MiddleButton == ButtonState.Pressed)
{
hasPanningStarted = true;
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
public void wheelReleaseEvent(object sender, MouseEventArgs e)
{
if (e.Mouse.MiddleButton == ButtonState.Released)
{
hasPanningStarted = false;
}
}
public void wheelDragEvent(object sender, MouseEventArgs e)
{
if (hasPanningStarted == true)
{
xTrans = xTrans + 2 * (e.Mouse.X - startX);
yTrans = yTrans - 2 * (e.Mouse.Y - startY);
startX = e.Mouse.X;
startY = e.Mouse.Y;
}
}
}
}
Here is the main function:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenTK;
namespace OpenTK3D
{
class Program
{
static void Main(string[] args)
{
var window = new GameWindow(500, 500);
var gm = new Game3D(window);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Press enter to finish...");
Console.ReadLine();
}
}
}
This is the result when I run my code using the first STL file (it works fine):
When I run my code using the second STL file, I got this Fatal Execution Engine Error:

Image rotation performance improvement

I am writing code for image rotation. But performance is so bad.
When I use 10000 x 10000 image, it took about 100 minutes. I want to speed up up to < 1~3 min, but I don't know how I can improve this code.
This code is for huge size images (over 4gb), and process single line of image sequentially.
I attach full code. First I do x-y movement transformation, after that I perform angle transformation.
Here is code for this. Environment is .net framework 4.6.2, 64bit.
Test code: I used "emgucv3 and speedycoding" library from nuget package
flatten method is from speedycoding , and Image<Gray, byte> from emgucv3
Image<Gray,byte> img = new Image<Gray, byte>(imgpath);
PointD[] posdList = new PointD[4]
{
new PointD(-1024,48),
new PointD(-3264,0),
new PointD(639,-2016),
new PointD(3119,1696)
};
var data = img.Data.TointArray();
var dataW = img.Data.GetLength(1);
var dataH = img.Data.GetLength(0);
var strideW = dataW % 4;
var strideH = dataH % 4;
posdList = posdList.Select( x => new PointD( x.X * ratio + dataW/2, x.Y * ratio+dataH/2 ) ).ToArray();
img = img.Resize( dataW + ( strideW == 0 ? 0 : 4 - strideW ), dataH + ( strideH == 0 ? 0 : 4 - strideH ), Inter.Cubic );
data = img.Data.TointArray();
dataW = img.Data.GetLength(1);
dataH = img.Data.GetLength(0);
var srcdata = img.Data.Flatten();
byte[][] temprers;
using (MemoryStream mstream = new MemoryStream(srcdata))
{
temprers = Run(mstream, dataW, dataH, posdList);
}
This is main run code.
public static byte[][] Run(MemoryStream bytestream, int w, int h, PointD[] pos3)
{
try
{
Stopwatch stw = new Stopwatch();
var srcPos = new AffinePos(pos3[0], pos3[1], pos3[2], pos3[3]);
var trsData = srcPos.ToTrnsData(w, h);
var xc = trsData.XSrcCnter;
var yc = trsData.YSrcCnter;
var xmax = Math.Max(w - xc, xc) * 2;
var ymax = Math.Max(h - yc, yc) * 2;
byte[][] R1 = CreateJagged(ymax, xmax);
for (int i = 0; i < h; i++)
{
var data = new byte[w];
bytestream.Seek(i * w, SeekOrigin.Begin);
bytestream.Read(data, 0, w);
var reshaped = data.Reshape(1, w).ToJagged();
xytransform(ref R1, trsData, reshaped, i, xmax, ymax);
}
var w1 = R1[0].Length;
var h1 = R1.Length;
var degree = trsData.Angle * 180 / Math.PI;
double radian = trsData.Angle;
double cosRadian = Cos(radian);
double sinRadian = Sin(radian);
int newWidth = (int)(w1 * Abs(cosRadian) + h1 * Abs(sinRadian));
int newHeight = (int)(h1 * Abs(cosRadian) + w1 * Abs(sinRadian));
Console.WriteLine( "Create Jagged (sec)" );
stw.Start();
byte[][] R2 = CreateJagged(newWidth, newHeight);
stw.Stop();
Console.WriteLine( stw.ElapsedMilliseconds / 1000 );
Console.WriteLine( "Length : {0} / (ms)", R1.Length );
for (int i = 0; i < R1.Length; i++)
{
var reshaped = R1[i].Reshape(1, w1).ToJagged();
Stopwatch stwinnter = new Stopwatch();
stwinnter.Start();
rotateGeneral(ref R2, trsData, reshaped, i, w1, h1);
stwinnter.Stop();
Console.WriteLine( stwinnter.ElapsedMilliseconds );
}
return R2;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
return null;
}
}
public static void xytransform(ref byte[][] target, TrnsData data, byte[][] src, int hidx, int xmax, int ymax)
{
var h = src.GetLength(0);
var w = src[0].GetLength(0);
var tcenterX = (int)xmax / 2;
var tcenterY = (int)ymax / 2;
var xshift = (int)(data.XSrcCnter - tcenterX);
var yshift = (int)(data.YSrcCnter - tcenterY);
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
if (i - xshift >= 0
&& j - yshift >= 0
&& i - xshift < target[0].Length
&& j - yshift < target.Length)
{
var yidx = (j - yshift + hidx).ToString();
var xidx = (i - xshift).ToString();
if (j - yshift + hidx * h < target.Length
&& i - xshift < target[0].Length)
{ target[j - yshift + hidx * h][i - xshift] = src[j][i]; }
}
}
}
}
public static void rotateGeneral(ref byte[][] target, TrnsData data, byte[][] G, int hidx, int oldw, int oldh)
{
double radian = data.Angle;
var newWidth = target[0].Length;
var newHeight = target.Length;
double cosRadian = Cos(radian);
double sinRadian = Sin(radian);
int centerX = oldw / 2;
int centerY = oldh / 2;
int diffX = (newWidth - oldw) / 2;
int diffY = (newHeight - oldh) / 2;
double sourceX, sourceY;
int isourceX, isourceY;
int isourceX2, isourceY2;
int h = G.Length;
var temptarget = target;
Parallel.For( 0, target.Length ,
y =>
{
for (int x = 0; x < temptarget[0].Length; x++)
{
var dx = x - (centerX + diffX);
var dy = y - (centerY + diffY);
var xres = dx * cosRadian - dy * sinRadian;
var yres = dx * sinRadian + dy * cosRadian;
var srcX = xres + centerX;
var srcY = yres - hidx * h + centerY;
var isourceX_ = (int)Math.Round( srcX );
var isourceY_ = (int)Math.Round( srcY );
//try
//{
if (isourceY_ < G.Length
&& isourceY_ >= 0
&& isourceX_ < G[0].Length
&& isourceX_ >= 0)
{
temptarget[y][x] = G[isourceY_][isourceX_];
}
//}
//catch (Exception es)
//{
// Console.WriteLine( es.ToString() );
//}
}
} );
target = temptarget;
}
transData class is this
public struct TrnsData
{
public double Innerw;
public double Innterh;
public int H;
public int W;
public int XSrcCnter;
public int YSrcCnter;
public int XShift;
public int YShift;
public int dX;
public int dY;
public double Angle; // radian
}
public class AffinePos
{
public PointD LB;
public PointD LT;
public PointD RT;
public PointD RB;
public AffinePos(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
{
LB = new PointD(x1, y1);
LT = new PointD(x2, y2);
RT = new PointD(x3, y3);
RB = new PointD(x4, y4);
}
public AffinePos(PointD lb, PointD lt, PointD rt, PointD rb)
{
LB = lb;
LT = lt;
RT = rt;
RB = rb;
}
}
This is extension method for create TrnsData
public static TrnsData ToTrnsData
(this AffinePos srcPos, int w, int h)
{
var innerh = PosL2(srcPos.LB, srcPos.LT);
var innerw = PosL2(srcPos.RT, srcPos.LT);
var trgPos = srcPos.MoveToCenter(new PointD(w / 2.0, h / 2.0)); // ok
var fcenterX = srcPos.GetCenter().X;
var fcenterY = srcPos.GetCenter().Y;
var lcenterX = trgPos.GetCenter().X;
var lcenterY = trgPos.GetCenter().Y;
var xshift = lcenterX - fcenterX;
var yshift = lcenterY - fcenterY;
var dx = srcPos.LT.X - srcPos.RT.X;
var dy = srcPos.LT.Y - srcPos.RT.Y;
double radian;
if (Abs( dx) < 0.0001)
{
radian = 1.5708;
}
else if (Abs(dy) < 0.0001)
{
radian = 3.14159;
}
else
{
radian = Math.Atan(dy / dx);
}
return new TrnsData()
{
H = h,
W = w,
XShift = (int)xshift,
YShift = (int)yshift,
Innerw = innerw,
Innterh = innerh,
XSrcCnter = (int)fcenterX,
YSrcCnter = (int)fcenterY,
dX = (int)dx,
dY = (int)dy,
Angle = radian,
};
}
and additional extension method
public static byte[][] CreateJagged(int h, int w)
{
byte[][] output = new byte[h][];
for (int i = 0; i < h; i++)
{
output[i] = new byte[w];
}
return output;
}

Zoom every point in chart by mouse over

I have a chart on my c# windows application.
I want to zoom every point of chart when mouse on them.
like google map
I mean I don't want zoom all part of chart
I want zoom just specefic point like google map
code:
public partial class Form1 : Form
{
int[] myArrayX = new int[5];
double[] myArrayY = new double[5];
int lastX = -1;
double lastY = -0.6;
double xmax;
Graph.Chart chart;
public Form1()
{
InitializeComponent();
this.MouseWheel += new MouseEventHandler(Form1_MouseWheel);
}
void Form1_MouseWheel(object sender, MouseEventArgs e)
{
try
{
if (e.Delta > 0)
{
double xMin = chart.ChartAreas["draw"].AxisX.ScaleView.ViewMinimum;
double xMax = chart.ChartAreas["draw"].AxisX.ScaleView.ViewMaximum;
double yMin = chart.ChartAreas["draw"].AxisY.ScaleView.ViewMinimum;
double yMax = chart.ChartAreas["draw"].AxisY.ScaleView.ViewMaximum;
double posXStart = chart.ChartAreas["draw"].AxisX.PixelPositionToValue(e.Location.X) - (xMax - xMin) / 2;
double posXFinish = chart.ChartAreas["draw"].AxisX.PixelPositionToValue(e.Location.X) + (xMax - xMin) / 2;
double posYStart = chart.ChartAreas["draw"].AxisY.PixelPositionToValue(e.Location.Y) - (yMax - yMin) / 2;
double posYFinish = chart.ChartAreas["draw"].AxisY.PixelPositionToValue(e.Location.Y) + (yMax - yMin) / 2;
chart.ChartAreas["draw"].AxisX.ScaleView.Zoom(posXStart, posXFinish);
chart.ChartAreas["draw"].AxisY.ScaleView.Zoom(posYStart, posYFinish);
}
else if (e.Delta < 0)
{
ZoomOut();
}
}
catch { }
}
private void ZoomOut()
{
chart.ChartAreas["draw"].AxisX.ScaleView.ZoomReset();
chart.ChartAreas["draw"].AxisY.ScaleView.ZoomReset();
}
void CreateNewGraph()
{
// Create new Graph
chart = new Graph.Chart();
chart.Location = new System.Drawing.Point(13, 185);
chart.Size = new System.Drawing.Size(900, 500);
chart.ChartAreas.Add("draw");
chart.ChartAreas["draw"].AxisX.Minimum = 0;
chart.ChartAreas["draw"].AxisX.Maximum = 20;
chart.ChartAreas["draw"].AxisX.Interval = 1;
chart.ChartAreas["draw"].AxisX.MajorGrid.LineColor = Color.White;
chart.ChartAreas["draw"].AxisX.MajorGrid.LineDashStyle = Graph.ChartDashStyle.Dash;
chart.ChartAreas["draw"].AxisY.Minimum = -0.4;
chart.ChartAreas["draw"].AxisY.Maximum = 1;
chart.ChartAreas["draw"].AxisY.Interval = 0.2;
chart.ChartAreas["draw"].AxisY.MajorGrid.LineColor = Color.White;
chart.ChartAreas["draw"].AxisY.MajorGrid.LineDashStyle = Graph.ChartDashStyle.Dash;
chart.ChartAreas["draw"].BackColor = Color.Black;
var series = chart.Series.Add("Test");
chart.Series["Test"].ChartType = Graph.SeriesChartType.Line;
chart.Series["Test"].Color = Color.Yellow;
chart.Series["Test"].BorderWidth = 3;
chart.Legends.Add("MyLegend");
chart.Legends["MyLegend"].BorderColor = Color.YellowGreen;
// Set automatic zooming
chart.ChartAreas["draw"].AxisX.ScaleView.Zoomable = true;
chart.ChartAreas["draw"].AxisY.ScaleView.Zoomable = true;
// Set automatic scrolling
chart.ChartAreas["draw"].CursorX.AutoScroll = true;
chart.ChartAreas["draw"].CursorY.AutoScroll = true;
// Allow user selection for Zoom
chart.ChartAreas["draw"].CursorX.IsUserSelectionEnabled = true;
chart.ChartAreas["draw"].CursorY.IsUserSelectionEnabled = true;
chart.ChartAreas["draw"].AxisX.ScaleView.Zoomable = true;
chart.ChartAreas["draw"].AxisY.ScaleView.Zoomable = true;
//chart.MouseWheel += new MouseEventHandler(chart_MouseWheel);
}
private void Form1_Load(object sender, EventArgs e)
{
CreateNewGraph();
}
private void timer1_Tick(object sender, EventArgs e)
{
fillarray();
for (int i = 1; i <= 5; i += 1)
{
chart.Series["Test"].Points.AddXY(myArrayX[i - 1], myArrayY[i - 1]);
xmax = myArrayX[i - 1];
}
if (xmax >= 20)
{
chart.ChartAreas["draw"].AxisX.ScrollBar.Enabled = true;
chart.ChartAreas["draw"].AxisX.ScaleView.Zoomable = true;
chart.ChartAreas["draw"].AxisX.ScaleView.Zoom(0, xmax);
}
Controls.Add(this.chart);
}
public void fillarray()
{
for (int i = 1; i <= 5; i += 1)
{
lastX = lastX + 1;
myArrayX[i - 1] = lastX;
}
for (int i = 1; i < 5; i += 1)
{
lastY = lastY + 0.2;
myArrayY[i - 1] = lastY;
}
}
}
Asuming that you use the "standard" (since .NET 4.0) Charting Lib which is in the namespace System.Windows.Forms.DataVisualization.Charting. You can implement custom interactivity (zoom when mouse does this or that). MSDN is a good start and GIYF.
http://msdn.microsoft.com/en-us/library/dd456772(v=vs.110).aspx
There are also a lot of examples around the web.
good luck!

High quality graph/waveform display component in C#

I'm looking for a fast, professionally looking and customizable waveform display component in C#.
I'm wanting to display mainly real-time audio waveforms (fast!) in both time and frequency domain. I would like the ability to zoom, change axis settings, display multiple channels, customize the feel and colors etc...
Anybody knows of anything, whether commercial or not?
Thank you!
Diego
I bumped into a code project awhile ago that was doing this.
Check out http://www.codeproject.com/KB/miscctrl/GraphComponents.aspx it may be what you are looking for to do real-time graphing in .net
as far as i know, national instrument has some cool control, but it's not free.
http://sine.ni.com/psp/app/doc/p/id/psp-317
free ones:
http://www.codeproject.com/KB/audio-video/wavecontrol.aspx
Based on Illaya's code:
public void CreateWaveForm(string audioFilePath, string audioWaveFormFilePath)
{
try
{
int bytesPerSample = 0;
using (NAudio.Wave.Mp3FileReader reader = new NAudio.Wave.Mp3FileReader(audioFilePath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf)))
{
using (NAudio.Wave.WaveChannel32 channelStream = new NAudio.Wave.WaveChannel32(reader))
{
bytesPerSample = (reader.WaveFormat.BitsPerSample / 8) * channelStream.WaveFormat.Channels;
//Give a size to the bitmap; either a fixed size, or something based on the length of the audio
using (Bitmap bitmap = new Bitmap((int)Math.Round(reader.TotalTime.TotalSeconds * 40), 200))
{
int width = bitmap.Width;
int height = bitmap.Height;
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.Clear(Color.White);
Pen bluePen = new Pen(Color.Blue);
int samplesPerPixel = (int)(reader.Length / (double)(width * bytesPerSample));
int bytesPerPixel = bytesPerSample * samplesPerPixel;
int bytesRead;
byte[] waveData = new byte[bytesPerPixel];
for (float x = 0; x < width; x++)
{
bytesRead = reader.Read(waveData, 0, bytesPerPixel);
if (bytesRead == 0)
break;
short low = 0;
short high = 0;
for (int n = 0; n < bytesRead; n += 2)
{
short sample = BitConverter.ToInt16(waveData, n);
if (sample < low) low = sample;
if (sample > high) high = sample;
}
float lowPercent = ((((float)low) - short.MinValue) / ushort.MaxValue);
float highPercent = ((((float)high) - short.MinValue) / ushort.MaxValue);
float lowValue = height * lowPercent;
float highValue = height * highPercent;
graphics.DrawLine(bluePen, x, lowValue, x, highValue);
}
}
bitmap.Save(audioWaveFormFilePath);
}
}
}
}
catch
{
}
}
That is a wave flow displayer
http://www.codeproject.com/KB/audio-video/wavecontrol.aspx
Check out Zedgraph. It's a free graphing library that works great. There are lots of code samples on their website that allow you to do what you're asking. Zedgraph Downloads Their website seems to be having issues right now, but the download session works and contains all of their sample files.
This will generate waveform from audio file using nAudio...
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string strPath = Server.MapPath("audio/060.mp3");
string SongID = "2";
byte[] bytes = File.ReadAllBytes(strPath);
WriteToFile(SongID,strPath, bytes);
Response.Redirect("Main.aspx");
}
private void WriteToFile(string SongID, string strPath, byte[] Buffer)
{
try
{
int samplesPerPixel = 128;
long startPosition = 0;
//FileStream newFile = new FileStream(GeneralUtils.Get_SongFilePath() + "/" + strPath, FileMode.Create);
float[] data = FloatArrayFromByteArray(Buffer);
Bitmap bmp = new Bitmap(1170, 200);
int BORDER_WIDTH = 5;
int width = bmp.Width - (2 * BORDER_WIDTH);
int height = bmp.Height - (2 * BORDER_WIDTH);
NAudio.Wave.Mp3FileReader reader = new NAudio.Wave.Mp3FileReader(strPath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf));
NAudio.Wave.WaveChannel32 channelStream = new NAudio.Wave.WaveChannel32(reader);
int bytesPerSample = (reader.WaveFormat.BitsPerSample / 8) * channelStream.WaveFormat.Channels;
using (Graphics g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
Pen pen1 = new Pen(Color.Gray);
int size = data.Length;
string hexValue1 = "#009adf";
Color colour1 = System.Drawing.ColorTranslator.FromHtml(hexValue1);
pen1.Color = colour1;
Stream wavestream = new NAudio.Wave.Mp3FileReader(strPath, wf => new NAudio.FileFormats.Mp3.DmoMp3FrameDecompressor(wf));
wavestream.Position = 0;
int bytesRead1;
byte[] waveData1 = new byte[samplesPerPixel * bytesPerSample];
wavestream.Position = startPosition + (width * bytesPerSample * samplesPerPixel);
for (float x = 0; x < width; x++)
{
short low = 0;
short high = 0;
bytesRead1 = wavestream.Read(waveData1, 0, samplesPerPixel * bytesPerSample);
if (bytesRead1 == 0)
break;
for (int n = 0; n < bytesRead1; n += 2)
{
short sample = BitConverter.ToInt16(waveData1, n);
if (sample < low) low = sample;
if (sample > high) high = sample;
}
float lowPercent = ((((float)low) - short.MinValue) / ushort.MaxValue);
float highPercent = ((((float)high) - short.MinValue) / ushort.MaxValue);
float lowValue = height * lowPercent;
float highValue = height * highPercent;
g.DrawLine(pen1, x, lowValue, x, highValue);
}
}
string filename = Server.MapPath("image/060.png");
bmp.Save(filename);
bmp.Dispose();
}
catch (Exception e)
{
}
}
public float[] FloatArrayFromStream(System.IO.MemoryStream stream)
{
return FloatArrayFromByteArray(stream.GetBuffer());
}
public float[] FloatArrayFromByteArray(byte[] input)
{
float[] output = new float[input.Length / 4];
for (int i = 0; i < output.Length; i++)
{
output[i] = BitConverter.ToSingle(input, i * 4);
}
return output;
}
}

Categories

Resources