/// <summary> /// Computes gradient orientations from the gray image. /// </summary> /// <param name="frame">Image.</param> /// <param name="magnitudeSqrImage">Squared magnitude image.</param> /// <param name="minValidMagnitude">Minimal valid magnitude.</param> /// <returns>Orientation image (angles are in degrees).</returns> public static Image <Gray, int> Compute(Image <Gray, Byte> frame, out Image <Gray, int> magnitudeSqrImage, int minValidMagnitude) { int minValidMagSqr = minValidMagnitude * minValidMagnitude; Image <Gray, short> dx = frame.Sobel(1, 0, 3); Image <Gray, short> dy = frame.Sobel(0, 1, 3); short *dxPtr = (short *)dx.ImageData; short *dyPtr = (short *)dy.ImageData; int dxyImgAllignStride = dx.Stride / sizeof(short) - dx.Width; Image <Gray, int> orientImg = new Image <Gray, int>(frame.Size, 0); //TODO: low priority - rewrite to remove constrain stride = 0 int *orientImgPtr = (int *)orientImg.ImageData; magnitudeSqrImage = new Image <Gray, int>(dx.Width, dx.Height, 0); //TODO: low priority - rewrite to remove constrain stride = 0 int *magSqrImgPtr = (int *)magnitudeSqrImage.ImageData; int imgWidth = frame.Width; int imgHeight = frame.Height; for (int j = 0; j < imgHeight; j++) { for (int i = 0; i < imgWidth; i++) { int magSqr = dxPtr[0] * dxPtr[0] + dyPtr[0] * dyPtr[0]; if (magSqr < minValidMagSqr) { *orientImgPtr = FeatureMap.INVALID_ORIENTATION; } else { //*orientImgPtr = (int)(Math.Atan2(*dyPtr, *dxPtr) * 180 / Math.PI); *orientImgPtr = MathExtensions.Atan2Aprox(*dyPtr, *dxPtr); /*if (*orientImgPtr < 0) * orientImgPtr += 360;*/ //ne treba ? *magSqrImgPtr = magSqr; //*magSqrImgPtr = (int)Math.Sqrt(magSqr); if (*magSqrImgPtr > 255) *magSqrImgPtr = 255; } dxPtr += 1; dyPtr += 1; orientImgPtr += 1; magSqrImgPtr += 1; } dxPtr += dxyImgAllignStride; dyPtr += dxyImgAllignStride; } return(orientImg); }
private unsafe static void computeColor(KernelThread thread, byte *frame, int frameStride, Gray <int>[,] orientationImage, Gray <int>[,] magnitudeSqrImage, int minSqrMagnitude) { frame = frame + frameStride * thread.Y + thread.X; int maxMagSqr = 0, maxDx = 0, maxDy = 0; for (int ch = 0; ch < 3; ch++) { var srcPtr = frame + ch; int sumX = 0, sumY = 0; for (int r = 0; r < 3; r++) { var chPtr = srcPtr; for (int c = 0; c < 3; c++) { sumX += *chPtr * Sobel_3x3_X[r, c]; sumY += *chPtr * Sobel_3x3_Y[r, c]; chPtr += 3 * sizeof(byte); } srcPtr = (byte *)srcPtr + frameStride; } //sumX >>= 3; sumY >>= 3; //divide by 8 (normalize kernel) var grad = sumX * sumX + sumY * sumY; if (grad > maxMagSqr) { maxMagSqr = grad; maxDx = sumX; maxDy = sumY; } } if (maxMagSqr < minSqrMagnitude) { //magnitudeSqrImage[thread.Y + kernelRadius, thread.X + kernelRadius] = 0; //redundant orientationImage[thread.Y + kernelRadius, thread.X + kernelRadius] = FeatureMap.INVALID_ORIENTATION; } else { magnitudeSqrImage[thread.Y + kernelRadius, thread.X + kernelRadius] = maxMagSqr; orientationImage[thread.Y + kernelRadius, thread.X + kernelRadius] = MathExtensions.Atan2Aprox(maxDy, maxDx); } }
private unsafe static void computeGray(KernelThread thread, byte *frame, int frameStride, Gray <int>[,] orientationImage, Gray <int>[,] magnitudeSqrImage, int minSqrMagnitude) { frame = frame + frameStride * thread.Y + thread.X; var srcPtr = frame; int sumX = 0, sumY = 0; for (int r = 0; r < 3; r++) { for (int c = 0; c < 3; c++) { sumX += srcPtr[c] * Sobel_3x3_X[r, c]; sumY += srcPtr[c] * Sobel_3x3_Y[r, c]; } srcPtr = (byte *)srcPtr + frameStride; } //sumX >>= 3; sumY >>= 3; //divide by 8 (normalize kernel) //without this var grad = sumX * sumX + sumY * sumY; if (grad < minSqrMagnitude) { //magnitudeSqrImage[thread.Y + kernelRadius, thread.X + kernelRadius] = 0; //redundant orientationImage[thread.Y + kernelRadius, thread.X + kernelRadius] = FeatureMap.INVALID_ORIENTATION; } else { magnitudeSqrImage[thread.Y + kernelRadius, thread.X + kernelRadius] = grad; orientationImage[thread.Y + kernelRadius, thread.X + kernelRadius] = MathExtensions.Atan2Aprox(sumY, sumX); } }
/// <summary> /// Computes gradient orientations from the color image. Orientation from the channel which has the maximum gradient magnitude is taken as the orientation for a location. /// </summary> /// <typeparam name="TColor">Color type.</typeparam> /// <param name="frame">Image.</param> /// <param name="magnitudeSqrImage">Squared magnitude image.</param> /// <param name="minValidMagnitude">Minimal valid magnitude.</param> /// <returns>Orientation image (angles are in degrees).</returns> public static Image <Gray, int> Compute <TColor>(Image <TColor, Byte> frame, out Image <Gray, int> magnitudeSqrImage, int minValidMagnitude) where TColor : IColor3 { int minValidMagSqr = minValidMagnitude * minValidMagnitude; Image <TColor, short> dx = frame.Sobel(1, 0, 3); Image <TColor, short> dy = frame.Sobel(0, 1, 3); short *dxPtr = (short *)dx.ImageData; short *dyPtr = (short *)dy.ImageData; int dxyImgAllignStride = dx.Stride / sizeof(short) - dx.Width * dx.ColorInfo.NumberOfChannels; var orientImg = new Image <Gray, int>(dx.Width, dx.Height, 0); //TODO: low priority - rewrite to remove constrain stride = 0 int *orientImgPtr = (int *)orientImg.ImageData; magnitudeSqrImage = new Image <Gray, int>(dx.Width, dx.Height, 0); //TODO: low priority - rewrite to remove constrain stride = 0 int *magSqrImgPtr = (int *)magnitudeSqrImage.ImageData; int imgWidth = dx.Width; int imgHeight = dx.Height; for (int j = 0; j < imgHeight; j++) { for (int i = 0; i < imgWidth; i++) { int B_mag = dxPtr[0] * dxPtr[0] + dyPtr[0] * dyPtr[0]; int G_mag = dxPtr[1] * dxPtr[1] + dyPtr[1] * dyPtr[1]; int R_mag = dxPtr[2] * dxPtr[2] + dyPtr[2] * dyPtr[2]; int maxDx, maxDy; if (B_mag > G_mag && B_mag > R_mag) { maxDx = dxPtr[0]; maxDy = dyPtr[0]; } else if (G_mag > B_mag && G_mag > R_mag) { maxDx = dxPtr[1]; maxDy = dyPtr[1]; } else { maxDx = dxPtr[2]; maxDy = dyPtr[2]; } int magSqr = maxDx * maxDx + maxDy * maxDy; if (magSqr < minValidMagSqr) { *orientImgPtr = FeatureMap.INVALID_ORIENTATION; } else { //*orientImgPtr = (int)(Math.Atan2(maxDy, maxDx) * 180 / Math.PI); //if (*orientImgPtr < 0) // *orientImgPtr += 360; *orientImgPtr = MathExtensions.Atan2Aprox(*dyPtr, *dxPtr); //faster *magSqrImgPtr = magSqr; } dxPtr += 3; dyPtr += 3; orientImgPtr += 1; magSqrImgPtr += 1; } dxPtr += dxyImgAllignStride; dyPtr += dxyImgAllignStride; } //magImg = frame.Canny(70, GlobalParameters.MIN_GRADIENT_THRESHOLD, 3).SmoothGaussian(3).Convert<Gray, byte>().Convert<Gray, int>(); //magImg = frame.Convert<Gray, byte>().Canny(70, GlobalParameters.MIN_GRADIENT_THRESHOLD, 3).SmoothGaussian(3).Convert<Gray, int>(); return(orientImg); }