/// <summary> /// Computes a confusion matrix using the soft values from the distributions in <paramref name="inferredLabels"/> based upon the ground truth /// pixel labels in <paramref name="groundTruth"/>. /// </summary> /// <param name="groundTruth">The ground truth labels of the image</param> /// <param name="inferredLabels">The inferred labels of the image</param> /// <returns>A confusion matrix</returns> public static ConfusionMatrix ComputeConfusionMatrix(LabelImage groundTruth, DistributionImage inferredLabels) { ConfusionMatrix matrix = new ConfusionMatrix(inferredLabels.Channels); ComputeConfusionMatrix(matrix, groundTruth, inferredLabels); return(matrix); }
/// <summary> /// Multiplies each pixel's distribution in this image by each pixel's distribution in <paramref name="image"/>. /// </summary> /// <param name="image">Image to multiply by</param> public unsafe void Multiply(DistributionImage image) { int rows = Rows; int columns = Columns; int channels = Channels; if (rows != image.Rows || columns != image.Columns || channels != image.Channels) throw new ArgumentException("Argument must be of same dimensions as image"); fixed(float *dataSrc = RawArray, argSrc = image.RawArray) { float *dataPtr = dataSrc; float *argPtr = argSrc; for (int r = 0; r < rows; r++) { for (int c = 0; c < columns; c++) { for (int i = 0; i < channels; i++, dataPtr++, argPtr++) { *dataPtr = *dataPtr * *argPtr; } } } } }
/// <summary> /// Subsamples this image. /// </summary> /// <param name="subsample">Value to subsample by</param> /// <returns>The subsampled distribution image</returns> public unsafe DistributionImage Subsample(int subsample) { int rows = Rows; int columns = Columns; int channels = Channels; int stride = columns * channels; int nRows = rows / subsample; int nColumns = columns / subsample; float[, ,] dst = new float[nRows, nColumns, channels]; fixed(float *srcBuf = RawArray, dstBuf = dst) { float *srcPtr = srcBuf; float *dstPtr = dstBuf; for (int r = 0; r < nRows; r++) { float *srcScan = srcPtr; for (int c = 0; c < nColumns; c++) { float *srcScan2 = srcScan; for (int srcR = 0; srcR < subsample; srcR++) { float *srcScan3 = srcScan2; for (int srcC = 0; srcC < subsample; srcC++) { for (int i = 0; i < channels; i++) { dstPtr[i] += *srcScan3++; } } srcScan2 += stride; } dstPtr += channels; srcScan += subsample * channels; } srcPtr += subsample * stride; } } DistributionImage dist = new DistributionImage(); dist.ID = ID; dist.SetData(dst); dist.Normalize(); return(dist); }
/// <summary> /// Creates a new distribution image by appending the distributions at each pixel. /// </summary> /// <param name="lhs">The first image</param> /// <param name="rhs">The second image</param> /// <returns>The appended distribution image</returns> public static unsafe DistributionImage Append(DistributionImage lhs, DistributionImage rhs) { int rows = lhs.Rows; int columns = lhs.Columns; int channels0 = lhs.Channels; int channels1 = rhs.Channels; if (rhs.Rows != rows || rhs.Columns != columns) { throw new ArgumentException("Arguments must be same dimension"); } DistributionImage combo = new DistributionImage(rows, columns, channels0 + channels1); fixed(float *lhsSrc = lhs.RawArray, rhsSrc = rhs.RawArray, comboSrc = combo.RawArray) { float *lhsPtr = lhsSrc; float *rhsPtr = rhsSrc; float *comboPtr = comboSrc; for (int r = 0; r < rows; r++) { for (int c = 0; c < columns; c++) { for (int i = 0; i < channels0; i++) { *comboPtr++ = *lhsPtr++; } for (int i = 0; i < channels1; i++) { *comboPtr++ = *rhsPtr++; } } } } return(combo); }
/// <summary> /// Adds a distribution image to this image, using <paramref name="label"/> to index that image. /// </summary> /// <param name="dist">The distribution image to add</param> /// <param name="label">The label to extract from the image</param> public unsafe void Add(DistributionImage dist, short label) { int numLabels = dist.Channels; int rows = dist.Rows; int columns = dist.Columns; int nRows = Rows; int nColumns = Columns; float scaleR = (float)nRows / rows; float scaleC = (float)nColumns / columns; float[,] counts = new float[nRows, nColumns]; fixed(float *labelSrc = dist.RawArray) { float *labelPtr = labelSrc; for (int r = 0; r < rows; r++) { for (int c = 0; c < columns; c++) { float val = labelPtr[label]; float rr = r * scaleR; float cc = c * scaleC; int i0 = (int)rr; int j0 = (int)cc; float di = rr - i0 - .5f; float dj = cc - j0 - .5f; if (di < 0) { i0--; di += 1; } if (dj < 0) { j0--; dj += 1; } int i1 = i0 + 1; int j1 = j0 + 1; if (i0 < 0) { i0++; } if (i1 == nRows) { i1--; } if (j0 < 0) { j0++; } if (j1 == nColumns) { j1--; } float a = 1 - di; float b = 1 - dj; counts[i0, j0] += a * b * val; counts[i0, j1] += a * dj * val; counts[i1, j0] += di * b * val; counts[i1, j1] += di * dj * val; _sum += val; _rowSums[i0] += a * val; _rowSums[i1] += di * val; _columnSums[j0] += b * val; _columnSums[j1] += dj * val; labelPtr += numLabels; } } } fixed(float *dataSrc = RawArray, countsSrc = counts) { float *dataPtr = dataSrc; float *countsPtr = countsSrc; int total = Rows * Columns; while (total-- > 0) { *dataPtr = *dataPtr + *countsPtr; dataPtr++; countsPtr++; } } }
/// <summary> /// Computes a confusion matrix using the soft values from the distributions in <paramref name="inferredLabels"/> based upon the ground truth /// pixel labels in <paramref name="groundTruth"/>, and adds them to <paramref name="matrix"/>. /// </summary> /// <param name="matrix">Matrix to add the confusion values of this image to</param> /// <param name="groundTruth">The ground truth labels of the image</param> /// <param name="inferredLabels">The inferred labels of the image</param> public static unsafe void ComputeConfusionMatrix(ConfusionMatrix matrix, LabelImage groundTruth, DistributionImage inferredLabels) { int rows = groundTruth.Rows; int columns = groundTruth.Columns; int channels = inferredLabels.Channels; fixed(short *labelsSrc = groundTruth.RawArray) { fixed(float *distSrc = inferredLabels.RawArray) { short *labelsPtr = labelsSrc; float *distPtr = distSrc; for (int r = 0; r < rows; r++) { for (int c = 0; c < columns; c++, labelsPtr++) { short trueLabel = *labelsPtr; for (short i = 0; i < channels; i++, distPtr++) { matrix.Add(trueLabel, i, *distPtr); } } } } } }