/// <summary> /// Extracts a segment from a provided image. /// </summary> /// <typeparam name="T">Type of <paramref name="image"/></typeparam> /// <param name="label">Label of the segment to extract</param> /// <param name="image">Image to extract the segment from</param> /// <returns>All the points in an image segment</returns> public unsafe List <ImageDataPoint <T> > ExtractSegment <T>(short label, IMultichannelImage <T> image) { if (image.Rows != Rows || image.Columns != Columns) { throw new Exception("Provided image is of difference dimensions than this label image"); } List <ImageDataPoint <T> > points = new List <ImageDataPoint <T> >(); int rows = Rows; int columns = Columns; fixed(short *src = RawArray) { short *srcPtr = src; for (short r = 0; r < rows; r++) { for (short c = 0; c < columns; c++, srcPtr++) { if (*srcPtr == label) { points.Add(new ImageDataPoint <T>(image, r, c, label)); } } } } return(points); }
public float Compute(ImageDataPoint <float> point) { if (point.ImageID != _currentID) { _currentID = point.ImageID; if (point.Image.IsIntegral || DecisionTree <ImageDataPoint <float>, float[]> .IsBuilding) { _integralImage = new FloatArrayHandler(point.Image.RawArray, true); } else { _integralImage = IntegralImage.ComputeFloat <FloatArrayHandler>(point.Image); } } int row = point.Row; int column = point.Column; IMultichannelImage <float> image = point.Image; float sum = 0; for (int i = 0; i < _count; i++) { if (i % 2 == 0) { sum += _integralImage.ComputeRectangleSum(row, column, _channels[i], _rectangles[i]); } else { sum -= _integralImage.ComputeRectangleSum(row, column, _channels[i], _rectangles[i]); } } Debug.Assert(!float.IsNaN(sum), "Rectangle sum is NaN!"); return(sum); }
/// <summary> /// Create a new Filter Bank Image. The input image is run through the provided filter banks and their responses are concatenated together to form the channels of the image. /// </summary> /// <param name="input">The input image</param> /// <param name="filterBanks">The filter banks to apply</param> /// <returns>The image</returns> public static unsafe FilterBankImage Create(IMultichannelImage <float> input, params FilterBank[] filterBanks) { FilterBankImage image = new FilterBankImage(); image.SetDimensions(input.Rows, input.Columns, filterBanks.Sum(o => o.DescriptorLength)); fixed(float *dataSrc = image.RawArray) { float *dataPtr = dataSrc; for (short r = 0; r < input.Rows; r++) { for (short c = 0; c < input.Columns; c++) { ImageDataPoint <float> point = new ImageDataPoint <float>(input, r, c, 0); foreach (var fb in filterBanks) { float[] values = fb.Compute(point); for (int i = 0; i < values.Length; i++, dataPtr++) { *dataPtr = values[i]; } } } } } return(image); }
/// <summary> /// Extracts a random number of points, such that the probability of a point being extracted is equal /// to <paramref name="percentage"/> /// </summary> /// <typeparam name="T">Underlying type of the image</typeparam> /// <param name="image">The image</param> /// <param name="percentage">The probability that a point will be extracted</param> /// <param name="border">Border around the edge of the image to exclude</param> /// <returns>A list of image points</returns> public static IEnumerable <ImageDataPoint <T> > ExtractPoints <T>(this IMultichannelImage <T> image, double percentage, short border = 0) { int rows = image.Rows; int columns = image.Columns; int total = (int)((rows - 2 * border) * (columns - 2 * border) * percentage); if (percentage <= .1) { for (int i = 0; i < total; i++) { short row = (short)ThreadsafeRandom.Next(border, rows - border); short column = (short)ThreadsafeRandom.Next(border, rows - border); yield return(new ImageDataPoint <T>(image, row, column, 0)); } } else { for (short r = border; r < rows - border; r++) { for (short c = border; c < columns - border; c++) { if (ThreadsafeRandom.NextDouble() < percentage) { yield return(new ImageDataPoint <T>(image, r, c, 0)); } } } } }
private unsafe float compute(int row, int column, IMultichannelImage <float> image) { int startR = row - _rows / 2; int startC = column - _columns / 2; int stride = image.Columns * image.Channels; int rows = image.Rows; int columns = image.Columns; int channels = image.Channels; float sum = 0; fixed(float *patch = image.RawArray, filter = _filterValues) { float *filterPtr = filter; float *patchPtr; if (startR < 0) { if (startC < 0) { patchPtr = patch + _channel; } else { patchPtr = patch + startC * channels + _channel; } } else if (startC < 0) { patchPtr = patch + startR * stride + _channel; } else { patchPtr = patch + startR * stride + startC * channels + _channel; } for (int r = 0; r < _rows; r++) { int rr = startR + r; float *patchScan = patchPtr; if (rr >= 0 && rr < rows - 1) { patchPtr += stride; } for (int c = 0; c < _columns; c++, filterPtr++) { float val = *patchScan; int cc = startC + c; if (cc >= 0 && cc < columns - 1) { patchScan += channels; } sum += *filterPtr * val; } } } return(sum); }
/// <summary> /// Constructor. /// </summary> /// <param name="image">Source image</param> /// <param name="row">Image row</param> /// <param name="column">Image column</param> /// <param name="label">Ground truth label</param> /// <param name="weight">Weight</param> public ImageDataPoint(IMultichannelImage <T> image, short row, short column, int label, float weight = 1f) { _image = image; _row = row; _column = column; _label = label; _weight = weight; }
protected float GetValue2(int row, int column, ImageDataPoint <float> point) { row += _row2; column += _column2; IMultichannelImage <float> image = point.Image; fixValue(ref row, 0, image.Rows); fixValue(ref column, 0, image.Columns); return(image.RawArray[row, column, _channel2]); }
/// <summary> /// Creates several splits of the dataset. /// </summary> /// <param name="sampleFrequency">How often to sample pixels within the training images.</param> /// <param name="boxRows">Vertical trim around the edges of images to avoid feature tests beyond the boundary of the image</param> /// <param name="boxColumns">Vertical trim around the edges of images to avoid feature tests beyond the boundary of the image</param> /// <param name="numSplits">Number of splits to create</param> /// <returns>Splits of the data</returns> public List <ImageDataPoint <T> >[] CreateDataPoints(int sampleFrequency, int boxRows, int boxColumns, int numSplits) { List <ImageDataPoint <T> > points = new List <ImageDataPoint <T> >(); foreach (LabeledImage <T> labelledImage in _images) { IMultichannelImage <T> image = labelledImage.Image; LabelImage labels = labelledImage.Labels; LabelSet set = labels.Labels; string id = labelledImage.ID; bool[,] valid = labelledImage.Valid; int maxRows = image.Rows - boxRows; int maxColumns = image.Columns - boxColumns; for (int r = boxRows; r < maxRows; r += sampleFrequency) { for (int c = boxColumns; c < maxColumns; c += sampleFrequency) { short label = getLabel(labels[r, c], set); bool sample = valid[r, c]; if (sample && label == LabelImage.BackgroundLabel) { switch (_backgroundSampleMode) { case BackgroundSampleMode.Ignore: sample = false; break; case BackgroundSampleMode.Half: sample = ThreadsafeRandom.Test(.5); break; } } if (sample) { points.Add(new ImageDataPoint <T>(image, (short)r, (short)c, label)); } } } } List <ImageDataPoint <T> >[] splits = new List <ImageDataPoint <T> > [numSplits]; for (int i = 0; i < numSplits; i++) { if (_byImage) { splits[i] = sampleByImage(points); } else { splits[i] = sample(points); } } return(splits); }
/// <summary> /// Thresholds the provided image. The <paramref name="lessThan"/> parameter will determine whether the pixels that are less than the /// threshold are set to true and the others "false" or vice versa. The thresholding will be performed on the provided channel. /// channel. /// </summary> /// <typeparam name="T">The underlying type of the input image. Must be of interface IComparable.</typeparam> /// <param name="image">The input image</param> /// <param name="threshold">The threshold to use</param> /// <param name="lessThan">Whether pixels less than the threshold are set to "true" and all others to "false", or vice versa</param> /// <param name="channel">The channel on which to perform thresholding</param> /// <returns>The thresholded image</returns> public static BinaryImage Threshold <T>(this IMultichannelImage <T> image, T threshold, bool lessThan, int channel) where T : IComparable <T> { T[, ,] data = image.RawArray; int rows = image.Rows; int columns = image.Columns; BinaryImage resultImage = new BinaryImage(rows, columns); bool[, ,] result = resultImage.RawArray; for (int r = 0; r < rows; r++) { for (int c = 0; c < columns; c++) { result[r, c, 0] = data[r, c, channel].CompareTo(threshold) <= 0 ? lessThan : !lessThan; } } return(resultImage); }
public float Compute(ImageDataPoint <float> point) { int row = point.Row + _row; int column = point.Column + _column; IMultichannelImage <float> image = point.Image; fixValue(ref row, 0, image.Rows); fixValue(ref column, 0, image.Columns); float val = image.RawArray[row, column, _channel]; if (_useLog) { val = Math.Abs(val); val = Math.Max(val, Decider <ImageDataPoint <float>, float[]> .DIRICHLET_PRIOR); val = (float)Math.Log(val); } if (_useAbsoluteValue) { val = Math.Abs(val); } return(val); }
/// <summary> /// Classifies each pixel in the image and returns the leaf nodes which they end up in. /// </summary> /// <param name="forest">The forest used for the computation</param> /// <param name="image">Image to classify</param> /// <returns>A leaf image</returns> public static LeafImage <T> ComputeLeafImage <T>(this DecisionForest <ImageDataPoint <T>, T[]> forest, IMultichannelImage <T> image) { LeafImage <T> leafImage = new LeafImage <T>(image.Rows, image.Columns, forest.TreeCount); leafImage.ID = image.ID; for (int i = 0; i < forest.TreeCount; i++) { forest[i].FillLeafImage(leafImage, image); } return(leafImage); }
/// <summary> /// Constructor. /// </summary> /// <param name="image">The source image</param> /// <param name="labels">The ground truth labels</param> public LabeledImage(IMultichannelImage <T> image, LabelImage labels) { Image = image; Labels = labels; initValid(); }
/// <summary> /// Classifies each pixel of <paramref name="image"/> and produces a corresponding <see cref="T:LabelImage" />. The maximum likelihood label /// is chosen at each pixel. /// </summary> /// <param name="tree">The tree used for the computation</param> /// <param name="image">Image to classify</param> /// <returns>A label image with all of the classifications</returns> public static LabelImage Classify <T>(this DecisionTree <ImageDataPoint <T>, T[]> tree, IMultichannelImage <T> image) { return(tree.ClassifySoft(image).ToLabelImage()); }
internal static void FillLeafImage <T>(this DecisionTree <ImageDataPoint <T>, T[]> tree, LeafImage <T> leafImage, IMultichannelImage <T> image) { INodeInfo <ImageDataPoint <T>, T[]>[, ,] array = leafImage.RawArray; int rows = image.Rows; int columns = image.Columns; List <ImageDataPoint <T> > points = new List <ImageDataPoint <T> >(); List <int> indices = new List <int>(); int i = 0; for (short r = 0; r < rows; r++) { for (short c = 0; c < columns; c++, i++) { points.Add(new ImageDataPoint <T>(image, r, c, -1)); indices.Add(i); } } INodeInfo <ImageDataPoint <T>, T[]>[] info = new INodeInfo <ImageDataPoint <T>, T[]> [points.Count]; DecisionTree <ImageDataPoint <T>, T[]> .assignLabels(tree._root, points, info, indices); i = 0; int treeLabel = tree.TreeLabel; for (short r = 0; r < rows; r++) { for (short c = 0; c < columns; c++, i++) { array[r, c, treeLabel] = info[i]; } } }
/// <summary> /// Computes a tree histogram from <paramref name="image"/>. /// </summary> /// <param name="tree">The tree used for the computation</param> /// <param name="image">The image used to compute the tree histogram</param> /// <returns>A tree histogram</returns> public static TreeHistogram ComputeHistogram <T>(this DecisionTree <ImageDataPoint <T>, T[]> tree, IMultichannelImage <T> image) { List <ImageDataPoint <T> > points = new List <ImageDataPoint <T> >(); for (short r = 0; r < image.Rows; r++) { for (short c = 0; c < image.Columns; c++) { points.Add(new ImageDataPoint <T>(image, r, c, -1)); } } return(tree.ComputeHistogram(points)); }
/// <summary> /// Classifies <paramref name="image"/>, creating a distribution over all labels at each pixel. /// </summary> /// <param name="tree">The tree used for the computation</param> /// <param name="image">Image to classify</param> /// <returns>Distributions at each pixel</returns> public static DistributionImage ClassifySoft <T>(this DecisionTree <ImageDataPoint <T>, T[]> tree, IMultichannelImage <T> image) { DistributionImage dist = new DistributionImage(image.Rows, image.Columns, tree.LabelCount); tree.ClassifySoft(image, dist); dist.Normalize(); return(dist); }
/// <summary> /// Classifies every pixel in the provided image, returning a full distribution over all labels. /// </summary> /// <param name="forest">The forest used for the computation</param> /// <param name="image">Image to classify</param> /// <returns>The classified image</returns> public static DistributionImage ClassifySoft <T>(this DecisionForest <ImageDataPoint <T>, T[]> forest, IMultichannelImage <T> image) { DistributionImage dist = new DistributionImage(image.Rows, image.Columns, forest.LabelCount); dist.ID = image.ID; for (int t = 0; t < forest.TreeCount; t++) { forest[t].ClassifySoft(image, dist); } dist.DivideThrough(forest.TreeCount); dist.Normalize(); return(dist); }
/// <summary> /// Classifies every pixel in the provided image with the maximum likelihood label. /// </summary> /// <param name="forest">The forest used for the computation</param> /// <param name="image">Image to classify</param> /// <returns>The classified image</returns> public static LabelImage Classify <T>(this DecisionForest <ImageDataPoint <T>, T[]> forest, IMultichannelImage <T> image) { return(forest.ClassifySoft(image).ToLabelImage()); }
/// <summary> /// Computes a histogram for all trees from the provided image. /// </summary> /// <param name="forest">The forest used for the computation</param> /// <param name="image">Image to classify</param> /// <returns>The histogram</returns> public static TreeHistogram ComputeHistogram <T>(this DecisionForest <ImageDataPoint <T>, T[]> forest, IMultichannelImage <T> image) { int rows = image.Rows; int columns = image.Columns; List <ImageDataPoint <T> > points = new List <ImageDataPoint <T> >(); for (short r = 0; r < rows; r++) { for (short c = 0; c < columns; c++) { points.Add(new ImageDataPoint <T>(image, r, c, -1)); } } return(forest.ComputeHistogram(points)); }
/// <summary> /// Classifies each pixel in <paramref name="image"/> and stores the results in <paramref name="dist"/>. /// </summary> /// <param name="tree">The tree used for the computation</param> /// <param name="image">Image to classify</param> /// <param name="dist">Image which is used to store the distributions</param> public static void ClassifySoft <T>(this DecisionTree <ImageDataPoint <T>, T[]> tree, IMultichannelImage <T> image, DistributionImage dist) { int rows = image.Rows; int columns = image.Columns; List <ImageDataPoint <T> > points = new List <ImageDataPoint <T> >(); List <int> indices = new List <int>(); int i = 0; for (short r = 0; r < rows; r++) { for (short c = 0; c < columns; c++, i++) { points.Add(new ImageDataPoint <T>(image, r, c, -1)); indices.Add(i); } } INodeInfo <ImageDataPoint <T>, T[]>[] info = new INodeInfo <ImageDataPoint <T>, T[]> [points.Count]; DecisionTree <ImageDataPoint <T>, T[]> .assignLabels(tree._root, points, info, indices); i = 0; for (short r = 0; r < rows; r++) { for (short c = 0; c < columns; c++, i++) { dist.Add(r, c, info[i].Distribution); } } }