Perlin noise how to get a vector from a permutation-array? - hash

I am currently trying to implement perlin noise on HLSL in 2D. I watched Ken's improved Perlin Noise, but i don't understand how the conversion from the permuation-array into Vectors works.
I know that i can get the hash-code like this
int g00 = p[floorX + p[floorY]],
g10 = p[floorX + 1 + p[floorY]],
g01 = p[floorX + p[floorY + 1]],
g11 = p[floorX + 1 + p[floorY + 1]];
(floorX and floorY are the floored x,y coordinates broken down to 8 bits.)
from here, but i still don't understand it. I also don't understand how the "grad(...)"- method from Ken's implementation works.
Can anyone explain me how that works?

Ken Perlin's actual java implementation is really pseudo-code for his GPU implementation, which means some parts (especially the one you are stuck on) are downright impenetrable (using some optimizing theory).
For readability,
try Stefan Gustavson's reference java implementation from Simplex Noise Demystified' (2005) in pdf, it is much more legible as it was designed partly as a teaching tool.
The long set of bit-operations and conditionals (using the trinary short hand operator) in his grad() function are there to choose a pseud-random Unit Vector. In particular, it should choose from a set that are equally spread around the unit circle (in 2D), or sphere (approximated by midpoints of the sides of a cube, in 3D), etc., and do so with an equal probability of each one.
If the lowest 4 bits are sufficiently scrambled by the hashing routine, those 16 choices can be mapped to the 12 best 3D vectors (of length sqrt2) quickly - that is what it's doing (and, imho, why Perlin noise is rarely ever implemented up to the standard he set forth in the accompanying paper).
In particular, he sums two axis unit vectors (x, y, and z)-pseudo-randomly chosen, with pseudo-randomly determined signs each.
Since you want 2D noise, may I suggest using a lookup table for the gradients themselves, but please make them all the same length (it looks a little better than the shortcut Perlin left in the appendix that's been copied EveryWhere, and the vectors are usually floats already). And you can actually choose 8 good basis gradients (so the bitwise scramble works without deformation!).

Related

Circular convolution of binary vectors (mod 2) using NTT

Let x, y be vectors of length n, with entries either 1 or 0. I want to efficiently compute the circular convolution
(x * y) mod 2
Where each component of the result is taken mod 2.
I know how to do it using a Fast Fourier Transform
(multiply Fourier transforms of x and y. transform back. Do the "mod 2")
However, this uses floating point calculations to solve a discrete problem and for large n (I'm interested in n ~ 10^7) it might lead to rounding errors. I expect there is a better way to do this using the number theoretic transform (NTT) but unfortunately I'm not familiar with number theory or NTT.
I looked at this website. Following the procedure there,
let's say n = 10^7. I need
a modulus M (use 10^7).
a prime N=kn+1 for some k. (use N = 3 * 10^7 + 1)
a root ω≡g^k mod N , where g is a generator (e.g. ω=2744)
Do the transform, etc.
Question
This seems promising. However, I would need 32-bit integers to store each bit during this calculation?
Also, this is not making use of the fact that I only need results modulo 2.
Is there a way to make use of this to simplify the procedure?
Since I don't know the number theory, this is not obvious to me.
I'm not asking for a full solution, only for an argument if my "mod 2" significantly simplifies the implementation (both in terms of difficulty to implement the necessary algorithms as well as computational resources).
Another question: If it's not possible to simplify using "mod 2", do you think it would still pay off to use NTT, as opposed to just throwing a well-known FFT library at the floating point problem?
For the NTT, your procedure looks correct. Yes, you would need 32-bit integers for each bit in your original vector. Unfortunately, there's not a lot you can do there to make use of the fact that the end result is mod 2, since you need a root of order 10^7. You may be able to shrink that number by a couple factors of two (and doing the standard DFT for a few base levels of recursion), but it wouldn't change much, relatively speaking.
Note, for your FFT implementation, I believe you could use integer arithmetic since its mod 2, but I'm not convinced it would be at all efficient. See this math stackexchange answer for details.

Integration of numerical data

I'm writing a test tomorrow and I'm contemplating doing everything on Matlab, to save time.
Some questions require numerical integration of datapoints (points, not necessarily functions).
E.g.
C=[0 1 5 8 10 8 6 4 3 2.2 1.5 0.6 0];
I've used trapz(C) to determine the integral of the data (area under the curve) and compared that to what my textbook gets.
Often, there is too large a difference between the two.
Is there another easy and fast way that the above data can be integrated numerically using Matlab, e.g. by using Simpson's rule, Gauleg or spline?
I've taken a look at integrate(), but that seems to work only on functions?
Are your data points spaced by dx = 1? if dx is .5 for example, this would change the result by a factor of two.
Otherwise, I'd point out: the data point by themselves, assuming zero width, will produce an area of 0: the point being that your textbook must be assuming some kind of interpolation between them to get a meaningful integral. If they are straight line segements, trapz(C) should give you the correct result; if your textbook is doing something else (points taken from a smooth function, for example), it is not surprising the results would be different.

Using matlab to obtain the vector fields and the angles made by the vector field on a closed curve?

Here is the given system I want to plot and obtain the vector field and the angles they make with the x axis. I want to find the index of a closed curve.
I know how to do this theoretically by choosing convenient points and see how the vector looks like at that point. Also I can always use
to compute the angles. However I am having trouble trying to code it. Please don't mark me down if the question is unclear. I am asking it the way I understand it. I am new to matlab. Can someone point me in the right direction please?
This is a pretty hard challenge for someone new to matlab, I would recommend taking on some smaller challenges first to get you used to matlab's conventions.
That said, Matlab is all about numerical solutions so, unless you want to go down the symbolic maths route (and in that case I would probably opt for Mathematica instead), your first task is to decide on the limits and granularity of your simulated space, then define them so you can apply your system of equations to it.
There are lots of ways of doing this - some more efficient - but for ease of understanding I propose this:
Define the axes individually first
xpts = -10:0.1:10;
ypts = -10:0.1:10;
tpts = 0:0.01:10;
The a:b:c syntax gives you the lower limit (a), the upper limit (c) and the spacing (b), so you'll get 201 points for the x. You could use the linspace notation if that suits you better, look it up by typing doc linspace into the matlab console.
Now you can create a grid of your coordinate points. You actually end up with three 3d matrices, one holding the x-coords of your space and the others holding the y and t. They look redundant, but it's worth it because you can use matrix operations on them.
[XX, YY, TT] = meshgrid(xpts, ypts, tpts);
From here on you can perform whatever operations you like on those matrices. So to compute x^2.y you could do
x2y = XX.^2 .* YY;
remembering that you'll get a 3d matrix out of it and all the slices in the third dimension (corresponding to t) will be the same.
Some notes
Matlab has a good builtin help system. You can type 'help functionname' to get a quick reminder in the console or 'doc functionname' to open the help browser for details and examples. They really are very good, they'll help enormously.
I used XX and YY because that's just my preference, but I avoid single-letter variable names as a general rule. You don't have to.
Matrix multiplication is the default so if you try to do XX*YY you won't get the answer you expect! To do element-wise multiplication use the .* operator instead. This will do a11 = b11*c11, a12 = b12*c12, ...
To raise each element of the matrix to a given power use .^rather than ^ for similar reasons. Likewise division.
You have to make sure your matrices are the correct size for your operations. To do elementwise operations on matrices they have to be the same size. To do matrix operations they have to follow the matrix rules on sizing, as will the output. You will find the size() function handy for debugging.
Plotting vector fields can be done with quiver. To plot the components separately you have more options: surf, contour and others. Look up the help docs and they will link to similar types. The plot family are mainly about lines so they aren't much help for fields without creative use of the markers, colours and alpha.
To plot the curve, or any other contour, you don't have to test the values of a matrix - it won't work well anyway because of the granularity - you can use the contour plot with specific contour values.
Solving systems of dynamic equations is completely possible, but you will be doing a numeric simulation and your results will again be subject to the granularity of your grid. If you have closed form solutions, like your phi expression, they may be easier to work with conceptually but harder to get working in matlab.
This kind of problem is tractable in matlab but it involves some non-basic uses which are pretty hard to follow until you've got your head round Matlab's syntax. I would advise to start with a 2d grid instead
[XX, YY] = meshgrid(xpts, ypts);
and compute some functions of that like x^2.y or x^2 - y^2. Get used to plotting them using quiver or plotting the coordinates separately in intensity maps or surfaces.

Detect incorrect points in a homogeneous surface

In my project i have hige surfaces of 20.000 points computed by a algorithm. This algorithm, sometimes, has an error, computing 1 or more points in an small area incorrectly.
This error can not be solved in the algorithm, but needs to be detected afterwards.
The error can be seen in the next figure:
As you can see, there is a point wrongly computed that not only breaks the full homogeneous surface, but also destroys the aestetics of the plot (wich is also important in the project.)
Sometimes it can be more than a point, in general no more than 5 or 6. The error is allways the Z axis, so no need to check X and Y
I have been squeezing my mind to find a bit "generic" algorithm to detect this poitns.
I thougth that maybe taking patches of surface and meaning the Z, then detecting the points out of the variance... but I dont think it will work allways.
Any ideas?
NOTE: I dont want someone to write code for me, just an idea.
PD: relevant code for the avobe image:
[x,y] = meshgrid([-2:.07:2]);
Z = x.*exp(-x.^2-y.^2);
subplot(1,2,1)
surf(x,y,Z,gradient(Z))
subplot(1,2,2)
Z(35,35)=Z(35,35)+0.3;
surf(x,y,Z,gradient(Z))
The standard trick is to use a Laplacian, looking for the largest outliers. (This is not unlike what Mohsen posed for an answer, but is actually a bit easier.) You could even probably do it with conv2, so it would be pretty efficient.
I could offer a few ways to implement the idea. A simple one is to use my gridfit tool, found on the File Exchange. (Gridfit essentially uses a Laplacian for its smoothing operation.) Fit the surface with all points included, then look for the single point that was perturbed the most by the fit. Exclude it, then rerun the fit, again looking for the largest outlier. (With gridfit, you can use weights to give points a zero weight, a simple way to exclude a point or list of points.) When the largest perturbation that was needed is small enough, you can decide to stop the process. A nice thing is gridfit will also impute new values for the outliers, filling in all of the holes.
A second approach is to use the Laplacian directly, in more of a filtering approach. Here, you simply compute a value at each point that is the average of each neighbor to the left, right, above, and below. The single value that is most largely in disagreement with its computed average is replaced with a new value. Or, you can use a weighted average of the new value with the old one there. Again, iterate until the process does not generate anything larger than some tolerance. (This is the basis of an old outlier detection and correction scheme that I recall from the Fortran IMSL libraries, but probably dates back to roughly 30 years ago.)
Since your functions seems to vary smoothly these abrupt changes can be detected by looking into the derivatives. You can
Take the derivative in one direction
Calculate mean and standard deviation of derivative
Find the points by looking for points that are further from mean by certain multiple of standard deviation.
Here is the code
U=diff(Z);
V=(U-mean(U(:)))/std(U(:));
surf(x(2:end,:),y(2:end,:),V)
V=[zeros(1,size(V,2)); V];
V(abs(V)<10)=0;
V=sign(V);
W=cumsum(V);
[I,J]=find(W);
outliers = [I, J];
For your example you get this plot for V with a peak at around 21.7 while second peak is at around 1.9528, so maybe a threshold of 10 is ok.
and running the code returns
outliers =
35 35
The need for cumsum is for the cases that you have a patch of points next to each other that are incorrect.

How to use multilinear functions with Matlab?

Multilinear function is such that it is linear with respect to each variable. For example, x1+x2x1-x4x3 is a multilinear function. Working with them requires proper data-structure and algrorihms for fast assignment, factorization and basic aritmetics.
Does there exist some library for processing multilinear function in Matlab?
No, not that much so.
For example, interp2 an interpn have 'linear' methods, which are effectively as you describe. But that is about the limit of what is supplied. And there is nothing for more general functions of this form.
Anyway, this class of functions has some significant limitations. For example, as applied to color image processing, they are often a terribly poor choice because of what they do to neutrals in your image. Other functional forms are strongly preferred there.
Of course, there is always the symbolic toolbox for operations such as factorization, etc., but that tool is not a speed demon.
Edit: (other functional forms)
I'll use a bilinear form as the example. This is the scheme that is employed by tools like Photoshop when bilinear interpolation is chosen. Within the square region between a group of four pixels, we have the form
f(x,y) = f_00*(1-x)*(1-y) + f_10*x*(1-y) + f_01*(1-x)*y + f_11*x*y
where x and y vary over the unit square [0,1]X[0,1]. I've written it here as a function parameterized by the values of our function at the four corners of the square. Of course, those values are given in image interpolation as the pixel values at those locations.
As has been said, the bilinear interpolant is indeed linear in x and in y. If you hold either x or y fixed, then the function is linear in the other variable.
An interesting question is what happens along the diagonal of the unit square? Thus, as we follow the path between points (0,0) and (1,1). Since x = y along this path, substitute x for y in that expression, and expand.
f(x,x) = f_00*(1-x)*(1-x) + f_10*x*(1-x) + f_01*(1-x)*x + f_11*x*x
= (f_11 + f_00 - f_10 - f_01)*x^2 + (f_10 + f_01 - 2*f_00)*x + f_00
So we end up with a quadratic polynomial along the main diagonal. Likewise, had we followed the other diagonal, it too would have been quadratic in form. So despite the "linear" nature of this beast, it is not truly linear along any linear path. It is only linear along paths that are parallel to the axes of the interpolation variables.
In three dimensions, which is where we really care about this behavior for color space interpolation, that main diagonal will now show a cubic behavior along that path, despite that "linear" name for the function.
Why are these diagonals important? What happens along the diagonal? If our mapping takes colors from an RGB color space to some other space, then the neutrals in your image live along the path R=G=B. This is the diagonal of the cube. The problem is when you interpolate an image with a neutral gradient, you will see a gradient in the result after color space conversion that moves from neutral to some non-neutral color as the gradient moves along the diagonal through one cube after another. Sadly, the human eye is very able to see differences from neutrality, so this behavior is critically important. (By the way, this is what happens inside the guts of your color ink jet printer, so people do care about it.)
The alternative chosen is to dissect the unit square into a pair of triangles, with the shared edge along that main diagonal. Linear interpolation now works inside a triangle, and along that edge, the interpolant is purely a function of the endpoints of that shared edge.
In three dimensions, the same thing happens, except we use a dissection of the unit cube into SIX tetrahedra, all of which share the main diagonal of the cube. The difference is indeed critically important, with a dramatic reduction in the deviation of your neutral gradients from neutrality. As it turns out, the eye is NOT so perceptive to deviations along other gradients, so the loss along other paths does not hurt nearly so much. It is neutrals that are crucial, and the colors we must reproduce as accurately as possible.
So IF you do color space interpolation using mappings defined by what are commonly called 3-d lookup tables, this is the agreed way to do that interpolation (agreed upon by the ICC, an acronym for the International Color Consortium.)