Emgu.CV DTrees train System.AccessViolationException - c#

I use this function to train my DTrees object from Emgu.CV library.
public void Learn_Internal(double[][] aadMlInpFv, int[] anMlOutGt)
{
if (aadMlInpFv == null || aadMlInpFv.Length == 0) return;
try
{
//Use the first 80% of data as training sample
int trainingSampleCount = (int)(aadMlInpFv.Length * 0.8);
Matrix<Byte> varType = new Matrix<byte>(aadMlInpFv[0].Length + 1, 1);
varType.SetValue((byte)VarType.Categorical); //the data is categorical
Matrix<byte> sampleIdx = new Matrix<byte>(aadMlInpFv.Length, 1);
using (Matrix<byte> sampleRows = sampleIdx.GetRows(0, trainingSampleCount, 1))
sampleRows.SetValue(255);
//Matrix<double> trainData = new Matrix<double>(aadMlInpFv.Length, aadMlInpFv[0].Length);
Matrix<float> trainData = new Matrix<float>(aadMlInpFv.Length, aadMlInpFv[0].Length);
for (int i = 0; i < aadMlInpFv.Length; i++)
{
for (int j = 0; j < aadMlInpFv[i].Length; j++)
{
trainData[i, j] = (float)aadMlInpFv[i][j];
}
}
Matrix<int> trainClasses = new Matrix<int>(anMlOutGt);
using (TrainData td = new TrainData(trainData, DataLayoutType.RowSample, trainClasses))
{
m_oModelDTree.Train(td);
}
}
catch (Exception ex)
{
}
}
It cause an exception: System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'
m_oModelDTree is an object from DTrees initialized like this:
m_oModelDTree = new DTrees()
{
MaxDepth = 8,
MinSampleCount = 10,
RegressionAccuracy = 0,
UseSurrogates = true,
MaxCategories = 15,
CVFolds = 10,
Use1SERule = true,
TruncatePrunedTree = true
};
I have implemented other classifier models like KNN, AdaBoost, etc from Emgu.CV befor like this method and all of them works except DTrees.
What was wrong with this?
EDIT:
Exception thrown in line: m_oModelDTree.Train(td);

Related

How to set a timeout for a lock (that has been acquired)?

I am recently working on a multithreaded project, and come across with a problem.
SafeCreateProcessThread(); is being called every 220ms as long as the sensor is streaming.
public void StreamingDisplayMonitor()
{
var dtStartTemp = DateTime.Now;
while (IsStreaming)
{
if ((DateTime.Now - dtStartTemp).TotalMilliseconds >= 220)
{
SafeCreateProcessThread();
dtStartTemp = DateTime.Now;
}
if (SystemManager.bleTask.DicConnection.Count == 0) IsStreaming = false;
}
}
Here is the method that starts the thread:
private void SafeCreateProcessThread()
{
var th = new Thread(() => ProcessStreamingData());
th.IsBackground = true;
th.Start();
th.Join(230);
if (th.IsAlive)
{
// timeout
// terminate the thread and release the lock
}
}
and the ProcessStreamingData() is as follows
private void ProcessStreamingData()
{
var sensorCount = ConnectedSensors.Length;
for (int i = 0; i < sensorCount; i++)
{
lock (lockObject1)
{
var sensor = ConnectedSensors[i];
if (sensor.lst_streaming_data.Count > 0)
{
var streamingPacket = sensor.lst_streaming_data.Last();
var calibrateMag = sensor.attitudeHelper.CalibrateStreamingPacket(streamingPacket, sensor);
sensor.attitudeHelper.MagDisturbDetect(sensor, streamingPacket, calibrateMag);
sensor.attitudeHelper.CalculateQuaternion(sensor, streamingPacket, calibrateMag);
}
}
}
this.Invoke(new Action(UpdateAllConnectedChart));
}
as it goes, one of the threads became stuck at sensor.attitudeHelper.MagDisturbDetect(sensor, streamingPacket, calibrateMag); with some unknown reasons (without throwing any exceptions), it is a method within a 3rd party library. and as this problematical thread locks the lockObject1, all the new threads created can not run the code within the lock...
So in this case, using the cancellation token, stop flag seems not a right way to terminate the thread. I have tried the .abort() method, which, of course, makes the termination process unpredictable, therefore, it is not a good way either. and also Monitor.TryEnter can not do the job as it timeout the threads trying to acquire the lock, not the problematical one who owns the lock.
What I want to do is to terminate the problematical thread and release the lock when it is timeout. If there is anyone can tell me how to implement a reliable way to terminate a thread (the code block in SafeCreateProcessThread()).
if (th.IsAlive)
{
// timeout
// terminate the thread and release the lock
}
Thanks in advance.
the code in which the thread became stuck:
marked with // ------>
public bool MagDisturbDetect(DSensor sensor, StreamingPacket streamingPacket, double[] calibratedMag)
{
if (lstMagXBuffer == null)
{
lstMagXBuffer = new List<double>();
lstMagYBuffer = new List<double>();
lstMagZBuffer = new List<double>();
}
if (lstRawMagXBuffer == null)
{
lstRawMagXBuffer = new List<double>();
lstRawMagYBuffer = new List<double>();
lstRawMagZBuffer = new List<double>();
}
bool disturbDetected = false;
int bufferLength = 200;
if (sensor.config.mag_sampling_frequency != "standby")
{
var x = Convert.ToInt32(sensor.config.mag_sampling_frequency.Replace("Hz", ""));
bufferLength = 2 * x;
}
double isDisturbed = 0;
magCalibrator magCalibrator = new magCalibrator();
if (lstMagXBuffer.Count >= bufferLength)
{
double[] magXBuffer = lstMagXBuffer.ToArray();
double[] magYBuffer = lstMagYBuffer.ToArray();
double[] magZBuffer = lstMagZBuffer.ToArray();
isDisturbed = magCalibrator.callisMagDisturbanceFcn(magXBuffer, magYBuffer, magZBuffer, 0.3f);
if (isDisturbed == 1)
{
disturbDetected = true;
}
else
{
disturbDetected = false;
}
//Console.WriteLine($"MagDisturbDetect {isDisturbed}");
//Console.WriteLine("------------------------------clear calibrated buffer");
lstMagXBuffer = new List<double>();
lstMagYBuffer = new List<double>();
lstMagZBuffer = new List<double>();
}
else
{
lstRawMagXBuffer.Add(streamingPacket.magnx);
lstRawMagYBuffer.Add(streamingPacket.magny);
lstRawMagZBuffer.Add(streamingPacket.magnz);
lstMagXBuffer.Add(calibratedMag[0]);
lstMagYBuffer.Add(calibratedMag[1]);
lstMagZBuffer.Add(calibratedMag[2]);
}
// DateTime dt = DateTime.Now;
if (disturbDetected)
{
double[] rawMagXBuffer = lstRawMagXBuffer.ToArray();
double[] rawMagYBuffer = lstRawMagYBuffer.ToArray();
double[] rawMagZBuffer = lstRawMagZBuffer.ToArray();
double[] gainOut = new double[] { 0 }, magXAfterCali = new double[] { 0 }, magYAfterCali = new double[] { 0 }, magZAfterCali = new double[] { 0 }, rmse = new double[] { 0 };
double[] gainIn = new double[] { 1, 0, 0, 0, 1, 0, 0, 0, 1 };
double[] offsetIn = new double[] { 0, 0, 0 };
// ------> became stuck when executing magCalibrator.callCalibrateMagetometerLiveFcn(...)
magCalibrator.callCalibrateMagetometerLiveFcn(rawMagXBuffer, rawMagYBuffer, rawMagZBuffer, gainIn, offsetIn, 0.3f,
ref gainOut, ref sensor.offsetMagCalibrate, ref magXAfterCali, ref magYAfterCali, ref magZAfterCali, ref rmse);
lstRawMagXBuffer = new List<double>();
lstRawMagYBuffer = new List<double>();
lstRawMagZBuffer = new List<double>();
}
else
{
magCalibrator.callUpdateOffsetFcn((float)streamingPacket.magnx, (float)streamingPacket.magny, (float)streamingPacket.magnz, 0.3f,
sensor.offsetMagCalibrate[0], sensor.offsetMagCalibrate[1], sensor.offsetMagCalibrate[2], ref sensor.offsetMagCalibrate);
}
magDisturbed = disturbDetected;
return disturbDetected;
}

SystemAccessViolationException in OpenTK.dll using Shaders

Using OpenTK to attempt to create shaders in C#, repeatedly getting memory access violation errors. Any help would be appreciated. Here is the class I am having errors with, full code will be able to be found at https://github.com/Autodesk/synthesis/engine-research/OpenTKBuild
Error at Line 53 :
An unhandled exception of type 'System.AccessViolationException'
occurred in OpenTK.dll
Additional information: Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.
Source code:
using OpenTK.Graphics.OpenGL;
namespace OpenTKbuild
{
class Shader
{
public int Program;
public Shader(string vertexPath, string fragmentPath)
{
string vertexCode, fragmentCode;
int vertex, fragment;
try
{
System.IO.FileStream vShaderFile = new System.IO.FileStream(vertexPath, System.IO.FileMode.Open);
System.IO.FileStream fShaderFile = new System.IO.FileStream(fragmentPath, System.IO.FileMode.Open);
System.IO.StreamReader vShaderRead = new System.IO.StreamReader(vShaderFile);
System.IO.StreamReader fShaderRead = new System.IO.StreamReader(fShaderFile);
vShaderFile.Close();
fShaderFile.Close();
vertexCode = vShaderRead.ToString();
fragmentCode = fShaderRead.ToString();
char[] vShaderCodeChar = vertexCode.ToCharArray();
char[] fShaderCodeChar = fragmentCode.ToCharArray();
string[] vShaderCode = new string[vShaderCodeChar.Length];
string[] fShaderCode = new string[fShaderCodeChar.Length];
for (int i = 0; i < vShaderCodeChar.Length; i++)
{
vShaderCode[i] = vShaderCodeChar[i].ToString();
}
for (int i = 0; i < vShaderCodeChar.Length; i++)
{
vShaderCode[i] = vShaderCodeChar[i].ToString();
}
int vcount = vShaderCode.Length;
int fcount = fShaderCode.Length;
vertex = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(vertex, 1, vShaderCode, ref vcount);
GL.CompileShader(vertex);
fragment = GL.CreateShader(ShaderType.FragmentShader);
// --------> error occurs onthe next line. when commented out, error does not persist.
GL.ShaderSource(fragment, 1, fShaderCode, ref fcount);
GL.CompileShader(fragment);
Program = GL.CreateProgram();
GL.AttachShader(Program, vertex);
GL.AttachShader(Program, fragment);
GL.LinkProgram(Program);
GL.DeleteShader(vertex);
GL.DeleteShader(fragment);
}
catch
{
throw new System.Exception("wut");
}
}
public void Use()
{
GL.UseProgram(Program);
}
}
}
I'm not sure why you convert the shader source string into a character array and then into a string array with just one character per string. But even if you do so, the length and the count parameter of GL.ShaderSource have to fit your data. At the moment, you tell OpenGL that there is one element in the array and that this element has fcount characters, which is not the case. This is then the reason why OpenGL tries to read outside of your allocated memory.
To solve your problem, I would suggest the following code:
GL.ShaderSource(vertex, 1, new string[] { vertexCode }, vertexCode.Length);
solved using the following code:
using OpenTK;
using OpenTK.Graphics.OpenGL;
namespace MeshImport
{
class Shader
{
public int ShaderProgram = 0;
public static int vertex, fragment, geometry;
public Shader() : base()
{
}
public Shader(string vertexPath, string fragmentPath, string geometryPath)
{
#region OLD
//string vertexCode = null, fragmentCode = null;
//System.IO.FileStream vShaderFile = new System.IO.FileStream(vertexPath, System.IO.FileMode.Open);
//System.IO.FileStream fShaderFile = new System.IO.FileStream(fragmentPath, System.IO.FileMode.Open);
#endregion
string vCode = null, fCode = null, gCode = null;
try
{
#region OLD
//System.IO.StreamReader vShaderRead = new System.IO.StreamReader(vShaderFile);
//System.IO.StreamReader fShaderRead = new System.IO.StreamReader(fShaderFile);
//vShaderFile.Close();
//fShaderFile.Close();
//vertexCode = vShaderRead.ToString();
//fragmentCode = fShaderRead.ToString();
#endregion
vCode = System.IO.File.ReadAllText(vertexPath);
fCode = System.IO.File.ReadAllText(fragmentPath);
gCode = System.IO.File.ReadAllText(geometryPath);
}
catch
{
System.Console.WriteLine("FILE NOT READ SUCCESSFULLY\n");
}
#region OLD
//char[] vShaderCodeChar = vertexCode.ToCharArray();
//char[] fShaderCodeChar = fragmentCode.ToCharArray();
//string[] vShaderCode = new string[vShaderCodeChar.Length];
//string[] fShaderCode = new string[fShaderCodeChar.Length];
//for (int i = 0; i < vShaderCodeChar.Length; i++)
//{
// vShaderCode[i] = vShaderCodeChar[i].ToString();
//}
//for (int i = 0; i < vShaderCodeChar.Length; i++)
//{
// vShaderCode[i] = vShaderCodeChar[i].ToString();
//}
#endregion
vertex = GL.CreateShader(ShaderType.VertexShader);
GL.CompileShader(vertex);
fragment = GL.CreateShader(ShaderType.FragmentShader);
GL.CompileShader(fragment);
geometry = GL.CreateShader(ShaderType.GeometryShaderExt);
GL.CompileShader(geometry);
compileShader(vertex, vCode);
compileShader(fragment, fCode);
compileShader(geometry, gCode);
ShaderProgram = GL.CreateProgram();
GL.AttachShader(ShaderProgram, vertex);
GL.AttachShader(ShaderProgram, fragment);
GL.LinkProgram(ShaderProgram);
string info;
GL.GetProgramInfoLog(ShaderProgram, out info);
System.Console.WriteLine(info);
GL.ProgramParameter(ShaderProgram, Version32.GeometryInputType, (int)All.Lines);
GL.ProgramParameter(ShaderProgram, Version32.GeometryOutputType, (int)All.LineStrip);
int tmp;
GL.GetInteger((GetPName)ExtGeometryShader4.MaxGeometryOutputVerticesExt, out tmp);
#region OLD
//int success;
//char[] infolog = new char[512];
//int[] vcount = null;
//int[] fcount = null;
//int nullint = 0;
//System.Text.StringBuilder sb = new System.Text.StringBuilder();
//sb.Append(infolog);
//vertex = GL.CreateShader(ShaderType.VertexShader);
//GL.CompileShader(vertex);
//GL.GetShader(vertex, ShaderParameter.CompileStatus, out success);
//if (success == 0)
//{
// GL.GetShaderInfoLog(vertex, 512, out nullint, sb);
// System.Console.WriteLine("Error: Shader : Vertex : Compilation Failed\n" + infolog);
//}
//fragment = GL.CreateShader(ShaderType.FragmentShader);
//GL.CompileShader(fragment);
//GL.GetShader(fragment, ShaderParameter.CompileStatus, out success);
//if (success == 0)
//{
// GL.GetShaderInfoLog(fragment, 512, out nullint, sb);
// System.Console.WriteLine("Error: Shader : Fragment : Compilation Failed\n" + infolog);
//}
//Program = GL.CreateProgram();
//GL.AttachShader(Program, vertex);
//GL.AttachShader(Program, fragment);
//GL.LinkProgram(Program);
//GL.DeleteShader(vertex);
//GL.DeleteShader(fragment);
#endregion
}
public void Use()
{
GL.UseProgram(ShaderProgram);
}
private void compileShader(int shader, string source)
{
GL.ShaderSource(shader, source);
GL.CompileShader(shader);
string info;
GL.GetShaderInfoLog(shader, out info);
System.Console.WriteLine(info);
int compileResult;
GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
if (compileResult != 1)
{
System.Console.WriteLine("CompileError : " + source);
}
}
public void cleanUp()
{
if (fragment != 0)
GL.DeleteShader(fragment);
if (vertex != 0)
GL.DeleteShader(vertex);
if (geometry != 0)
GL.DeleteShader(geometry);
}
}
}

how to apply OpenCvSharp FitLine

I'm using OpenCvSharp with C# and cannot find how to apply FitLine method.
public static void Apply(Bitmap bitmap)
{
using (Mat source = bitmap.ToMat())
{
var output = new List<OpenCvSharp.CPlusPlus.Vec4f>(); // I don't know which variable is accepted.
Cv2.FitLine(source, OutputArray.Create(output), DistanceType.L2, 0, 0.01, 0.01);
Debug.WriteLine(output);
}
}
An exception occurred in FitLine method and the error message is as below.
An exception of type 'OpenCvSharp.OpenCVException' occurred in OpenCvSharp.dll but was not handled in user code
Additional information: (is2d || is3d) && (points.depth() == CV_32F || points.depth() == CV_32S)
I changed source using source.ConvertTo(source, MatType.CV_32F, 1.0 / 255.0); in order to match MatType CV_32F in error message but same error was shown.
As second trial, refer to this link, below code throws memory protection exception.
using (Mat source = bitmap.ToMat())
{
var input = new List<OpenCvSharp.CPlusPlus.Point2f>();
for (int i = 0; i < source.Width; i++)
{
for (int j = 0; j < source.Height; j++)
{
if (source.At<byte>(i, j) > 0)
input.Add(new Point2f(i, j));
}
}
var output = new List<OpenCvSharp.CPlusPlus.Vec4f>();
Cv2.FitLine(InputArray.Create(input), OutputArray.Create(output), DistanceType.L2, 0, 0.01, 0.01);
Debug.WriteLine(output);
return source.ToBitmap();
}
How can I apply FitLine correctly?
I just mocked this test below based on this url http://answers.opencv.org/question/14547/fitline-always-crashes/?answer=14550#post-id-14550 and it seems to work. This example is with OpenCvSharp 3.1.
List<Point2f> points = new List<Point2f>();
points.Add(new Point2f(3, 3));
points.Add(new Point2f(4, 4));
points.Add(new Point2f(5, 5));
Line2D line = Cv2.FitLine(points, DistanceTypes.L2, 0, 0.01, 0.01);

Saving raw detph-data

I am trying to save my kinect raw depth-data and i dont want to use the Kinect Studio, because i need the raw-data for further calculations. I am using the kinectv2 and kinect sdk!
My problem is that i just get low FPS for the saved data. Its about 15-17FPS.
Here my Framereader ( in further steps i want to save colorstream also):
frameReader = kinectSensor.OpenMultiSourceFrameReader(FrameSourceTypes.Depth);
frameReader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;
Here the Event:
void Reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e)
{
var reference = e.FrameReference.AcquireFrame();
saveFrameTest(reference);
frame_num++;
}
Here the saving-function:
private unsafe void saveFrameTest(Object reference)
{
MultiSourceFrame mSF = (MultiSourceFrame)reference;
using (var frame = mSF.DepthFrameReference.AcquireFrame())
{
if (frame != null)
{
using (Microsoft.Kinect.KinectBuffer depthBuffer = frame.LockImageBuffer())
{
if ((frame.FrameDescription.Width * frame.FrameDescription.Height) == (depthBuffer.Size / frame.FrameDescription.BytesPerPixel))
{
ushort* frameData = (ushort*)depthBuffer.UnderlyingBuffer;
byte[] rawDataConverted = new byte[(int)(depthBuffer.Size / 2)];
for (int i = 0; i < (int)(depthBuffer.Size / 2); ++i)
{
ushort depth = frameData[i];
rawDataConverted[i] = (byte)(depth >= frame.DepthMinReliableDistance && depth <= frame.DepthMaxReliableDistance ? (depth) : 0);
}
String date = string.Format("{0:hh-mm-ss}", DateTime.Now);
String filePath = System.IO.Directory.GetCurrentDirectory() + "/test/" +date+".raw";
File.WriteAllBytes(filePath, rawDataConverted);
rawDataConverted = null;
}
}
}
}
}
Further Infomration:
I included my code in a simple Console-Application on a Intel® Xeon® Processor E5-1620 3,7GHz with 16 GB RAM.
i think the for-loop is taking to much time:
for (int i = 0; i < (int)(depthBuffer.Size / 2); ++i)
{
ushort depth = frameData[i];
rawDataConverted[i] = (byte)(depth >= frame.DepthMinReliableDistance && depth <= frame.DepthMaxReliableDistance ? (depth) : 0);
}
I could improved my framerate. Now, i am accessing the kinectbuffer directly and resign the for-loop.
Microsoft.Kinect.KinectBuffer depthBuffer = frame.LockImageBuffer();
Marshal.Copy(depthBuffer.UnderlyingBuffer, rawData_depth, 0, (depthImageSize));
depthBuffer.Dispose();
frame.Dispose();
However i couldnt get the 30FPS-rate. Now it is about 25 FPS.
You could try something like this to get your array.
It's what I normally use.
var frame = frameReference.AcquireFrame();
var frameDescription = frame.FrameDescription;
ushort[] frameData = new ushort[frameDescription.Width * frameDescription.Height];
frame.CopyFrameDataToArray(frameData);

function works correctly from MATLAB, but not when called from .NET

I'm using MATLAB Builder NE for interoperability to call MATLAB functions from a C# .NET program built as a plug-in for the open source application ClearCanvas. When I run the code normally from the .NET program, I usually (but not always) get the error message
MWMCR::EvaluateFunction error ... Reference to non-existent element of a cell array. Error in => ComputeT1Maps.m at line 178.
The line of MATLAB code in question is as follows:
seriesHeader = currentSlab.Slice{1}.MetaData{1}.Header;
Header is a struct of the form given by MATLAB's dicominfo function and MetaData{n} is a struct that contains the filename and image header struct for the nth image file.
The function signature for the ComputeT1Maps function is:
function ComputeT1Maps(data, options)
To try to figure out this bug I put the following line in at the beginning of the ComputeT1Maps function in order to preserve state so I could see what values were passed to MATLAB from .NET:
save(fullfile('F:\MATLAB\T1Mapping', 'T1_debug.mat'), 'data', 'options', ...
'-mat', '-v7.3');
So, having preserved the inputs to this function (received from the .NET program that called it), I then tried running my ComputeT1Maps function from an interactive MATLAB session after loading in the saved variables, so that I could utilize MATLAB's debugging tools to figure out why I was getting the error. That's when things got really bizarre. The function works just fine from the interactive MATLAB session when given the exact same operands that were given to it when it was called from my .NET program. How can this be? How can the function fail when called from C# .NET, but run properly when given the exact same input in an interactive MATLAB session? Also, this same code used to work before and the error only began to happen after I updated both my local installation of MATLAB and the MCR to the latest version (2011b).
On the .NET side, the data that is passed to MATLAB is constructed by the following function:
public void ExchangeData(MultidimensionalDataCollection mdc, string outputPath, bool generateAncillaryTestImages,
bool excludeAcquisitions, double[] exclusionList, bool showProgressBar, bool displayComputedImages,
bool pauseAtEachSlice, bool softwareDiagnostics, bool displayProgressBar)
{
try
{
int subspaceIndex = 0;
int slabIndex = 0;
int sliceIndex = 0;
int imageIndex = 0;
MWStructArray topLevelGrouping;
MWCellArray geometricSubspaceList;
MWStructArray geometricGrouping;
MWCellArray slabList;
MWStructArray slabGrouping;
MWCellArray sliceList;
MWStructArray sliceGrouping;
MWCellArray imageMetaData;
MWStructArray perImageData;
MWArray[] result;
MWLogicalArray successFlag;
MWStructArray header;
MWCellArray sopInstanceUids;
MWStructArray t1MapOptions;
topLevelGrouping = new MWStructArray(1, 1, new string[] { "GeometricSubspace",
"GeometricSubspaceCount" });
topLevelGrouping["GeometricSubspaceCount", 1] = mdc.Count;
geometricSubspaceList = new MWCellArray(1, mdc.Count);
subspaceIndex = 0;
foreach (GeometricSubspace subspace in mdc)
{
subspaceIndex++;
geometricGrouping = new MWStructArray(1, 1, new string[] { "Slab",
"SlabCount" });
geometricGrouping["SlabCount", 1] = subspace.Count;
slabList = new MWCellArray(1, subspace.Count);
slabIndex = 0;
foreach (Slab slab in subspace)
{
slabIndex++;
slabGrouping = new MWStructArray(1, 1, new string[] { "Slice",
"SliceCount" });
slabGrouping["SliceCount", 1] = slab.Count;
sliceList = new MWCellArray(1, slab.Count);
sliceIndex = 0;
foreach (Slice slice in slab)
{
sliceIndex++;
sliceGrouping = new MWStructArray(1, 1, new string[] {
"ImageCount", "MetaData", "MultidimensionalPixelData",
"SliceLocation", "SopInstanceUids" });
sliceGrouping["ImageCount", 1] = slice.Count;
imageMetaData = new MWCellArray(1, slice.Count);
int rows, columns;
short[,,,] multidimensionalPixelData = null;
imageIndex = 0;
foreach (Image image in slice)
{
imageIndex++;
short[,] imageMatrix = null;
if (!image.ImageSopClass.DicomUid.Equals(DicomUids.MRImageStorage))
throw new NotSupportedException("SopClass " + image.ImageSopClass.Name + " is not supported.");
else
{
DicomUncompressedPixelData rawPixelData = image.PixelData;
imageMatrix = GetCCImageMatrix(rawPixelData, out rows, out columns);
if (imageIndex == 1)
{
multidimensionalPixelData = new short[slice.Count, 1, columns, rows];
}
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
// Remember that C# array indices start with 0 while in MATLAB they start with 1
multidimensionalPixelData[imageIndex - 1, 0, i, j] = imageMatrix[i, j];
}
}
}
perImageData = new MWStructArray(1, 1, new string[] { "FileName", "Header" });
perImageData["FileName", 1] = image.FileName;
result = _mlT1Mapping.QT1GetDicomHeader(2, image.FileName);
if (result == null)
throw new Exception("GetDicomHeader failed to read the header file for filename: " +
image.FileName);
else
{
// MWStructArray
successFlag = (MWLogicalArray)result[0];
bool[] headerObtained = successFlag.ToVector();
if (headerObtained[0])
{
header = (MWStructArray)result[1];
perImageData["Header", 1] = header;
imageMetaData[1, imageIndex] = perImageData;
}
else
{
Console.WriteLine("GetDicomHeader failed to read the header file for filename: " +
image.FileName);
}
}
}
sliceList[1, sliceIndex] = sliceGrouping;
sliceGrouping["MetaData", 1] = imageMetaData;
sliceGrouping["SliceLocation", 1] = slice.SliceLocation;
List<string> theSops = slice._sopList;
sopInstanceUids = new MWCellArray(1, slice._sopList.Count);
int count = 0;
foreach (string sop in theSops)
{
count++;
sopInstanceUids[1, count] = sop;
}
sliceGrouping["SopInstanceUids", 1] = sopInstanceUids;
sliceGrouping["MultidimensionalPixelData", 1] = (MWNumericArray)multidimensionalPixelData;
}
slabList[1, slabIndex] = slabGrouping;
slabGrouping["Slice", 1] = sliceList;
}
geometricSubspaceList[1, subspaceIndex] = geometricGrouping;
geometricGrouping["Slab", 1] = slabList;
}
topLevelGrouping["GeometricSubspace", 1] = geometricSubspaceList;
t1MapOptions = new MWStructArray(1, 1, new string[] { "DirectoryPath",
"ComputeDifferenceImages", "ComputeMultiplicationImages", "DisplayComputedImages", "PauseAtEachSlice",
"SoftwareDiagnostics", "DisplayProgressBar"
});
t1MapOptions["DirectoryPath"] = (MWCharArray)outputPath;
t1MapOptions["SaveS0Maps"] = (MWLogicalArray)generateAncillaryTestImages;
t1MapOptions["ExcludeAcquisitions"] = (MWLogicalArray)excludeAcquisitions;
t1MapOptions["ExclusionList"] = (MWNumericArray)exclusionList;
t1MapOptions["DisplayComputedImages"] = (MWLogicalArray)displayComputedImages;
t1MapOptions["PauseAtEachSlice"] = (MWLogicalArray)pauseAtEachSlice;
t1MapOptions["SoftwareDiagnostics"] = (MWLogicalArray)softwareDiagnostics;
t1MapOptions["DisplayProgressBar"] = (MWLogicalArray)displayProgressBar;
_mlT1Mapping.ComputeT1Maps(topLevelGrouping, t1MapOptions);
}
catch (Exception)
{
throw;
}
}
I'm not yet 100% certain that I've fixed everything, but so far the tests appear to be succeeding after a few changes. It seems that the crux of the problem was that the order of some assignments was transposed. This occurred in a few places. For example, instead of:
sliceList[1, sliceIndex] = sliceGrouping;
sliceGrouping["MetaData", 1] = imageMetaData;
it should have been ordered as:
sliceGrouping["MetaData", 1] = imageMetaData;
sliceList[1, sliceIndex] = sliceGrouping;
The strange thing about this bug was that the code worked just fine in the previous version of MATLAB. It should have never worked at all!

Categories

Resources