How do you calculate a rectangular wave from input values? - c#

Here's a picture to make it a little easier:
The blue line represents some input values that resemble waves with variable amplitudes and lengths. The y axis represents the values, the x axis represents time. Please note that there is quite some jitter in the wave. However, every wave has a certain minimum and maximum length.
The green line shows how the input values should be transformed.
Please note: The above picture is just a hand drawn example to explain the task. In an ideal case, the position of the rising and falling edges of the rectangular (green) wave are close to the blue waves average value. The height/amplitude of the green wave segments should match the values of the blue wave.
How do you calculate the green line?
Do you know of any C# libraries or algorithms to do that? I guess this could be a rather common task for electrical engineers, so there are most likely some common approaches available. If so, how are hey called?
How would you approach this requirements?
Any advice that helps in getting started is welcome.

Take a base frequency (f) at an amplitude (a).
Then add ODD harmonics with the inverse amplitude ie f * a + f3 * a/3 + f5 * a/5 + f7 * a/7 ...
This will tend towards a square wave as you add harmonics.
BTW Try doing the same with even harminics, and with all the harmonics - Great fun!!!
Good luck
Tony

Related

Stretch noise value meanwhile keep it in range (math issue!)

I implemented a simplex noise algorithm (by KdotJPG: OpenSimplex2S) which works fine, but I'd like to add a "function" which can increase/decrease the contrast of the noise. The noise method returns a value between -1 and 1 but the overall result is quite homogeneous. It is not bad at all, but I need to get a different outcome now.
So basically I should "pull" the value of the noise toward the range edges.. this will result more contrasting noise (more distance between the smaller and bigger values). Of course this change must be consistent and proportionally scaled between -1 and 1 (or 0-1) to get natural result.
Actually this is pure mathematical issue, but I'm not good in math at all! I'd like to make it more understandable to give this picture of two graphs:
So, on these graph the Y axis is the noise value (-1 is bottom and +1 it the top) and X axis is the time passed. The left graph shows the original result of the noise generator, and the right is the stretched version what I need to get. As you can see on the right graph everything the same but their values stretched/pulled toward the edge (toward the min, max limit) but still in range.
Is there any math formula or c# built in function to stretch the return value of the noise proportionally respect to the min, max values (-1/1 or 0/1)? If you need the code of the noise you can see it here OpenSimplex2S too, but this is irrelevant in my case, as I just wish to modify its return value. Thanks!

How to produce a detailed spectrogram from Fourier output?

I am developing a little application in Visual Studio 2010 in C# to draw a spectrogram (frequency "heat map").
I have already done the basic things:
Cut a rectangular windowed array out of the input signal array
Feed that array into FFT, which returns complex values
Store magnitude values in an array (spectrum for that window)
Step the window, and store the new values in other arrays, resulting in a jagged array that holds every step of windowing and their spectra
Draw these into a Graphics object, in color that uses the global min/max values of the heat map as relative cold and hot
The LEFT side of the screenshot shows my application, and on the RIGHT there is a spectrogram for the same input (512 samples long) and same rectangular window with size 32 from a program called "PAST - time series analysis" (https://folk.uio.no/ohammer/past/index.html). My 512 long sample array only consists of integer elements ranging from around 100 to 1400.
(Note: the light-blue bar on the very right of the PAST spectrogram is only because I accidentally left an unnecessary '0' element at the end of thats input array. Otherwise they are the same.)
Link to screenshot: https://drive.google.com/open?id=1UbJ4GyqmS6zaHoYZCLN9c0JhWONlrbe3
But I have encountered a few problems here:
The spectrogram seems very undetailed, related to another one that I made in "PAST time series analysis" for reference, and that one looks extremely detailed. Why is that?
I know that for an e.g. 32 long time window, the FFT returns 32 elements, the 0. elem is not needed here, the next 32/2 elements have the magnitude values I need. But this means that the frequency "resolution" on the output for a 32 long window is 16. That is exactly what my program uses. But "PAST" program shows a lot more detail. If you look at the narrow lines in the blue background, you can see that they show a nice pattern in the frequency axis, but in my spectrogram that information remains unseen. Why?
In the beginning (windowSize/2) wide window step-band and the ending (windowSize/2) step-band, there are less values for FFT input, thus there is less output, or just less precision. But in the "PAST" program those parts also seem relatively detailed, not just stretched bars like in mine. How can I improve that?
The 0. element of the FFT return array (the so called "DC" element) is a huge number, which is a lot bigger than the sample average, or even its sum. Why is that?
Why are my values (e.g. the maximum that you see near the color bar) so huge? That is just a magnitude value from the FFT output. Why are there different values in the PAST program? What correction should I use on the FFT output to get those values?
Please share your ideas, if you know more about this topic. I am very new to this. I only read first about Fourier transform a little more than a week ago.
Thanks in advance!
To get more smoothness in the vertical axis, zero pad your FFT so that there are more (interpolated) frequency bins in the output. For instance, zero pad your 32 data points so that you can use a 256 point or larger FFT.
To get more smoothness in the horizontal axis, overlap your FFT input windows (75% overlap, or more).
For both, use a smooth window function (Hamming or Von Hann, et.al.), and try wider windows, more than 32 (thus even more overlapped).
To get better coloring, try using a color mapping table, with the input being the log() of the (non zero) magnitudes.
You can also use multiple different FFTs per graph XY point, and decide which to color with based on local properties.
Hello LimeAndConconut,
Even though I do not know about PAST, I can provide you with some general information about FFT. Here is an answer for each of your points
1- You are right, a FFT performed on 32 elements returns 32 frequencies (null frequency, positive and negative components). It means that you already have all the information in your data, and PAST cannot get more information with the same 32 sized window. That's why I suspect the data to be interpolated for plotting, but this just visual. Once again PAST cannot create more information than the one you have in your data.
2- Once again I agree with you. On the borders, you have access to less frequency components. You can decide different strategies: not show data at the borders, or extend this data with zero-padding or circular padding
3- The zero element of the FFT should be the sum of your 32 windowed array. You need to check FFT normalization, have a look at the documentation of your FFT function.
4- Once again check the FFT normalization. Since PAST colorbar exhibit negative values, it seems to be plotted in logarithmic scale. This is common usage to use logarithm for plotting data with high dynamics in order to enhance details.

Barrel Distortion - Correcting image when expected/received control points are known

I'm working with a mounted industrial CCD camera and I have no information about its parameters. When an image is taken programmatically over WinUSB, the result in figure 1 is received. What you will notice is that the gaps between the lines differ greatly in the image. This is not the case in the actual image.
I have a technique for determining the location of the lines and have a list of pixel coordinates for where the lines must occur in a non-distorted image.
So I have
The pixel coordinate of the lines when the image is taken
The pixel coordinates of where the lines should be
What I need to do
Use these values to apply to every subsequent image taken with the camera, so that
each image is corrected.
However, I am pretty stuck on exisiting techniques which follow this approach. I know many algorithms exist on the internet which either make use of lens parameters or a strength parameter, but these techniques aren't very suitable in my scenario. The parameters aren't known and adjusting a strength value by the eye is not accurate enough.
Any pointers on techniques would be of great help; as I'm currently at a loss.
Figure 1. Distorted image taken by fixed location CCD camera
Hum, can you explain why the standard calibration techniques aren't suitable? You don't need to know the "true" camera parameters, but you do need to estimate the linear (actually, affine) part of the distortion, which is almost the same thing.
Explanation: assuming you are dealing with a plain old spherical-like lens, the first model I'd try for your case is a two-parameter radial distortion of the form:
X = f * |x - c|
Y = k1 * X^2 + k2 * X^4
y = c + Y / f
where
x = (u, v) are the distorted pixel coordinates;
c = (cu, cv) is an unknown center of distortion (i.e. the place in the image with zero
distortion, usually on (or very close to) the lens's focal axis.
|x -c| is the radial distance of x from c in the distorted image
f is an unknown scale factor
X is the location of the distorted pixel in scaled-centered coordinates
k1 and k2 are unknown distortion coefficients
Y is the undistorted pixel in scaled-centered coordinates
y is the undistorted pixel, located on the same radius c->x as x, at a distance Y/f from c.
So your unknowns are cu, cv, f, k1 and k2. It's starting to look like a camera calibration problem, isn't it?
Except you don't really need to estimate a "true" focal length f, since (I assume) you are not interested in computing rays in 3D space. So you can simplify the problem by assigning f as the value that makes the diameter of your data point distribution equal to, say, 2, so that all the centered-scaled points X will have coordinates no larger than 1.0 in absolute value. This helps in two ways: it improves the numerical conditioning of the problem, and drops the number of unknowns to 4.
You can usually initialize the estimation by using the center of your image for c, and zero values for k1 and k2, plug your data in your favorite least-squares optimizer, run, get the solution for the unknowns, and verify that it makes sense (on additional independent images). Rinse and repeat until you get something satisfactory.
Note that you can enrich the data set used for the estimation by using more than one image, assuming, of course, that the lens parameters are constant.

Nearest plane to non-coplanar points?

I have a number of non-coplanar 3D points and I want to calculate the nearest plane to them (They will always form a rough plane but with some small level of variation). This can be done by solving simultaneous linear equations, one for each point, of the form:
"Ax + By + Cz + D = 0"
The problem I'm having at the moment is twofold.
Firstly since the points are 3D floats they can't be relied on to be precise due to rounding errors.
Secondly all of the methods to solving linear equations programatically that I have found thus far involve using NXN matrices which severely limits what I would be able to do given that I have 4 unknowns and any number of linear equations (due to the variation in the number of 3D points).
Does anyone have a decent way to either solve the simultaneous linear equations without these constraints or, alternatively, a better way to calculate the nearest plane to non-coplanar points? (The precision of the plane calculation is not too much of a concern)
Thanks! :)
If your points are all close to the plane, you have a choice between ordinary least squares (where you see Z as a function of two independent variables X and Y and you minimize the sum of squared vertical distances to the plane), or total least squares (all variables independent, minimize the sum of normal distances). The latter requires a 3x3 SVD. (See http://en.wikipedia.org/wiki/Total_least_squares, unfortunately not the easiest presentation.)
If some of the points are outliers, you will need to resort to robust fitting methods. One of them is RANSAC: choose three points are random, build their plane and compute the sum of distances of all points to the plane, as a measure of fitness. Keep the best result after N drawings.
There are numerical methods for linear regression, which calculates the nearest line y=mx+c to a set of points. Your solution will be similar, only it has one more dimension and is thus a "planar regression".
If you don't care the mathematical accuracy of the algorithm and just want to get a rough result, then perhaps you'd randomly 3 points to construct a plane vector, then adjust it incrementally as you go through the rest of the points. Just some thoughts...

Vertical Curve Formula

I'm making just a basic application that just writes pixels along a curve in C#.
I came across this website with a formula that looks promising. I believe this website is also talking about the same thing here.
What I don't really understand is how to implement it. I tried looking at the JavaScript code on the first link but I can't really tell what data I need to supply. The things involving the PVC, PVI, or PVT are the things I don't understand.
The example situation I'm going to set up is just both of the grades (vertical incline/decline) is just 5 and -5. Let's say point 1 is at 0, 0 and point 2 is 100, 100.
Can someone explain some of the obscure variables in the formula and how would I use the formula to draw the curve?
Generally, to draw a curve in 2D you vary one parameter, and then collect x,y point pairs, and plot the pairs. In your case it will work to just vary the horizontal distance (x), and then collect the corresponding y-values, and then you can plot these.
As for the formula, it is very unclear. Basically it's just a parabola with a bunch of (poorly defined) jargon around it. To graph this, you want to vary x from 0 to L (this isn't obvious, btw, I had to work out the math, i.e., how to vary x so that the slopes would be as they suggest in the figure, anyway, it's 0 to L, and they should have said so).
I don't have C# running now, but hopefully you can translate this Python code:
from matplotlib.pyplot import plot, show
from numpy import arange
G1 = .1 # an initial slope (grade) of 10% (note that one never uses percentages directly in calculations, it's always %/100)
G2 = -.02 # a final slope (grade) of 2%
c = 0 # elevation (value of curve when x=0, that is, y at PVC
L = 10. # the length of the curve in whatever unit you want to use (ft, m, mi, etc), but this basically sets your unit system
N = 1000 # I'm going to calculate and plot 100 points to illustrate this curve
x = arange(0, L, float(L)/N) # an array of N x values from 0 to (almost) L
# calculate the curve
a = (G2-G1)/(2*L)
b = G1
y = a*x*x + b*x + c # this is shorthand for a loop y[0]=a*x[0]*x[0] + b*...
plot(x, y)
show()
print (y[1]-y[0])/(x[1]-x[0]), (y[-1]-y[-2])/(x[-1]-x[-2])
The final line prints the initial and final slopes as a check (in Python neg indexing counts from the back of the array), and this match what I specified for G1 and G2. The plot looks like:
As for your requests: "The example situation I'm going to set up is just both of the grades (vertical incline/decline) is just 5 and -5. Let's say point 1 is at 0, 0 and point 2 is 100, 100.", in a parabola you basically get three free parameters (corresponding to a, b, and c), and here, I think, you over-specified it.
What are PVC, PVT, and PVI? PVC: the starting point, so Y_PVC is the height of the starting point. PVT: the ending point. PVI: if you draw a line from PVC at the initial slope G1 (ie the tangent to the curve on the left), and similarly from PVT, the point where they intersect is called PVI (though why someone would ever care about this point is beyond me).

Categories

Resources