Project: intelligence scissors.
The first part of the project is to load an image (in the form of RGBPixel 2d array) then to construct a graph of weights to use it later to determine the shortest path between 2 points on the image (the 2 points will be determined by an anchor and a free point..In short i will have the source and the destination points).
I have a function that open the image and return a RGBPixel 2d array already made.Now image is loaded i want to construct the graph to do the i should use a function called CalculatePixelEnergies here is the code
public static Vector2D CalculatePixelEnergies(int x, int y, RGBPixel[,] ImageMatrix)
{
if (ImageMatrix == null) throw new Exception("image is not set!");
Vector2D gradient = CalculateGradientAtPixel(x, y, ImageMatrix);
double gradientMagnitude = Math.Sqrt(gradient.X * gradient.X + gradient.Y * gradient.Y);
double edgeAngle = Math.Atan2(gradient.Y, gradient.X);
double rotatedEdgeAngle = edgeAngle + Math.PI / 2.0;
Vector2D energy = new Vector2D();
energy.X = Math.Abs(gradientMagnitude * Math.Cos(rotatedEdgeAngle));
energy.Y = Math.Abs(gradientMagnitude * Math.Sin(rotatedEdgeAngle));
return energy;
}
This function use CalculateGradientAtPixel, Here is the code in case you want it.
private static Vector2D CalculateGradientAtPixel(int x, int y, RGBPixel[,] ImageMatrix)
{
Vector2D gradient = new Vector2D();
RGBPixel mainPixel = ImageMatrix[y, x];
double pixelGrayVal = 0.21 * mainPixel.red + 0.72 * mainPixel.green + 0.07 * mainPixel.blue;
if (y == GetHeight(ImageMatrix) - 1)
{
//boundary pixel.
for (int i = 0; i < 3; i++)
{
gradient.Y = 0;
}
}
else
{
RGBPixel downPixel = ImageMatrix[y + 1, x];
double downPixelGrayVal = 0.21 * downPixel.red + 0.72 * downPixel.green + 0.07 * downPixel.blue;
gradient.Y = pixelGrayVal - downPixelGrayVal;
}
if (x == GetWidth(ImageMatrix) - 1)
{
//boundary pixel.
gradient.X = 0;
}
else
{
RGBPixel rightPixel = ImageMatrix[y, x + 1];
double rightPixelGrayVal = 0.21 * rightPixel.red + 0.72 * rightPixel.green + 0.07 * rightPixel.blue;
gradient.X = pixelGrayVal - rightPixelGrayVal;
}
return gradient;
}
In my code of graph construction i decided to make a 2d double array to hold the weights, here what i do but it seems to be a wrong construction
public static double [,] calculateWeights(RGBPixel[,] ImageMatrix)
{
double[,] weights = new double[1000, 1000];
int height = ImageOperations.GetHeight(ImageMatrix);
int width = ImageOperations.GetWidth(ImageMatrix);
for (int y = 0; y < height - 1; y++)
{
for (int x = 0; x < width - 1; x++)
{
Vector2D e;
e = ImageOperations.CalculatePixelEnergies(x, y, ImageMatrix);
weights[y + 1, x] = 1 / e.X;
weights[y, x + 1] = 1 / e.Y;
}
}
return weights;
}
an example for an image
an other example for an image
I try to make a meteor like this video,
but I can only get like this:
This is my simplex noise:
public class PerlinNoise{
int B = 256;
int[] m_perm = new int[B+B];
Texture2D m_permTex;
public int octava;
public float frequencia, amplitud;
public PerlinNoise(int seed, float frec, float amp, int oct)
{
octava = oct;
amplitud = amp;
frequencia = frec;
UnityEngine.Random.seed = seed;
int i, j, k;
for (i = 0 ; i < B ; i++)
{
m_perm[i] = i;
}
while (--i != 0)
{
k = m_perm[i];
j = UnityEngine.Random.Range(0, B);
m_perm[i] = m_perm[j];
m_perm[j] = k;
}
for (i = 0 ; i < B; i++)
{
m_perm[B + i] = m_perm[i];
}
}
float FADE(float t) { return t * t * t * ( t * ( t * 6.0f - 15.0f ) + 10.0f ); }
float LERP(float t, float a, float b) { return (a) + (t)*((b)-(a)); }
float GRAD1(int hash, float x )
{
int h = hash & 15;
float grad = 1.0f + (h & 7);
if ((h&8) != 0) grad = -grad;
return ( grad * x );
}
float GRAD2(int hash, float x, float y)
{
int h = hash & 7;
float u = h<4 ? x : y;
float v = h<4 ? y : x;
return (((h&1) != 0)? -u : u) + (((h&2) != 0) ? -2.0f*v : 2.0f*v);
}
float GRAD3(int hash, float x, float y , float z)
{
int h = hash & 15;
float u = h<8 ? x : y;
float v = (h<4) ? y : (h==12 || h==14) ? x : z;
return (((h&1) != 0)? -u : u) + (((h&2) != 0)? -v : v);
}
float Noise1D( float x )
{
//returns a noise value between -0.5 and 0.5
int ix0, ix1;
float fx0, fx1;
float s, n0, n1;
ix0 = (int)Mathf.Floor(x); // Integer part of x
fx0 = x - ix0; // Fractional part of x
fx1 = fx0 - 1.0f;
ix1 = ( ix0+1 ) & 0xff;
ix0 = ix0 & 0xff; // Wrap to 0..255
s = FADE(fx0);
n0 = GRAD1(m_perm[ix0], fx0);
n1 = GRAD1(m_perm[ix1], fx1);
return 0.188f * LERP( s, n0, n1);
}
public float Noise2D( float x, float y )
{
int ix0, iy0, ix1, iy1;
float fx0, fy0, fx1, fy1, s, t, nx0, nx1, n0, n1;
ix0 = (int)Mathf.Floor(x);
iy0 = (int)Mathf.Floor(y);
fx0 = x - ix0;
fy0 = y - iy0;
fx1 = fx0 - 1.0f;
fy1 = fy0 - 1.0f;
ix1 = (ix0 + 1) & 0xff; // Wrap to 0..255
iy1 = (iy0 + 1) & 0xff;
ix0 = ix0 & 0xff;
iy0 = iy0 & 0xff;
t = FADE( fy0 );
s = FADE( fx0 );
nx0 = GRAD2(m_perm[ix0 + m_perm[iy0]], fx0, fy0);
nx1 = GRAD2(m_perm[ix0 + m_perm[iy1]], fx0, fy1);
n0 = LERP( t, nx0, nx1 );
nx0 = GRAD2(m_perm[ix1 + m_perm[iy0]], fx1, fy0);
nx1 = GRAD2(m_perm[ix1 + m_perm[iy1]], fx1, fy1);
n1 = LERP(t, nx0, nx1);
return 0.507f * LERP( s, n0, n1 );
}
float Noise3D( float x, float y, float z )
{
//returns a noise value between -1.5 and 1.5
int ix0, iy0, ix1, iy1, iz0, iz1;
float fx0, fy0, fz0, fx1, fy1, fz1;
float s, t, r;
float nxy0, nxy1, nx0, nx1, n0, n1;
ix0 = (int)Mathf.Floor( x ); // Integer part of x
iy0 = (int)Mathf.Floor( y ); // Integer part of y
iz0 = (int)Mathf.Floor( z ); // Integer part of z
fx0 = x - ix0; // Fractional part of x
fy0 = y - iy0; // Fractional part of y
fz0 = z - iz0; // Fractional part of z
fx1 = fx0 - 1.0f;
fy1 = fy0 - 1.0f;
fz1 = fz0 - 1.0f;
ix1 = ( ix0 + 1 ) & 0xff; // Wrap to 0..255
iy1 = ( iy0 + 1 ) & 0xff;
iz1 = ( iz0 + 1 ) & 0xff;
ix0 = ix0 & 0xff;
iy0 = iy0 & 0xff;
iz0 = iz0 & 0xff;
r = FADE( fz0 );
t = FADE( fy0 );
s = FADE( fx0 );
nxy0 = GRAD3(m_perm[ix0 + m_perm[iy0 + m_perm[iz0]]], fx0, fy0, fz0);
nxy1 = GRAD3(m_perm[ix0 + m_perm[iy0 + m_perm[iz1]]], fx0, fy0, fz1);
nx0 = LERP( r, nxy0, nxy1 );
nxy0 = GRAD3(m_perm[ix0 + m_perm[iy1 + m_perm[iz0]]], fx0, fy1, fz0);
nxy1 = GRAD3(m_perm[ix0 + m_perm[iy1 + m_perm[iz1]]], fx0, fy1, fz1);
nx1 = LERP( r, nxy0, nxy1 );
n0 = LERP( t, nx0, nx1 );
nxy0 = GRAD3(m_perm[ix1 + m_perm[iy0 + m_perm[iz0]]], fx1, fy0, fz0);
nxy1 = GRAD3(m_perm[ix1 + m_perm[iy0 + m_perm[iz1]]], fx1, fy0, fz1);
nx0 = LERP( r, nxy0, nxy1 );
nxy0 = GRAD3(m_perm[ix1 + m_perm[iy1 + m_perm[iz0]]], fx1, fy1, fz0);
nxy1 = GRAD3(m_perm[ix1 + m_perm[iy1 + m_perm[iz1]]], fx1, fy1, fz1);
nx1 = LERP( r, nxy0, nxy1 );
n1 = LERP( t, nx0, nx1 );
return 0.936f * LERP( s, n0, n1 );
}
public float FractalNoise1D(float x, int octNum, float frq, float amp)
{
float gain = 1.0f;
float sum = 0.0f;
for(int i = 0; i < octNum; i++)
{
sum += Noise1D(x*gain/frq) * amp/gain;
gain *= 2.0f;
}
return sum;
}
public float FractalNoise2D(float x, float y, int octNum, float frq, float amp)
{
float gain = 1.0f;
float sum = 0.0f;
for(int i = 0; i < octNum; i++)
{
sum += Noise2D(x*gain/frq, y*gain/frq) * amp/gain;
gain *= 2.0f;
}
return sum;
}
public int Noise2D(Vector3Int v3) {
return Mathf.RoundToInt(FractalNoise2D(v3.x,v3.z,octava,frequencia,amplitud));
}
public int Noise2D(int x, int z)
{
return Mathf.RoundToInt(FractalNoise2D(x, z, octava, frequencia, amplitud));
}
public float FractalNoise3D(float x, float y, float z, int octNum, float frq, float amp)
{
float gain = 1.0f;
float sum = 0.0f;
for(int i = 0; i < octNum; i++)
{
sum += Noise3D(x*gain/frq, y*gain/frq, z*gain/frq) * amp/gain;
gain *= 2.0f;
}
return sum;
}
public void LoadPermTableIntoTexture()
{
m_permTex = new Texture2D(256, 1, TextureFormat.Alpha8, false);
m_permTex.filterMode = FilterMode.Point;
m_permTex.wrapMode = TextureWrapMode.Clamp;
for(int i = 0; i < 256; i++)
{
float v = (float)m_perm[i] / 255.0f;
m_permTex.SetPixel(i, 0, new Color(0,0,0,v));
}
m_permTex.Apply();
}
}
This is my implementation:
public void Resimulate() {
PerlinNoise per = new PerlinNoise(seed, frec, amp, octa);
for (int x = 0; x < TamX; x++)
{
for (int y = 0; y < TamY; y++)
{
for (int z = 0; z < TamZ; z++)
{
if (per.FractalNoise3D(x, y, z, octa, frec, amp)>0)
{
lista.Add(new Bloque(new Vector3Int(x, y, z)));
}
}
}
}
}
I found information on various pages, blogs and here but found nothing that worked for me. If anyone has information I would greatly appreciate your help.
Thank you for helping me.
First, it's important to note that the code you have is not Simplex noise! It's the older "Perlin noise" algorithm that tends to exhibit visually significant directional artifacts.
I would suggest avoiding both Perlin noise and Simplex noise altogether. Perlin because of the directional artifacts, and Simplex because you run into patent issues with the 3D implementation.
There's an algorithm I've designed recently to get around both of those issues, that's starting to be adopted by a fair number of game developers, called OpenSimplex noise. Code: https://gist.github.com/KdotJPG/b1270127455a94ac5d19
(EDIT: Here's a C# port: https://gist.github.com/omgwtfgames/601497972e4e30fd9c5f)
Do something like this:
const double S = 24; //Sparsity of noise features
public void Resimulate() {
//To get fractal noise, ideally you want multiple instances of noise so you don't get odd behavior near (0,0,0)
OpenSimplexNoise n1 = new OpenSimplexNoise(seed);
OpenSimplexNoise n2 = new OpenSimplexNoise(seed+1);
OpenSimplexNoise n3 = new OpenSimplexNoise(seed+2);
for (int x = 0; x < TamX; x++) {
for (int y = 0; y < Tamy; z++) {
for (int z = 0; z < TamZ; z++) {
double n = (n1.eval(x / S, y / S, z / S)
+ n2.eval(x / S / 2, y / S / 2, z / S / 2) * .5
+ n3.eval(x / S / 4, y / S / 4, z / S / 4) * .25)
/ (1 + .5 + .25);
double dx = (TamX / 2.0 - x);
double dy = (TamY / 2.0 - y);
double dz = (TamZ / 2.0 - z);
double d = dx*dx + dy*dy + dz*dz;
//d is now your squared distance from the center.
//n is your fractal noise value
//you want to combine d and n to form some threshold that
//determines whether or not there is a block.
//threshold = d / C1 + n + C2 > 0 where C1 and C2 are constants you choose
}
}
}
}
EDIT: Here's a visual difference between Perlin and OpenSimplex:
Left is noise(x, y, 0) grayscale
Next is noise(x, y, 0) > 0 ? white : black
Next is |noise(x, y, 0)| > 0.1 ? white : black
Next is noise(x, y, 0.5) grayscale
I have an fisheye image and what I am trying to do is convert it into landscape.
The code I have written converts it into landscape but when it comes to divding it into different parts it adds black parts to them.
Can anyone help
using System;
using System.Drawing;
namespace fisheye_image
{
class Program
{
static void Main()
{
// assume the source image is square, and its width has even number of pixels
Bitmap bm = (Bitmap)Image.FromFile(#"C:\Users\abc\Desktop\lillestromfisheye.jpg");
int l = bm.Width / 2;
int i, j;
int x, y;
double radius, theta;
// calculated indices in Cartesian coordinates with trailing decimals
double fTrueX, fTrueY;
int iSourceWidth = (2 * l);
int run = 0, lastWidth = 1;
while (run<4)
{
Bitmap bmDestination = new Bitmap(lastWidth*l, l);
for (i = 0; i < bmDestination.Height; ++i)
{
radius = (double)(l - i);
for (j = run*l; j < lastWidth*l ; ++j)
{
// theta = 2.0 * Math.PI * (double)(4.0 * l - j) / (double)(4.0 * l);
theta = 2.0 * Math.PI * (double)(-j) / (double)(4.0 * l);
fTrueX = radius * Math.Cos(theta);
fTrueY = radius * Math.Sin(theta);
// "normal" mode
x = (int)(Math.Round(fTrueX)) + l;
y = l - (int)(Math.Round(fTrueY));
// check bounds
if (x >= 0 && x < iSourceWidth && y >= 0 && y < iSourceWidth)
{
bmDestination.SetPixel(j, i, bm.GetPixel(x, y));
}
}
}
bmDestination.Save(#"C:\Users\abc\Desktop\fisheyelandscape"+run.ToString()+".jpg",System.Drawing.Imaging.ImageFormat.Jpeg);
run++;
lastWidth++;
}
}
}
}
Below are the original and processed images
We just need to add another variable 'k' in the second for loop that goes from zero to the width of destination image.
while (run<4)
{
Bitmap bmDestination = new Bitmap(l, l);
for (i = 0; i < bmDestination.Height; ++i)
{
radius = (double)(l - i);
for (j = run * l, k = 0; j < lastWidth * l||k < bmDestination.Width; ++j, ++k)
{
// theta = 2.0 * Math.PI * (double)(4.0 * l - j) / (double)(4.0 * l);
theta = 2.0 * Math.PI * (double)(-j) / (double)(4.0 * l);
fTrueX = radius * Math.Cos(theta);
fTrueY = radius * Math.Sin(theta);
// "normal" mode
x = (int)(Math.Round(fTrueX)) + l;
y = l - (int)(Math.Round(fTrueY));
// check bounds
if (x >= 0 && x < iSourceWidth && y >= 0 && y < iSourceWidth)
{
bmDestination.SetPixel(k, i, bm.GetPixel(x, y));
}
}
I'm trying to give certain colors to image based on their movement (like vector direction) in Emgu Cv. I have managed to calculate the dense optical flow to my video stream. I have used this
OpticalFlow.Farneback(prev,NextFrame,velx,vely,0.5,1,1,2,5,1.1,Emgu.CV.CvEnum.OPTICALFLOW_FARNEBACK_FLAG.FARNEBACK_GAUSSIAN);
The variable vely and velx contains the velocity of vertical and horizontal directions.Does anyone know how to map colors to these. There are many algorithms that calculates the dense flow. HS also can be used, but I'm not sure what to use.
Any solution would be really appreciated.
EDIT:
Optical Flow Color Map in OpenCV
This is the same thing that i wanted, since I'm using Emgu cv I tried to convert this code to c# but I cannot understand how to pass the dense flow to function "colorflow".
public void colorflow(MCvMat imgColor)
{
MCvMat imgHsv = new MCvMat();
double max_s = 0;
double[] hsv_ptr = new double[3000];
IntPtr[] color_ptr = new IntPtr[3000];
int r = 0, g = 0, b = 0;
double angle = 0;
double h = 0, s = 0, v = 0;
double deltaX = 0, deltaY = 0;
int x = 0, y = 0;
for (y = 0; y < imgColor.rows; y++)
{
for (x = 0; x < imgColor.cols; x++)
{
PointF fxy = new PointF(y, x);
deltaX = fxy.X;
deltaY = fxy.Y;
angle = Math.Atan2(deltaX, deltaY);
if (angle < 0)
angle += 2 * Math.PI;
hsv_ptr[3 * x] = angle * 180 / Math.PI;
hsv_ptr[3 * x + 1] = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
hsv_ptr[3 * x + 2] = 0.9;
if (hsv_ptr[3 * x + 1] > max_s)
max_s = hsv_ptr[3 * x + 1];
}
}
for (y = 0; y < imgColor.rows; y++)
{
//hsv_ptr=imgHsv.ptr<float>(y);
//color_ptr=imgColor.ptr<unsigned char>(y);
for (x = 0; x < imgColor.cols; x++)
{
h = hsv_ptr[3 * x];
s = hsv_ptr[3 * x + 1] / max_s;
v = hsv_ptr[3 * x + 2];
//hsv2rgb(h,s,v,r,g,b);
Color c = ColorFromHSV(h, s, v);
color_ptr[3 * x] = (IntPtr)c.B;
color_ptr[3 * x + 1] = (IntPtr)c.G;
color_ptr[3 * x + 2] = (IntPtr)c.R;
}
}
drawLegendHSV(imgColor, 15, 25, 15);
}
I having trouble how to covert the two commented lines in the code. Can anyone Help me with this.?
Another thing that the Farneback algorithm gives two images velx and vely. It does not gives the flow( MCvMat). The colorFlow algorithms it takes the MCvMat type parameters.Did i done any wrong with the code. thanks
I'm trying to generate a set of points (represented by a Vector struct) that roughly models a spiral galaxy.
The C# code I've been playing with is below; but I can only seem to get it to generate a single 'arm' of the galaxy.
public Vector3[] GenerateArm(int numOfStars, int numOfArms, float rotation)
{
Vector3[] result = new Vector3[numOfStars];
Random r = new Random();
float fArmAngle = (float)((360 / numOfArms) % 360);
float fAngularSpread = 180 / (numOfArms * 2);
for (int i = 0; i < numOfStars; i++)
{
float fR = (float)r.NextDouble() * 64.0f;
float fQ = ((float)r.NextDouble() * fAngularSpread) * 1;
float fK = 1;
float fA = ((float)r.NextDouble() % numOfArms) * fArmAngle;
float fX = fR * (float)Math.Cos((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));
float fY = fR * (float)Math.Sin((MathHelper.DegreesToRadians(fA + fR * fK + fQ)));
float resultX = (float)(fX * Math.Cos(rotation) - fY * Math.Sin(rotation));
float resultY = (float)(fY * Math.Cos(rotation) - fX * Math.Sin(rotation));
result[i] = new Vector3(resultX, resultY, 1.0f);
}
return result;
}
Check this. It's a simulation of galaxy using density wave theory. Code is available.
http://beltoforion.de/galaxy/galaxy_en.html
I liked this idea so much i had to play around with it on my own and here is my result.
Note that i used PointF instead of Vector3, but you should be able to search and replace and add , 0) in a few places.
PointF[] points;
private void Render(Graphics g, int width, int height)
{
using (Brush brush = new SolidBrush(Color.FromArgb(20, 150, 200, 255)))
{
g.Clear(Color.Black);
foreach (PointF point in points)
{
Point screenPoint = new Point((int)(point.X * (float)width), (int)(point.Y * (float)height));
screenPoint.Offset(new Point(-2, -2));
g.FillRectangle(brush, new Rectangle(screenPoint, new Size(4, 4)));
}
g.Flush();
}
}
public PointF[] GenerateGalaxy(int numOfStars, int numOfArms, float spin, double armSpread, double starsAtCenterRatio)
{
List<PointF> result = new List<PointF>(numOfStars);
for (int i = 0; i < numOfArms; i++)
{
result.AddRange(GenerateArm(numOfStars / numOfArms, (float)i / (float)numOfArms, spin, armSpread, starsAtCenterRatio));
}
return result.ToArray();
}
public PointF[] GenerateArm(int numOfStars, float rotation, float spin, double armSpread, double starsAtCenterRatio)
{
PointF[] result = new PointF[numOfStars];
Random r = new Random();
for (int i = 0; i < numOfStars; i++)
{
double part = (double)i / (double)numOfStars;
part = Math.Pow(part, starsAtCenterRatio);
float distanceFromCenter = (float)part;
double position = (part * spin + rotation) * Math.PI * 2;
double xFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;
double yFluctuation = (Pow3Constrained(r.NextDouble()) - Pow3Constrained(r.NextDouble())) * armSpread;
float resultX = (float)Math.Cos(position) * distanceFromCenter / 2 + 0.5f + (float)xFluctuation;
float resultY = (float)Math.Sin(position) * distanceFromCenter / 2 + 0.5f + (float)yFluctuation;
result[i] = new PointF(resultX, resultY);
}
return result;
}
public static double Pow3Constrained(double x)
{
double value = Math.Pow(x - 0.5, 3) * 4 + 0.5d;
return Math.Max(Math.Min(1, value), 0);
}
Example:
points = GenerateGalaxy(80000, 2, 3f, 0.1d, 3);
Result:
I would abstract that function out into a createArm function.
Then you can store each arm as its own galaxy (temporarily).
So if you want 2 arms, do 2 galaxies of 5000. Then, rotate one of them 0 degrees around the origin (so doesn't move) and the other 180 degrees around the origin.
With this you can do an arbitrary number of arms by using different rotation amounts. You could even add some "naturalization" to it by making the rotation distance more random, like with a range instead of straight (360 / n). For example, 5 arms would be 0, 72, 144, 216, 288. But with some randomization you could make it 0, 70, 146, 225, 301.
Edit:
Some quick google-fu tells me (source)
q = initial angle, f = angle of rotation.
x = r cos q
y = r sin q
x' = r cos ( q + f ) = r cos q cos f - r sin q sin f
y' = r sin ( q + w ) = r sin q cos f + r cos q sin f
hence:
x' = x cos f - y sin f
y' = y cos f + x sin f