Equivalent Java Mat.put() in C# (OpenCV) - c#

I have been facing this line of code in a book(JAVA) many times.
It seems like it sets matrix with hardcoded values.
Mat src = new Mat(4, 1, CvType.CV_32FC2);
src.put(0, 0,
0, 0,
img.width() - 1, 0,
0, img.height() - 1,
img.width() - 1, img.height() - 1
);
And couldn't find what is equivalent to .put method in C#.
I have latest 4 version.

put method inserts data at starting position specified by row and column.
public int put(int row, int col, int[] data)
Equivalent in OpenCVSharp is
Mat src = new Mat(4, 1, MatType.CV_32FC2,
new []
{
0, 0,
img.Width - 1, 0,
0, img.Height - 1,
img.Width - 1, img.Height - 1
});
Documentation

Related

C# Span2D CopyTo not copying a 2d range correctly

I'm trying to use the Span2D type to "roll" entries in a 2d array, but it's not working as expected.
By rolling I mean the following - given an array such as:
{
{ 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2 },
{ 0, 0, 0, 0, 0 },
}
I would like to copy the first two rows down one row, so the top row can be repopulated. After the roll operation the array should look like this:
{
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 2, 2, 2, 2, 2 },
}
The Span2d CopyTo method seems perfect for this - I create a Slice of the top two rows, and a slice of the bottom two rows, copy the first slice to the second slice. But instead of the expected result above, I get:
{
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
{ 1, 1, 1, 1, 1 },
}
Here's a runnable class that shows the problem:
public class SpanTest
{
public static void Main()
{
int[,] array =
{
{ 1, 2, 3, 4, 5 },
{ 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0 },
};
var h = array.GetLength(0) - 1;
var w = array.GetLength(1);
Console.WriteLine($"slice height:{h} width: {w}\n-----------");
Span2D<int> span = array;
Console.WriteLine($"{span.ToStringMatrix()}-----------");
var sourceSlice = span.Slice(0, 0, h, w);
Console.WriteLine($"{sourceSlice.ToStringMatrix()}-----------");
var targetSlice = span.Slice(1, 0, h, w);
Console.WriteLine($"{targetSlice.ToStringMatrix()}-----------");
sourceSlice.CopyTo(targetSlice);
Console.WriteLine($"{span.ToStringMatrix()}-----------");
}
}
with a helper for printing the Span2Ds:
public static class Utils
{
public static string ToStringMatrix<T>(this Span2D<T> arr)
{
var sb = new StringBuilder();
for (var i = 0; i < arr.Height; i++)
{
for (var j = 0; j < arr.Width; j++)
{
sb.Append($"{arr[i, j]} ");
}
sb.Append(Environment.NewLine);
}
return sb.ToString();
}
}
How can I make the copy operation behave as expected? Thanks
Well, the answer is quite obvious actually - at least it was when it occurred to me at 5am this morning!
Span2D wraps an array, copying to itself alters the backing array during the copy process. By the time the second row is copied, it already contains the contents of the first row. And hence, the first row gets propagated throughout the 2d array.

EmguCV Kalman filter giving unstable results

I'm new to Kalman filtering and trying to put together a bunch of tutorials to get EMGU.CV's Kalman filter to work.
I've found a functional kalman filter at https://github.com/rlabbe/Kalman-and-Bayesian-Filters-in-Python/blob/master/13-Smoothing.ipynb that I can compare my results to.
I set up the EMGU Kalman filter with the same values, and get mostly the same results. However, sometimes it will go wrong very suddenly. (Measurement noise = 10, Q = 0.001)
Further, small changes to the measurement noise variable can suddenly make it correct (Measurement noise = 9.999, Q = 0.001)
Am I doing something wrong in the code or is it something to do with a bug or instability in the implementation?
measurementNoise = 9.999f;
processNoise = 0.001f;
List<float> measuredResult = new List<float>();
List<float> smoothedResult = new List<float>();
var depthType = DepthType.Cv32F;
var kal = new KalmanFilter(4, 1, 0, depthType);
kal.StatePost.SetTo(new float[] { 0, 1, 1, 1 }); //[x, v_x, a_x, da_dx]
var meas = new Mat(1, 1, depthType, 1); //[x]
//Transition State Matrix A
//Note: Set dT at each processing step
//[1 1 0 0]
//[0 1 1 0]
//[0 0 1 1]
//[0 0 0 1]
CvInvoke.SetIdentity(kal.TransitionMatrix, new MCvScalar(1));
kal.TransitionMatrix.SetValue(0, 1, 1.0f);
kal.TransitionMatrix.SetValue(1, 2, 1.0f);
kal.TransitionMatrix.SetValue(2, 3, 1.0f);
//Measure Matrix H
//[1 0 0 0]
kal.MeasurementMatrix.SetTo(new float[] { 1, 0, 0, 0 });
//Process Noise Covariance Matrix Q
CvInvoke.SetIdentity(kal.ProcessNoiseCov, new MCvScalar(processNoise));
//Measurement Noise Covariance Matrix R
CvInvoke.SetIdentity(kal.MeasurementNoiseCov, new MCvScalar(measurementNoise));
//Error Covariance Matrix
CvInvoke.SetIdentity(kal.ErrorCovPost, new MCvScalar(10));
for (int count = 0; count < times.Length; count++)
{
measuredResult.Add(values[count]);
meas.SetValue(0, 0, values[count]);
kal.Predict();
var mat = kal.Correct(meas);
smoothedResult.Add(((float[,])mat.GetData())[0, 0]);
}
foreach (var f in smoothedResult)
{
Console.Out.WriteLine($"{f}");
}
EDIT: Turns out that the stability was just that I'd found a set of values that didn't show spikes in that dataset. The instability is still there. Using this initialisation pattern does match the expected pattern until instability sets in though. So it looks like a bug in the underlying Kalman filter.
So after searching more, I found a closed issue in EMGU that pointed to the updated unit tests for the Kalman filter. Using their way of initialising, I've managed to get something that seems a lot more stable.
KalmanFilter tracker = new KalmanFilter(4, 1, 0);
var transitionMatrix = new Matrix<float>(new[,]
{
{1f, 1f, 0f, 0f},
{0, 1, 1, 0},
{0, 0, 1, 1},
{0, 0, 0, 1}
});
var measurementMatrix = new Matrix<float>(new[,] { { 1f, 0, 0, 0 } });
var procNoiseCov = new Matrix<float>(4, 4);
procNoiseCov.SetIdentity(new MCvScalar(processNoise));
var measurementNoise = new Matrix<float>(1, 1);
measurementNoise.SetIdentity(new MCvScalar(measurementNoiseValue));
var errorCovPost = new Matrix<float>(4, 4);
errorCovPost.SetIdentity(new MCvScalar(10));
transitionMatrix.Mat.CopyTo(tracker.TransitionMatrix);
measurementMatrix.Mat.CopyTo(tracker.MeasurementMatrix);
procNoiseCov.Mat.CopyTo(tracker.ProcessNoiseCov);
measurementNoise.Mat.CopyTo(tracker.MeasurementNoiseCov);
errorCovPost.Mat.CopyTo(tracker.ErrorCovPost);
tracker.StatePost.SetTo(new float[] { 0, 1, 1, 1 });
List<float> result = new List<float>();
Matrix<float> corrected = new Matrix<float>(4, 1);
foreach (var z in values)
{
tracker.Correct(measurement.Mat).CopyTo(corrected);
tracker.Predict();
states.Add(corrected[0,0]);
}
return states;
It's not exactly the same, but it's stable and good enough for me right now.

How do I find the middle of a 2d array?

Let's say I have a 2d array.
int[,] rooms = new int[3,5];
How would I find the middle most position?
var middle = rooms[rooms.GetLength(0) / 2, rooms.GetLength(1) / 2]
But that's only going to work where they're odd. Define further behaviour required...
In the example, this would return 1:
int[,] rooms = new int[3,5] { { 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0 } };
int len0 = rooms.GetLength(0);
int len1 = rooms.GetLength(1);
return rooms[len0 / 2, len1 / 2];
Use rooms.GetLength(0) / 2 and rooms.GetLength(1) / 2 to get the first and second index of the middle position.
This was answered here.
To find the row length
int rowLength = arr.length;
To find the column length
int columnLength = arr[0].length;
To find the middle element
int mid = arr[arr.length/2][arr[0].length/2];

Error splitting an array into two

So I need to cut off the first 16 bytes from my byte array. I followed another post I saw on Stack Overflow to use the following code:
//split message into iv and encrypted bytes
byte[] iv = new byte[16];
byte[] workingHash = new byte[rage.Length - 16];
//put first 16 bytes into iv
for (int i = 0; i < 16; i++)
{
iv[i] = rage[i];
}
Buffer.BlockCopy(rage, 16, workingHash, 0, rage.Length);
What we are trying here is to cut off the first 16 bytes from the byte[] rage and put the rest into byte[] workingHash
The error occurs at Buffer.BlockCopy(rage, 16, workingHash, 0, rage.Length);
Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
Any help will be much appreciated.
The problem is trivial: Buffer.BlockCopy's last argument requires the correct number of bytes to be copied, which (taking the starting index into account) may not exceed the array's bounds (docs).
Hence the code should look like this, avoiding any for cycles:
Buffer.BlockCopy(rage, 0, iv, 0, 16);
Buffer.BlockCopy(rage, 16, workingHash, 0, rage.Length - 16);
Notice the “- 16” at the second line, fixing the original code. The first line replaces the for cycle for the sake of consistency.
Lets assume rage is a byte array of length 20:
var rage = new byte[20]
{
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
};
After byte[] iv = new byte[16];, iv will contain:
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
After byte[] workingHash = new byte[rage.Length - 16];, workingHash will contain:
{ 0, 0, 0, 0 }
After the for loop iv is:
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }
You need:
Buffer.BlockCopy(rage, 16, workingHash, 0, rage.Length - 16);
Copy rage.Length - 16 (4) elements from rage's 16th element (which is 17) to workingHash starting from the 0th element.
The result:
{ 17, 18, 19, 20 }
By the way there is a very readable way, probably not as fast as copying arrays, but worth mentioning:
var firstSixteenElements = rage.Take(16).ToArray();
var remainingElements = rage.Skip(16).ToArray();
Fixed:
//split message into iv and encrypted bytes
byte[] iv = new byte[16];
byte[] workingHash = new byte[rage.Length - 16];
//put first 16 bytes into iv
for (int i = 0; i < 16; i++)
{
iv[i] = rage[i];
}
for (int i = 0; i < rage.Length - 16; i++)
{
workingHash[i] = rage[i + 16];
}

Maze algorithm path finder

I am trying to find the path of a maze, below is the code, it suppose to goes inside the recursiveSolve loop but it keep exiting, after second if condition what i am doing wrong here can someone help me please?
im setting Washere and correctpath array as false by default.
recursiveSolve(0, 0);
public static int[,] maze = {{0, 0, 0, 0, 0, 1},
{1, 1, 0, 0, 0, 1},
{0, 0, 0, 1, 0, 0},
{0, 1, 1, 0, 0, 1},
{0, 1, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 1}};
public static Boolean recursiveSolve(int row, int col) {
Boolean[,] wasHere = new Boolean[6, 6];
Boolean[,] correctPath = new Boolean[6, 6]; // The solution to the maze
if (maze[row, col] == 1 || wasHere[row, col]) {
return false;
}
else if (row == 0 || row == 6 - 1 || col == 0 || col ==6 - 1) {
correctPath[row, col] = true;
return true;
}
else {
wasHere[row, col] = true;
if (recursiveSolve(row - 1, col) || recursiveSolve(row + 1, col) ||
recursiveSolve(row, col - 1) ||
recursiveSolve(row, col +1)) {
correctPath[row, col] = true;
return true; // successfully escaped; this square is on path
}
else {
return false;
}
}
}
Your wasHere and correctPath arrays are local to the recursiveSolve function, which means each time you enter in this function, the arrays will be inited to false (or random value).
First of all try to make these arrays static as well, and see if that solves your problem with the always false.
Also, you should start your search from somewhere inside the maze instead of from an edge (0,0 means you already exiting the maze).
If you want to start from 0,0 ,mark that as a starting point, and don't allow it as a valid solution.
If you're actually doing path finding and this is not an excercise which requires this particular solution, then you might also want to look into the A* algorithm which is probably more efficient and robust.
Wikipedia

Categories