how to apply OpenCvSharp FitLine - c#

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);

Related

Emgu.CV DTrees train System.AccessViolationException

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);

Matching two imageBox controls (EmguCV)

Currently I'm working with a fingerletter recognition using visual studio 2013 C# along with emguCV. i already have a database using ms access and a program which allow me to add images(in graysacle already) to it.
I've got 2 imageBox (imageBox0, imageBox1, imageBox2).., imageBox0 displays the live streaming of my camera., imageBox1 displays the processed image of imageBox0 (contour of my hand, grayscale, rectangle) and imageBox2 displays a selected image from the ms access database.
What I needed is a way to recognize an image from imageBox1 that is similar to imageBox2 or (in the whole images inside the database)
Here are snapshots of what I am doing:
I am using EmguCV version 2.
private Image GetImgFromDB()
{
if (rowNumber >= 0)
{
byte[] FetchedImgBytes = (byte[])LocalDataTable.Rows[rowNumber]["alphaImage"];
MemoryStream stream = new MemoryStream(FetchedImgBytes);
FetchedImg = Image.FromStream(stream);
txtAlphaName.Text = (string)LocalDataTable.Rows[rowNumber]["AlphaName"];
Bitmap FetchedImgCV = (Bitmap)FetchedImg;
normalizedMasterImage = new Image<Gray, Byte>(FetchedImgCV);
return FetchedImg;
}
else
{
MessageBox.Show("There are no images in the dataase yet. add some Please");
//return null;
}
return null;
} `
I've been though this with quiet a good degree of success. Mine compares two images and you set the percentage differences between to two to raise an alert.
The key is to compare hashes, not raw data...
class bitmapCompare
{
public enum CompareResult
{
ciCompareOk,
ciPixelMismatch,
ciSizeMismatch
};
public static CompareResult Compare(bool useHash, Bitmap bmp1, Bitmap bmp2, out double err, out Bitmap diff)
{
CompareResult cr = CompareResult.ciCompareOk;
int er = 0;
err = 0;
diff = new Bitmap(bmp1.Width, bmp1.Height);
//Test to see if we have the same size of image
if (bmp1.Size != bmp2.Size)
{
cr = CompareResult.ciSizeMismatch;
err = 100;
}
else
{
//Convert each image to a byte array
System.Drawing.ImageConverter ic =
new System.Drawing.ImageConverter();
byte[] btImage1 = new byte[1];
btImage1 = (byte[])ic.ConvertTo(bmp1, btImage1.GetType());
byte[] btImage2 = new byte[1];
btImage2 = (byte[])ic.ConvertTo(bmp2, btImage2.GetType());
//Compute a hash for each image
SHA256Managed shaM = new SHA256Managed();
byte[] hash1 = shaM.ComputeHash(btImage1);
byte[] hash2 = shaM.ComputeHash(btImage2);
//Compare the hash values
if (useHash)
{
for (int i = 0; i < hash1.Length && i < hash2.Length; i++)
{
if (hash1[i] != hash2[i])
{
er++;
cr = CompareResult.ciPixelMismatch;
}
}
}
else
{
int totalPixels = 0;
er = 0;
for (int x = 0; x < bmp1.Width; x++)
{
for (int y = 0; y < bmp1.Height; y++)
{
totalPixels++;
if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
{
diff.SetPixel(x, y, Color.Black);
er++;
cr = CompareResult.ciPixelMismatch;
}
else
diff.SetPixel(x, y, Color.White);
}
}
System.Diagnostics.Debug.WriteLine("Total pixels:{0}", totalPixels);
System.Diagnostics.Debug.WriteLine("Diff pixels:{0}", er);
if (er > 0)
err = (double)er / ((double)bmp1.Height * (double)bmp1.Width);
else
err = 0;
if (err > 0) err = Math.Round(err*100, 1);
if (err > 100) err = 100;
}
}
return cr;
}
Feel free to change, this was only a POC, nothing production.

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);

"fread(serial)" and "fscanf(serial)" from Matlab to C#

everyone,
now i'm writing a C# programm according to a piece of matlab code.
In matlab code there are two commands to read data from the COM-Port:
A=fscanf(com_Port1,'%s');
A=fread(com_Port1,1008); //two sentences are next to each other like i write here.
For the first command "A=fscanf(com_Port1,'%s');" i used:
string A = com_Port1.ReadExisting();
and it seems all right, because no error warning;
for the second command "A=fread(com_Port1,1008);" i used:
double[] B = new double[1008];
for (int i = 0; i <= 1008 - 1; i++)
{
B[i] = com_Port1.ReadByte() ;
}
then it shows an error:
"A first chance exception of type 'System.TimeoutException' occurred
in System.dll".
So i'm assuming that "ReadExisting" has read all the data, and "ReadByte" can't read available data any more, is that right?Could someone tell me where i war wrong? thank you.
Yours
Adam
Add at Nov.20.2013, below is the code i have wrote, i have tried "Read()","ReadTo()","ReadLine()", but i still get the error at "otdr_Portobject.ReadByte()", i have no idea any more.
otdr_Portobject = new otdr_Port(cB_portNames.SelectedItem.ToString());
otdr_Portobject.Open();
btn_Stop.Enabled = true;
btn_Start.Enabled = false;
/*if (!otdr_Portobject.IsOpen)
{
MessageBox.Show("not open");
}
else {
MessageBox.Show("Serial Port opened");
};*/
//string start = "start";
otdr_Portobject.Write("start");
char[] b9 = new char[7];
otdr_Portobject.Read(b9, 0, 7);
Thread.Sleep(5000);
//string isready = "isready";
otdr_Portobject.Write("isready");
char[] b10 = new char[10];
otdr_Portobject.Read(b10, 0, 10);
//A = otdr_Portobject.ReadTo("\n");
//string rdatb = "rdatb";
int int32_Auslesekommando = Convert.ToInt32(pointsCon.Value-1);
otdr_Portobject.Write("rdatb " + int32_Auslesekommando.ToString("X4") + "\n");
Thread.Sleep(50);
char[] b11 = new char[18];
otdr_Portobject.Read(b11, 0, 18);
//A = otdr_Portobject.ReadTo("\n");
//A = otdr_Portobject.ReadTo("\n");
//int A1=otdr_Portobject.ReadByte();
//brechnen Y Axis
int pointNum = Convert.ToInt32(pointsCon.Value);
double[] B = new double[pointNum];
//int byteNum=otdr_Portobject.BytesToRead;
//if ( byteNum== 0) return;
try
{
for (int i = 0; i <= pointNum - 1; i++)
{
B[i] =System.Convert.ToDouble( otdr_Portobject.ReadByte() )* 256;
}
}
catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
From the c#-docs:
ReadExsting: Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object..
MATLAB:
%s format for fscanf: Read series of characters, until find white space.
So you should probably switch to ReadTo, specifying a white-space character to stop.
Or call Read yourself until the returned value is a whitespace-character.

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