private void initalizeHistograms() { int[] binSizes = new int[] { 32, 32 }; //X bins per channel IntRange[] ranges = new IntRange[] { new IntRange(0, 180), //Hue (for 8bpp image hue>> range is (0-180) otherwise (0-360) new IntRange(0, 255) }; originalObjHist = new DenseHistogram(binSizes, ranges); backgroundHist = originalObjHist.CopyBlank(); }
private static unsafe void calculateHistByte(DenseHistogram hist, IImage[] channels, Image<Gray<byte>> mask) { /******************************* prepare data *****************************/ float* bins = (float*)hist.HistogramData; float[][] valueToIndexMultipliers = hist.ValueToIndexMultipliers; int[] strides = hist.Strides; int width = channels[0].Width; int height = channels[0].Height; int channelStride = channels[0].Stride; int numDimensions = channels.Length; byte*[] channelPtrs = new byte*[channels.Length]; for (int i = 0; i < channelPtrs.Length; i++) { channelPtrs[i] = (byte*)channels[i].ImageData; } byte* maskPtr = (byte*)mask.ImageData; int maskStride = mask.Stride; /******************************* prepare data *****************************/ for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { if (maskPtr[col] == 0) continue; float* binsTemp = bins; for (int d = 0; d < numDimensions; d++) { var idxDecimal = channelPtrs[d][col] * valueToIndexMultipliers[d][0] + valueToIndexMultipliers[d][1]; int idx = (int)(idxDecimal); binsTemp += idx * strides[d]; //index checking Debug.Assert(idx >= 0 && idx < hist.binSizes[d], string.Format("Calculated index does not match specified bin size. Dimension = {0}", d)); } binsTemp[0]++; } for (int d = 0; d < numDimensions; d++) channelPtrs[d] += channelStride; maskPtr += maskStride; } }
private static void backProjectByte(DenseHistogram hist, IImage[] channels, IImage projImg) { /******************************* prepare data *****************************/ float* bins = (float*)hist.HistogramData; float[][] valueToIndexMultipliers = hist.ValueToIndexMultipliers; int[] strides = hist.Strides; int width = channels[0].Width; int height = channels[0].Height; int channelStride = channels[0].Stride; int numDimensions = channels.Length; byte*[] channelPtrs = new byte*[channels.Length]; for (int i = 0; i < channelPtrs.Length; i++) { channelPtrs[i] = (byte*)channels[i].ImageData; } byte* projImgPtr = (byte*)projImg.ImageData; int projImgStride = projImg.Stride; /******************************* prepare data *****************************/ for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { float* binsTemp = bins; for (int d = 0; d < numDimensions; d++) { var idxDecimal = channelPtrs[d][col] * valueToIndexMultipliers[d][0] + valueToIndexMultipliers[d][1]; int idx = (int)(idxDecimal); binsTemp += idx * strides[d]; } projImgPtr[col] = (byte)binsTemp[0]; } for (int d = 0; d < numDimensions; d++) channelPtrs[d] += channelStride; projImgPtr += projImgStride; } }
private void initTracking(Image<Bgr, byte> frame) { //get hue channel from search area var hsvImg = frame.Convert<Hsv, byte>(); //<<parallel operation>> //user constraints... Image<Gray, byte> mask = hsvImg.InRange(new Hsv(0, 0, minV), new Hsv(0, 0, maxV), Byte.MaxValue, 2); originalObjHist.Calculate(hsvImg.GetSubRect(roi).SplitChannels(0, 1), !false, mask.GetSubRect(roi)); originalObjHist.Scale((float)1 / roi.Area()); //originalObjHist.Normalize(Byte.MaxValue); var backgroundArea = roi.Inflate(1.5, 1.5, frame.Size); backgroundHist.Calculate(hsvImg.GetSubRect(backgroundArea).SplitChannels(0, 1), !false, mask.GetSubRect(backgroundArea)); backgroundHist.Scale((float)1 / backgroundArea.Area()); //backgroundHist.Normalize(Byte.MaxValue); //how good originalObjHist and objHist match (suppresses possible selected background) ratioHist = originalObjHist.CreateRatioHistogram(backgroundHist, Byte.MaxValue, 10); searchArea = roi; roi = Rectangle.Empty; }
private void initTracking(Bgr<byte>[,] frame) { //get hue channel from search area var hsvImg = frame.ToHsv(); //user constraints... Gray<byte>[,] mask = hsvImg.InRange(new Hsv<byte>(0, 0, (byte)minV), new Hsv<byte>(0, 0, (byte)maxV), Byte.MaxValue, 2); originalObjHist.Calculate(hsvImg.SplitChannels<Hsv<byte>, byte>(roi, 0, 1), !false, mask, roi.Location); originalObjHist.Scale((float)1 / roi.Area()); //originalObjHist.Normalize(Byte.MaxValue); var backgroundArea = roi.Inflate(1.5, 1.5, frame.Size()); backgroundHist.Calculate(hsvImg.SplitChannels<Hsv<byte>, byte>(backgroundArea, 0, 1), !false, mask, backgroundArea.Location); backgroundHist.Scale((float)1 / backgroundArea.Area()); //backgroundHist.Normalize(Byte.MaxValue); //how good originalObjHist and objHist match (suppresses possible selected background) ratioHist = originalObjHist.CreateRatioHistogram(backgroundHist, Byte.MaxValue, 10); searchArea = roi; roi = Rectangle.Empty; }
private static void initalize(DenseHistogram hist, int[] binSizes, IntRange[] ranges) { hist.binSizes = binSizes; hist.ranges = ranges; var valueToIndexMultipliers = new float[binSizes.Length][]; /***********************************************************************************/ // binSizes[i] //idx = (val - range[i].Min) * ----------------------------------- // range[i].Max - range[i].Min + 1 for (int bin = 0; bin < binSizes.Length; bin++) { valueToIndexMultipliers[bin] = new float[2]; valueToIndexMultipliers[bin][0] = (float)binSizes[bin] / (ranges[bin].Max - ranges[bin].Min + 1); valueToIndexMultipliers[bin][1] = -ranges[bin].Min * valueToIndexMultipliers[bin][0]; } hist.valueToIndexMultipliers = valueToIndexMultipliers; /***********************************************************************************/ /***********************************************************************************/ var strides = new int[binSizes.Length]; strides[binSizes.Length - 1] = 1; for (int bin = (binSizes.Length - 1) - 1; bin >= 0; bin--) { strides[bin] = strides[bin + 1] * (binSizes[bin + 1]); } hist.strides = strides; /***********************************************************************************/ hist.NumberOfElements = binSizes.Aggregate((a, b) => a * b); hist.histogram = new float[hist.NumberOfElements]; hist.histogramHandle = GCHandle.Alloc(hist.histogram, GCHandleType.Pinned); hist.histPtr = (float*)hist.histogramHandle.AddrOfPinnedObject(); }
/// <summary> /// Creates ratio histogram [0.. <paramref name="histogramsNormalizationFactor"/>]. /// </summary> /// <param name="hist2">Second histogram. This histogram will be element-wise dived with it. Both histograms must be normalized to the same value!</param> /// <param name="histogramsNormalizationFactor">Histogram normalization factor. The maximum value in the ratio histogram will be the provided value.</param> /// <param name="hist2Gain">Second histogram gain.</param> /// <returns>Normalized ratio histogram</returns> public unsafe DenseHistogram CreateRatioHistogram(DenseHistogram hist2, float histogramsNormalizationFactor = 1, float hist2Gain = 1) { //histograms must be normalized! DenseHistogram ratioHist = this.CopyBlank(); float* hist1Ptr = (float*)this.HistogramData; float* hist2Ptr = (float*)hist2.HistogramData; float* ratioHistPtr = (float*)ratioHist.HistogramData; int numOfElems = this.NumberOfElements; for (int i = 0; i < numOfElems; i++) { if (hist2Ptr[i] != 0) ratioHistPtr[i] = (hist1Ptr[i] / (hist2Gain * hist2Ptr[i])) * histogramsNormalizationFactor; else ratioHistPtr[i] = 0; //in original Accord's implementation. Why ? //ratioHistPtr[i] = hist1Ptr[i]; ratioHistPtr[i] = System.Math.Min(histogramsNormalizationFactor, ratioHistPtr[i]); } return ratioHist; }
/// <summary> /// Gets the same histogram representation but without data. (data is default = zero) /// </summary> /// <returns></returns> public DenseHistogram CopyBlank() { DenseHistogram hist = new DenseHistogram(); initalize(hist, (int[])this.binSizes.Clone(), (IntRange[])this.ranges.Clone()); return hist; }