I'm creating deep neural network with EmguCV in C#, and to train said neural network, I need to put labels into Mat format. I´ve created my Mat like this:
Mat responses = Mat.Zeros(trainData.Rows, distinctLabelCount.Count, Emgu.CV.CvEnum.DepthType.Cv32F, 1);
It creates Mat of zeros of size (400,10) as type float and with grayscale values if I understood correctly.
Now I have 400 rows of input data and 10 labels and I need to replace 0 value at certain positions to encode correct label into the mat. like at position (0,1) for value of 1 ,,, position (3,5) to set label 5 for 4th row etc.
All I've seen so far from googling was method responses.at<float>(...);, but that was probably in C++ and I cannot seem to access that method in C#. So I'm stuck not knowing how to edit values in Mat.
Any help would be greatly appreciated, thanks for reading and thank you for your time.
The equivalent to c++ opencv at() in C# is the index operator:
pixel = image[x, y]
image[x, y] = pixel;
You can change the value at row r and column c to newvalue using Marshal.Copy like this:
float newvalue = 1;
float [] mv = new float [] { newvalue };
Marshal.Copy(mva, 0, responses.DataPointer + (r * responses.Cols + c) * responses.ElementSize, 1);
Setting individual values on a Mat is a bit tricky.
You can either use the Matrix<DepthType.Cv32F> class instead Mat.
var matrix = new Matrix<DepthType.Cv32F>(rows, cols);
matrix[0, 0] = 3;
Or setting the values of a flaot[,] array that underlays a Mat object.
var imagedata = new float[rows, cols];
GCHandle imageDataHandle = GCHandle.Alloc(imagedata, GCHandleType.Pinned);
var m = new Mat(rows, cols, DepthType.Cv32F, imageDataHandle.AddrOfPinnedObject());
imagedata[0, 0] = 3;
imageDataHandle.Free();
Related
I am trying to take a grayscale bitmap and extract a single line from it and then graph the gray values. I got something to work, but I'm not really happy with it. It just seems slow and tedious. I am sure someone has a better idea
WriteableBitmap someImg; //camera image
int imgWidth = someImg.PixelWidth;
int imgHeight = someImg.PixelHeight;
Int32Rect rectLine = new Int32Rect(0, imgHeight / 2, imgWidth, 1); //horizontal line half way down the image as a rectangle with height 1
//calculate stride and buffer size
int imgStride = (imgWidth * someImg.Format.BitsPerPixel + 7) / 8; // not sure I understand this part
byte[] buffer = new byte[imgStride * rectLine.Height];
//copy pixels to buffer
someImg.CopyPixels(rectLine, buffer, imgStride, 0);
const int xGraphHeight = 256;
WriteableBitmap xgraph = new WriteableBitmap(imgWidth, xGraphHeight, someImg.DpiX, someImg.DpiY, PixelFormats.Gray8, null);
//loop through pixels
for (int i = 0; i < imgWidth; i++)
{
Int32Rect dot = new Int32Rect(i, buffer[i], 1, 1); //1x1 rectangle
byte[] WhiteDotByte = { 255 }; //white
xgraph.WritePixels(dot, WhiteDotByte, imgStride, 0);//write pixel
}
You can see the image and the plot below the green line. I guess I am having some WPF issues that make it look funny but that's a problem for another post.
I assume the goal is to create a plot of the pixel value intensities of the selected line.
The first approach to consider it to use an actual plotting library. I have used oxyplot, it works fine, but is lacking in some aspects. Unless you have specific performance requirements this will likely be the most flexible approach to take.
If you actually want to render to an image you might be better of using unsafe code to access the pixel values directly. For example:
xgraph.Lock();
for (int y = 0; y < imgHeight; y++){
var rowPtr = (byte*)(xgraph.BackBuffer + y * xgraph.BackBufferStride);
for(int x = 0; x < imgWidth; x++){
rowPtr[x] = (byte)(y < buffer[i] ? 0 : 255);
}
}
self.Unlock(); // this should be placed in a finally statement
This should be faster than writing 1x1 rectangles. It should also write columns instead of single pixels, and that should help making the graph more visible. You might also consider allowing arbitrary image height and scale the comparison value.
If you want to plot the pixel values along an arbitrary line, and not just a horizontal one. You can take equidistant samples along the line, and use bilinear interpolation to sample the image.
So I want to grab a partial image from a byte array of colors. The image is a unity logo that is 64x64 pixels. I want to grab a third of the image (Unity Logo). How would I traverse the byte array to get this image?
Unity Byte Array
assuming each byte is a single pixel (which is only true for 8-bit depth images), the bytes 0-63 are the first row, 64-127 are the second row, etc etc.
meaning that to find out the position of a pixel in the one-dimensional array, based on its two-dimensional coordinates in the image itself, you do
int oneDimPos = (y*64) + x;
if each pixel were 3 bytes (24-bit color depth), the conversion from 2dimensional to 1dimensional coordinates would be:
int oneDimPos = (y * 64 * 3) + (x * 3);
(so the most generic equation is:
int oneDimPos = (y * imageWidth * colorDepth) + (x * colorDepth);
and you need to keep this in mind and adjust the code accordingly. or even better, use this most generic version, and actually read the image width and its color depth from the asset you're using as source.
BEWARE: if the image is anything else than 8bits per pixel, this equation will, naturally, only give you the first, starting bit belonging to that pixel, and you still need to take care to actually also read the other ones that belong to that pixel
i'm gonna finish the answer assuming 8bit color depth, for simplicity, as well as so that you can't just copypaste the answer, but also have to understand it and re-shape it according to your specific needs ;)
)
meaning you can now do classic two nested loops for x and y:
List<byte> result = new List(); //i'm going to use list so i can just .Add each byte instead of having to calculate and allocate the final size in advance, and having to mess around with recalculating the index from the source array into the destination one, because i'm lazy
for(int x=0; x < 22; x++){ //no way for you to grab precise third since that boundary is in the middle of a pixel for an image 64pixels wide
for(int y = 0; y < 64; y++){ //we go all the way to the bottom
result.Add(sourceAsset.bytes[(y*64) + x]);
}
}
//now just convert the list to actual byte array
byte[] resultBytes = result.ToArray();
The original issue that I was having was not exactly the same as the question. I wanted to simplify it by having a byte array that everyone could take a look at. The byte array from Unity's website wasn't exactly what I was getting.
So I have 3 x 1080p portrait screen (1080 x 1920 pixels) with RGBA channels. I grabbed a screenshot from this and got a 24,883,200 size byte array.
Note, 3 * width(1080) * height(1920) * channels(4) = 24,883,200.
byte[] colors = new byte[24883200]; // Screenshot of 3x1080p screen.
byte[] leftThird = new byte[colors.Length / 3];
Array.Copy(colors, 0, leftThird, 0, colors.Length / 3); // Grab the first third of array
This is an issue because the colors array is read from top to bottom, left to right. So instead, you should read a portion of the 3 x 1080 x 4 channels.
int width = 1080 * 4; // 4 channels of colors (RGBA)
int fullWidth = width * 3; // Three screens
int height = 1920;
byte[] leftScreen = new byte[screenShotByteArray.Length / 3];
for(int i = 0; i < height; i++)
{
Array.Copy(screenShotByteArray, (i * fullWidth) + (offset * 4), leftScreen, i * width, width);
}
Within a RGB image (from a webcam) I'm looking for a way to increase the intensity/brightness of green. Glad if anyone can give a starting point.
I'm using AFORGE.NET in C# and/or OpenCV directly in C++.
in general multiplication of pixel values is though of as an increase in contrast and addition is though of as an increase in brightness.
in c#
where you have an array to the first pixel in the image such as this:
byte[] pixelsIn;
byte[] pixelsOut; //assuming RGB ordered data
and contrast and brightness values such as this:
float gC = 1.5;
float gB = 50;
you can multiply and/or add to the green channel to achieve your desired effect: (r - row, c - column, ch - nr of channels)
pixelsOut[r*w*ch + c*ch] = pixelsIn[r*w*ch + c*ch] //red
int newGreen = (int)(pixelsIn[r*w*ch + c*ch+1] * gC + gB); //green
pixelsOut[r*w*ch + c*ch+1] = (byte)(newGreen > 255 ? 255 : newGreen < 0 ? 0 : newGreen); //check for overflow
pixelsOut[r*w*ch + c*ch+2] = pixelsIn[r*w*ch + c*ch+2]//blue
obviously you would want to use pointers here to speed things up.
(Please note: this code has NOT BEEN TESTED)
For AFORGE.NET, I suggest use ColorRemapping class to map the values in your green channel to other value. The mapping function should be a concave function from [0,255] to [0,255] if your want to increase the brightness without losing details.
This is what I came up with after reading through many pages of AForge.NET and OpenCV documentation. If you apply the saturation filter first, you might get a dizzy image. If you apply it later you will get a much clearer image but some "light green" pixels might have been lost before while applying the HSV filter.
// apply saturation filter to increase green intensity
var f1 = new SaturationCorrection(0.5f);
f1.ApplyInPlace(image);
var filter = new HSLFiltering();
filter.Hue = new IntRange(83, 189); // all green (large range)
//filter.Hue = new IntRange(100, 120); // light green (small range)
// this will convert all pixels outside the range into gray-scale
//filter.UpdateHue = false;
//filter.UpdateLuminance = false;
// this will convert all pixels outside that range blank (filter.FillColor)
filter.Saturation = new Range(0.4f, 1);
filter.Luminance = new Range(0.4f, 1);
// apply the HSV filter to get only green pixels
filter.ApplyInPlace(image);
I'm working on a project to show a 2D world generation process in steps using bitmap images.
Array data is stored in this way:
Main.tile[i, j].type = x;
With x being an integer value >= 0.
Basically i and j are changed every time the program loops using for-loops, and the following statement is run after certain conditions are met during the loop process at the end of the loop.
So, a possible sequence could be:
Main.tile[4, 67].type = 1;
Main.tile[4, 68].type = 1;
Main.tile[4, 69].type = 0;
And so on.
I tried several methods of directly modifying the bitmap image once the array was changed/updated (using Bitmap.SetPixel), but this seemed way to slow to be useful for a 21k,8k pixel resoltion bitmap.
I'm looking for a way to digest the whole array at the end of the whole looping process (not after each individual loop, but between steps), and put colored points (depending on the value of the array) accordingly to i, j (as if it were a coordinate system).
Are there any faster alternatives to SetPixel, or are there easier ways to save an array to a bitmap/image file?
Change your array to one dimension array and apply all operation on the one dimension array and ONLY if you want to
display the image change it back to 2 dimension.
How to change whole array from 2D to 1D:
byte[,] imageData = new byte[1, 2]
{
{ 1, 2 }
{ 3, 4 }
};
var mergedData = new byte[ImageData.Length];
// Output { 1, 2, 3, 4 }
Buffer.BlockCopy(imageData, 0, mergedData, 0, imageData.Length);
From 2D to 1D:
// depending on whether you read from left to right or top to bottom.
index = x + (y * width)
index = y + (x * height)
From 1D to 2D:
x = index % width
y = index / width or
x = index / height
y = index % height
I hope this will solve your problem!
I have problem in dynamic memory allocation getting data from matrix
Image image_gray = new Image("im1.jpg");
Matrix circles = new Matrix(100, 1, 3);
Question 1: How can I locate dynamic memory because I don't know the number of circles?
Emgu.CV.CvInvoke.cvHoughCircles(image_gray, circles, HOUGH_TYPE.CV_HOUGH_GRADIENT,
2, 100, 200, 100, 10, 500);
Question 2: Now circle is matrix with [100 ,3], How can I get
point center= Round (circle[i][1], circle[i][1])
How can I get
int radius= circle[i][2];
what should my for loop look like to get data from matrix and casting should be point and int.
I tried already (NOT WORKING / ERROR)
for (int i=0; i < circles.Rows; i++)
{ Matrix entry = circles.GetRow(i);
float x = entry[0];
float y = entry[1];
float r = entry[2];} // NOT WORKING
because instead of copying (required) only (i) row it copies whole matrix( circles) and float x=......gives errors
No overload for method 'this' takes '1' arguments
please help me in this regard
regards
sorry to answer my question. please give some hint to dynamic memory allocation and matrix data
The documentation suggests that it will grow the matrix to fit, but it also contradicts that, so honestly, I would try a 1 row 1 col matrix on an image with more circles and see what it gives you. I see that you're using Matrix type - I don't know how you convert to the IntPtr needed by cvHoughCircles, but it should be straight forward to iterate over each row and pull out the results, which are 3 floats: (x, y, r) -
for (int i=0; i < circles.Cols; i++) {
Matrix<float> entry = circles.GetRow(i);
float x = entry[0]; // guessing here - the doc'n is truly awful
float y = entry[1];
float r = entry[2];
}