/// <summary> /// Transforms each voxel position from the source image to a new position. /// </summary> /// <param name="sourceMatrix">The image which will provide the voxel values.</param> /// <param name="transformationMatrix">This matrix will be applied to the original positions to get a new position.</param> /// <returns></returns> public static Image3DMatrix Transform(Image3DMatrix sourceMatrix, TransformationMatrix transformationMatrix) { sourceMatrix.CancelParallelTransformation(); ParallelOptions options = CreateParallelOptions(sourceMatrix); //Before returning a new matrix, the transformed points are collected. In the last step, these points will //be analyzed to receive the new height, width and depth of the matrix after the transformation. ConcurrentDictionary <(int X, int Y, int Z), ushort> transformedPoints = new ConcurrentDictionary <(int X, int Y, int Z), ushort>(); try { //Due to using target to source exactly one value will be asigned for each position, so it is save //to run the process with parallel for loops. Parallel.For(0, sourceMatrix.Depth, options, (z) => { Parallel.For(0, sourceMatrix.Height, options, (y) => { Parallel.For(0, sourceMatrix.Width, options, (x) => { ushort targetValue = sourceMatrix[z, y, x]; var targetPoint = ApplyTransformationMatrix(x, y, z, transformationMatrix); transformedPoints[targetPoint] = targetValue; }); }); }); } catch (OperationCanceledException) { Console.WriteLine("Operation Cancelled"); } return(CreateNewSizedMatrix(transformedPoints, sourceMatrix.BytePerPixel)); }
public IEnumerable <WriteableBitmap> Build() { Image3DMatrix imageMatrix = _imageLoader.GetImageMatrix(); TransformationMatrix transformationMatrix = GetTransformationMatrix(imageMatrix); imageMatrix = ApplyTransformationMatrix(imageMatrix, transformationMatrix); return(MatrixToBitmapImageConverter.GetImages(imageMatrix)); }
private Image3DMatrix ApplyTransformationMatrix(Image3DMatrix imageMatrix, TransformationMatrix transformationMatrix) { if (transformationMatrix != TransformationMatrix.UnitMatrix4x4) { imageMatrix = Image3DMatrix.Transform(imageMatrix, transformationMatrix); } return(imageMatrix); }
/// <summary> /// Applies a function to every voxel of the image. /// </summary> /// <param name="sourceMatrix">The image which will provide the original voxel values.</param> /// <param name="targetMatrix">The image where the new values will be stored.</param> /// <param name="action">This function gets the position of the original voxel and returns a value for it.</param> /// /// <returns>The targetMatrix will be returned.</returns> public static Image3DMatrix Map(Image3DMatrix sourceMatrix, Image3DMatrix targetMatrix, Func <int, int, int, ushort> action) { for (int z = 0; z < sourceMatrix.Depth; z++) { for (int y = 0; y < sourceMatrix.Height; y++) { for (int x = 0; x < sourceMatrix.Width; x++) { targetMatrix[z, y, x] = action(x, y, z); } } } return(targetMatrix); }
private TransformationMatrix GetTransformationMatrix(Image3DMatrix imageMatrix) { if (imageMatrix != null) { //The transformations will be concatenated here. However, it is possible that //some combinations of parameters do need lead to correct results, because //transformations are not cumulative. TransformationMatrix transformationMatrix = TransformationMatrix. UnitMatrix4x4. Shear3D(Bxy, Byx, Bxz, Bzx, Byz, Bzy). Scale3D(Sx, Sy, Sz). RotateX3D(AlphaX). RotateY3D(AlphaY). RotateZ3D(AlphaZ). Shift3D(Dx, Dy, Dz); return(transformationMatrix); } return(TransformationMatrix.UnitMatrix4x4); }
public static IEnumerable <WriteableBitmap> GetImages(Image3DMatrix imageMatrix) { if (imageMatrix != null) { int height = imageMatrix.Height; int width = imageMatrix.Width; int depth = imageMatrix.Depth; int bitsPerPixel = 8 * imageMatrix.BytePerPixel; WriteableBitmap[] bitmaps = new WriteableBitmap[depth]; for (int layer = 0; layer < depth; layer++) { byte[] imageBytes = imageMatrix.GetBytes(layer); WriteableBitmap bitmap = CreateWriteableBitmap(height, width, bitsPerPixel, imageBytes); //Must be freezed to share it between threads. bitmap.Freeze(); bitmaps[layer] = bitmap; } return(bitmaps); } return(Array.Empty <WriteableBitmap>()); }
/// <summary> /// Applies a function to every voxel of the image. /// </summary> /// <param name="sourceMatrix">The image which will provide the original voxel values.</param> /// <param name="targetMatrix">The image where the new values will be stored.</param> /// <param name="action">This function gets the original voxel value and returns a new one.</param> /// <returns>The targetMatrix will be returned.</returns> public static Image3DMatrix Map(Image3DMatrix sourceMatrix, Image3DMatrix targetMatrix, Func <ushort, ushort> action) { return(Map(sourceMatrix, targetMatrix, (x, y, z) => action(sourceMatrix[z, y, x]))); }