Closed Lucashglund closed 5 years ago
Ops. I'm very sorry to trouble you. DlibDotNet.Extension is not included in nuget packge. It is experimental. Because .net core can not handle WritableBitmap. It means that it depends on non-nuget library. But .NET core 3.0 will use WritableBitmap class. So I can create nuget package of DlibDotNet.Extension.
Now, you can clone DlibDotNet and build DlibDotNet.Extension. Don't be afraid. It could be easy.
Thanks for the answer! I have one more question, I did manage to solve the problem and now I have some problem with the conversion.
To make you understand better why I need to make this conversion is because I have a video stream which is of type bitmap, I want to convert each frame to a Array2D<What ever you prefer, for best performance and available in your library> so I can use your face detection and landmark detection and finally convert it back to my bitmap.
When I am converting from bitmap to array2D I get some exceptions from ArrayToBitmap "throw new NotSupportedException(); cause I used UInt8/BYTE" and when I change type the conversion To array give me another one based on type.
Anyhow, I guess I should use RGBpixel somehow.
Could you help me out with an example of how I could make such a conversion?
Something like:
From System.Image.Bitmap -> ToArray2D
Finally - What do you think about the time complexity of such implementation? I am in need of having rather good time complexity because of real-time face tracking. I hope this isn't too much to ask for! Anyhow Thanks for an awesome library and code! Great work! @takuya-takeuchi
You can use Matrix
You can use the following code.
var bitmap = GetBitmap();
var array = ToManaged(bitmap);
var matrix = new Matrix<byte>(array, bitmap.Height, bitmap,Width);
..
..
array = matrix.ToArray();
// back to array to bitmap like ToManaged
private static byte[] ToManaged(Bitmap bitmap)
{
var format = bitmap.PixelFormat;
var width = bitmap.Width;
var height = bitmap.Height;
var array = new byte[width * height * 1]; // bitmap is treated as grayscale
BitmapData bitmapData = null;
try
{
bitmapData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly,
format);
var stride = bitmapData.Stride;
var scan0 = bitmapData.Scan0;
for (var y = 0; y < height; y++)
{
Marshal.Copy(new IntPtr(scan0 + y * stride), array, y * width * 1, width * 1)
}
}
finally
{
if (bitmapData != null)
bitmap.UnlockBits(bitmapData);
}
return array;
}
Thanks!! I still have problems with "var scan0 = bitmap.Scan0;" I did try to cast it to an int, but ended up with exceptions under runtime. If I don't cast it I have this error "Cannot convert from 'System.IntPtr to 'int' because of "new IntPtr(scan0 + y * stride)" in Marshal.copy()
Sorry late reply. I should have noted that the above code is not tested :(
y is int. But address value of scan0 may be in range of int64. Could you try cast to int64?
var tmp = ((long) scan0 + y) * stride;
Marshal.Copy(new IntPtr(tmp), array, y * width * 1, width * 1)
Don't worry! Thanks anyway, you helped me more than enough already!
I think I manage to solve it in another way, but I am not 100% sure. "Marshal.Copy(IntPtr.Add(scan0, ystride), array, y width 1, width 1);" seems to work for me, but what is the difference between creating a new IntPtr and Adding Scan0 with an offset of y*stride the way I am doing it?
Just want to make sure that I am doing it right so I don't lose some date because I use add instead. @takuya-takeuchi
Sorry, the above code is wrong.
var tmp = (long) scan0 + y * stride;
Marshal.Copy(new IntPtr(tmp), array, y * width * 1, width * 1)
what is the difference between creating a new IntPtr and Adding Scan0 with an offset of ystride the way I am doing it?
no diffrence!! My approach is old. I didn't think what you told right away. You way is elegant!!
Cool!
If I may ask another question, when I am trying to start with the face detection from your example, "DlibDotNet.Dlib.PyramidUp(matrix); And var dets = detector.Operator(matrix); " Ill receive an Exception "System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'" which seems to come from my conversion back toBitmap function "Marshal.Copy(array, 0, scan0, array.Length);".
I have tried to change the "ImageLockMode" but that doesn't seem to help.. Want me to post my code of the ToBitmap function so u can see what i have done? @takuya-takeuchi
I guess matrix won't be currupt even though using of Marshal.Copy is wrong. Because, If corrupt memory when using Marshal.Copy, CLR throw exception right now.
So I doubt it comes from bug of Matrix constructor(ArrayBase). However, PyramidUp and detector.Operator are well tested. So it may be depends on content of passed image.
Could you show me sample code and problem image if you can?
Ops. I'm very sorry to trouble you. DlibDotNet.Extension is not included in nuget packge. It is experimental. Because .net core can not handle WritableBitmap. It means that it depends on non-nuget library. But .NET core 3.0 will use WritableBitmap class. So I can create nuget package of DlibDotNet.Extension.
Now, you can clone DlibDotNet and build DlibDotNet.Extension. Don't be afraid. It could be easy.
I have another question.
@Lucashglund why did You not opening another issue here, how did we manage to understand the context of your problem, if need to gather info reading comments from totally unrelated issue names? @takuya-takeuchi could be closed
@Lucashglund Could you open new issue? Welcome to your issue report and future request!! @valerysntx thank you for your advice.
Summary of your issue
Hi there!
I need to convert my System.Drawing.Bitmap to your Array2D<> and back again to my System.Drawing.Bitmap.
I have tried to use the DlibDotNet Extension - BitmapExtensions by I can't find it. It only seems like I can find the "DlibDotNet.Extensions.EnumerableExtensions"..
I am using Visual Studio 2017, and I have added DlibDotNet from "NuGet Packages", and include it "using DlibDotNet;".
I manage to use other functions in your library, just seems like I have a problem with the Extensions...
What am I missing? Please help me :)