public unsafe UnmanagedImage ShowDerivative(UnmanagedImage imageA, UnmanagedImage imageB, DerivativeComponent component) { UnmanagedImage result = UnmanagedImage.Create(imageA.Width, imageA.Height, System.Drawing.Imaging.PixelFormat.Format8bppIndexed); byte * ptrBase = (byte *)result.ImageData.ToPointer(); byte * ptr = ptrBase; for (int i = 0; i < imageA.Height - 1; i++) { for (int j = 0; j < imageA.Width - 1; j++) { Derivative3 dI = CalculateDerivative(imageA, imageB, j, i); ptr = ptrBase + (i * result.Stride + j); float value = 0f; switch (component) { case DerivativeComponent.X: value = dI.X; break; case DerivativeComponent.Y: value = dI.Y; break; case DerivativeComponent.t: value = dI.t; break; default: break; } *ptr = (byte)Math.Min(255, Math.Max(0, value)); } } return(result); }
/// <summary> /// Calculates full velocity feild uses integral repsenetations to speed up /// </summary> public unsafe Point[,] CalculateVelocityField(UnmanagedImage imageA, UnmanagedImage imageB) { int width = imageA.Width; int height = imageA.Height; float[,] IxIx = new float[height, width]; float[,] IxIy = new float[height, width]; float[,] IyIy = new float[height, width]; float[,] ItIx = new float[height, width]; float[,] ItIy = new float[height, width]; // calculate integral representation //Parallel.For(0, height, (i) => for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { Derivative3 curdI = CalculateDerivative(imageA, imageB, j, i); IxIx[i, j] = CalcualateIntegralElement(IxIx, i, j, curdI.X * curdI.X); IxIy[i, j] = CalcualateIntegralElement(IxIy, i, j, curdI.X * curdI.Y); IyIy[i, j] = CalcualateIntegralElement(IyIy, i, j, curdI.Y * curdI.Y); ItIx[i, j] = CalcualateIntegralElement(ItIx, i, j, curdI.t * curdI.X); ItIy[i, j] = CalcualateIntegralElement(ItIy, i, j, curdI.t * curdI.Y); } } Point[,] velocities = new Point[height, width]; int winW = 2 * _winXRadius + 1; int winH = 2 * _winYRadius + 1; Parallel.For(0, width - winW + 1, (winX) => //for (int winX = 0; winX <= width - winW; winX++) { for (int winY = 0; winY <= height - winH; winY++) { // calculate G and b into window float IxIxWinValue = GetRegionSumFromIntegralRepresentation(IxIx, winX, winY, winW, winH); float IxIyWinValue = GetRegionSumFromIntegralRepresentation(IxIy, winX, winY, winW, winH); float IyIyWinValue = GetRegionSumFromIntegralRepresentation(IyIy, winX, winY, winW, winH); float ItIxWinValue = GetRegionSumFromIntegralRepresentation(ItIx, winX, winY, winW, winH); float ItIyWinValue = GetRegionSumFromIntegralRepresentation(ItIy, winX, winY, winW, winH); float[,] G = new float[2, 2] { { IxIxWinValue, IxIyWinValue }, { IxIyWinValue, IyIyWinValue } }; float[] b = new float[2] { ItIxWinValue, ItIyWinValue }; velocities[winY + _winYRadius, winX + _winXRadius] = Solve2x2LinearMatrixEquation(G, b); } }); return(velocities); }
//public Point IterativeCalculateVelocity(UnmanagedImage imageA, UnmanagedImage imageB, IntPoint point, bool weightedWindow, int maxIterations) //{ // float[,] G = new float[2, 2]; // float[] b; // #region Calculating G // for (int i = point.Y - WindowHalfHeight; i < point.Y + WindowHalfHeight; i++) // { // for (int j = point.X - WindowHalfWidth; j < point.X + WindowHalfWidth; j++) // { // Derivative3 dIij = CalculateDerivative(imageA, imageB, j, i); // if (!weightedWindow) // { // G[0, 0] += dIij.X * dIij.X; // G[1, 1] += dIij.Y * dIij.Y; // G[0, 1] += dIij.X * dIij.Y; // G[1, 0] = G[0, 1]; // } // else // weightedWindow // { // int dx = j - point.X; // int dy = i - point.Y; // float w = alpha * (float)Math.Exp(beta * (dx * dx + dy * dy) / (float)(WindowHalfWidth * WindowHalfWidth + WindowHalfHeight * WindowHalfHeight)); // G[0, 0] += w * dIij.X * dIij.X; // G[1, 1] += w * dIij.Y * dIij.Y; // G[0, 1] += w * dIij.X * dIij.Y; // G[1, 0] = G[0, 1]; // } // } // } // #endregion // Point shift = new Point(); // for (int iter = 0; iter < maxIterations; iter++) // { // #region Iteration: Calculating vector b // b = new float[2]; // for (int i = point.Y - WindowHalfHeight; i < point.Y + WindowHalfHeight; i++) // { // for (int j = point.X - WindowHalfWidth; j < point.X + WindowHalfWidth; j++) // { // Derivative3 dIij = CalculateDerivative(imageA, imageB, j, i, (int)Math.Round(shift.X), (int)Math.Round(shift.Y)); // if (!weightedWindow) // { // b[0] += dIij.X * dIij.t; // b[1] += dIij.Y * dIij.t; // } // else // weightedWindow // { // int dx = j - point.X; // int dy = i - point.Y; // float w = alpha * (float)Math.Exp(beta * (dx * dx + dy * dy) / (float)(WindowHalfWidth * WindowHalfWidth + WindowHalfHeight * WindowHalfHeight)); // b[0] += w * dIij.X * dIij.t; // b[1] += w * dIij.Y * dIij.t; // } // } // } // #endregion // Point dP = SolveMatrixEquation(G, b); // if (dP.EuclideanNorm() < 1f) // return shift + dP; // shift += dP; // } // return shift; //} public Point CalculateVelocity(UnmanagedImage imageA, UnmanagedImage imageB, IntPoint point, bool weightedWindow) { float[,] G = new float[2, 2]; float[] b = new float[2]; int px = point.X; int py = point.Y; for (int i = py - _winYRadius; i < py + _winYRadius; i++) { for (int j = px - _winXRadius; j < px + _winXRadius; j++) { Derivative3 d = CalculateDerivative(imageA, imageB, j, i); if (!weightedWindow) { G[0, 0] += d.X * d.X; G[1, 1] += d.Y * d.Y; G[0, 1] += d.X * d.Y; G[1, 0] = G[0, 1]; b[0] += d.X * d.t; b[1] += d.Y * d.t; } else // weightedWindow { int dxAbs = j - px; dxAbs = dxAbs < 0 ? -dxAbs : dxAbs; int dyAbs = i - py; dyAbs = dyAbs < 0 ? -dyAbs : dyAbs; float w = _weight[dxAbs, dyAbs]; G[0, 0] += w * d.X * d.X; G[1, 1] += w * d.Y * d.Y; G[0, 1] += w * d.X * d.Y; G[1, 0] = G[0, 1]; b[0] += w * d.X * d.t; b[1] += w * d.Y * d.t; } } } return(Solve2x2LinearMatrixEquation(G, b)); }