protected override void OnClosed(EventArgs e) { base.OnClosed(e); m_FFT.Dispose(); m_device.Dispose(); }
/// <summary> /// Very wasteful method that computes the spectrum of a source image /// </summary> /// <param name="_source"></param> /// <returns></returns> ImageFile ComputeSpectrum(ImageFile _source, float _scaleFactor) { uint size = _source.Width; uint offset = size >> 1; uint mask = size - 1; Complex[,] signal = new Complex[size, size]; _source.ReadPixels((uint _X, uint _Y, ref float4 _color) => { signal[_X, _Y].Set(_color.x, 0); }); SharpMath.FFT.FFT2D_GPU FFT = new SharpMath.FFT.FFT2D_GPU(m_device, size); Complex[,] spectrum = FFT.FFT_Forward(signal); FFT.Dispose(); ImageFile result = new ImageFile(size, size, _source.PixelFormat, _source.ColorProfile); result.WritePixels((uint _X, uint _Y, ref float4 _color) => { float V = _scaleFactor * (float)spectrum[(_X + offset) & mask, (_Y + offset) & mask].r; _color.Set(V, V, V, 1.0f); }); return(result); }
private void Convert(bool _centralValue, float _signX, float _signY) { // Initialize gradient filter Complex[,] dx = new Complex[m_size, m_size]; Complex[,] dy = new Complex[m_size, m_size]; Array.Clear(dx, 0, (int)(m_size * m_size)); Array.Clear(dy, 0, (int)(m_size * m_size)); if (_centralValue) { // Central-difference dx[m_size - 1, 0].Set(-_signX, 0); dx[1, 0].Set(_signX, 0); dy[0, m_size - 1].Set(_signY, 0); dy[0, 1].Set(-_signY, 0); } else { // One-sided difference dx[0, 0].Set(-_signX, 0); dx[1, 0].Set(_signX, 0); dy[0, 0].Set(_signY, 0); dy[0, 1].Set(-_signY, 0); } // Apply forward Fourier transform to obtain spectrum SharpMath.FFT.FFT2D_GPU FFT = new SharpMath.FFT.FFT2D_GPU(m_device, m_size); Complex[,] NX = FFT.FFT_Forward(nx); Complex[,] NY = FFT.FFT_Forward(ny); Complex[,] DX = FFT.FFT_Forward(dx); Complex[,] DY = FFT.FFT_Forward(dy); // Compute de-convolution float factor = m_imageNormal.Width * m_imageNormal.Height; Complex[,] H = new Complex[m_size, m_size]; Complex temp = new Complex(), sqrtTemp; for (uint Y = 0; Y < m_size; Y++) { for (uint X = 0; X < m_size; X++) { #if !F**K double sqNX = NX[X, Y].SquareMagnitude; double sqNY = NY[X, Y].SquareMagnitude; double num = sqNX + sqNY; double sqDX = DX[X, Y].SquareMagnitude; double sqDY = DY[X, Y].SquareMagnitude; double den = factor * (sqDX + sqDY); temp.Set(Math.Abs(den) > 0.0 ? num / den : 0.0, 0.0); sqrtTemp = temp.Sqrt(); H[X, Y] = sqrtTemp; #else Complex Nx = NX[X, Y]; Complex Ny = NY[X, Y]; Complex Dx = DX[X, Y]; Complex Dy = DY[X, Y]; double den = factor * (DX[X, Y].SquareMagnitude + DY[X, Y].SquareMagnitude); if (Math.Abs(den) > 0.0) { temp = -(Dx * Nx + Dy * Ny) / den; H[X, Y] = temp; } else { H[X, Y].Zero(); } #endif } } // Apply inverse transform Complex[,] h = FFT.FFT_Inverse(H); Complex heightMin = new Complex(double.MaxValue, double.MaxValue); Complex heightMax = new Complex(-double.MaxValue, -double.MaxValue); for (uint Y = 0; Y < m_size; Y++) { for (uint X = 0; X < m_size; X++) { Complex height = h[X, Y]; heightMin.Min(height); heightMax.Max(height); } } // Render result if (m_imageHeight != null) { m_imageHeight.Dispose(); m_imageHeight = null; } factor = 1.0f / (float)(heightMax.r - heightMin.r); // heightMin.r = -1.0f; // factor = 0.5f; m_imageHeight = new ImageFile(m_imageNormal.Width, m_imageNormal.Height, PIXEL_FORMAT.R16, new ColorProfile(ColorProfile.STANDARD_PROFILE.sRGB)); // m_imageHeight.WritePixels( ( uint X, uint Y, ref float4 _color ) => { _color.x = 1e3f * (float) H[X,Y].Magnitude; } ); // m_imageHeight.WritePixels( ( uint X, uint Y, ref float4 _color ) => { _color.x = 1e5f * (float) DX[X,Y].Magnitude; } ); m_imageHeight.WritePixels((uint X, uint Y, ref float4 _color) => { _color.x = factor * (float)(h[X, Y].r - heightMin.r); }); imagePanelHeight.Bitmap = m_imageHeight.AsBitmap; FFT.Dispose(); }