Kinect depth with player index + video stream - c#

I'm trying to produce an image from the kinect where all pixel that do not represent a player will be set to black.
My idea is to use the data produced by the depthstream with player index along with the videostream to accomplish this task.
My hope was to do something like this:
byte[] pixelData = video.imageFrame.Bits;
byte[] depthData = depth.imageFrame.Bits;
var depthIndex = 0;
for (var y = 0; y < height; y++)
{
var heightOffset = y * width;
for (var x = 0; x < width; x++)
{
var index = (x + heightOffset) * 4;
var distance = GetDistanceWithPlayerIndex(depthData[depthIndex], depthData[depthIndex + 1]);
if (GetPlayerIndex(depthData[depthIndex]) == 0)
{
pixelData[index + BlueIndex] = 0;
pixelData[index + GreenIndex] = 0;
pixelData[index + RedIndex] = 0;
}
}
}
The issue that I am currently working on it trying to get the videostream data to have the same resolution as the depthwithplayerindex.
I've tried to piece some stuff together from other posts on here but I can't get it to work:
private byte[] ScaleVideoImage(ImageFrame imageFrame, int newWidth, int newHeight)
{
//convert imageFrame to byte array
Byte[] oPixelData = imageFrame.Image.Bits;
Image tempImage = BytesToImg(oPixelData);
//scale image
Bitmap bmp = new Bitmap(newWidth, newHeight);
using (Graphics graphics = Graphics.FromImage(bmp))
{
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
graphics.DrawImage(tempImage, 0, 0, bmp.Width, bmp.Height);
}
//Convert image to byte array
MemoryStream ms1 = new MemoryStream();
bmp.Save(ms1, ImageFormat.Jpeg);
byte[] result = ms1.GetBuffer();
bmp.Dispose();
ms1.Close();
return result;
}
Any ideas?

Take a look at the code I've previously shared here: http://channel9.msdn.com/coding4fun/kinect/Display-Kinect-color-image-containing-only-players-aka-background-removal

Related

MWNumericArray (or byte[,]) to Format1bppIndexed image

I'm trying to convert a Matlab MWNumericArray to a black and white picture (not grayscale). Initially I tried to transform the 2D byte array to a 1D one, then copy that to a BitmapData object and transform it in a Bitmap, but did not work, because I must be doing several mistakes trying to manipulate this data.
The method that works is a mix of code I got from other answers and online documentation. Below is what works and what does not work.
Question:
Is there a simple way to convert a 8bpp bitmap to 1bpp, one shot or byte by byte, starting from a byte[,] array and without using GetPixel or Clone methods? Unsafe code is allowed.
What I tried (works):
// Most of this code is based on a Jon Skeet's answer.
// resultOut[0] is a 2D 356x356 MWArray
var numArray = (MWNumericArray)resultOut[0];
var data = numArray.ToArray(MWArrayComponent.Real) as byte[,];
var w = data.GetLength(0);
var h = data.GetLength(1);
unsafe
{
fixed (byte* ptr = data)
{
var scan0 = new IntPtr(ptr);
var bpm1 = new Bitmap(
w, h, // image size
w, // scan size
PixelFormat.Format8bppIndexed, scan0);
// works but is grayscale, not B&W
var palette = bpm1.Palette;
palette.Entries[0] = Color.Black;
for (var i = 1; i < 256; i++)
{
palette.Entries[i] = Color.FromArgb((i * 7) % 256, (i * 7) % 256, 255);
}
bpm1.Palette = palette;
bpm1.Save("output.grayscale.png");
// works but with additional helper method call
// based on a Hans Passant answer
var bpm2 = BitmapTo1Bpp(bpm1);
bpm2.Save("output.helper.png");
// works but uses Clone
var bpm3 = bpm1.Clone(new Rectangle(0, 0, bpm1.Width, bpm1.Height), PixelFormat.Format1bppIndexed);
bpm3.Save("output.clone.png");
}
}
What I tried (did not work):
if (numArray.ToArray(MWArrayComponent.Real) is byte[,] data)
{
// Convert to 1D byte array
var h = data.GetLength(1);
var w = data.GetLength(0);
var byteArray1D = new byte[h * w];
for (var i = 0; i < h; i++)
{
for (var j = 0; j < w; j++)
{
byteArray1D[i + j] = data[i, j];
}
}
// Create Bitmap object
var bmp = new Bitmap(w, h, PixelFormat.Format8bppIndexed);
//// Set palette
// var cp = bmp.Palette;
// for (var i = 0; i < 256; ++i)
// {
// cp.Entries[i] = Color.FromArgb(255, i, i, i);
// }
// bmp.Palette = cp;
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
Marshal.Copy(byteArray1D,
0,
bmpData.Scan0,
byteArray1D.Length);
bmp.UnlockBits(bmpData);
// Does not work: graphic object cannot be created from an image that has an indexed pixel format
using (var g = Graphics.FromImage(bmp))
{
g.Clear(Color.White);
}
// Does not work: saves all black image
bmp.Save("output.raw.png");
using (var ms = new MemoryStream())
{
ms.Write(byteArray1D, 0, byteArray1D.Length);
ms.Seek(0, SeekOrigin.Begin); // ms.Position = 0;
// Does not work: parameter is not valid exception
var bm = new Bitmap(ms);
bm.Save("output.ms.png");
// Does not work: parameter is not valid exception
var newImage = Image.FromStream(ms);
newImage.Save("output.fromstream.png");
}
}

GDI+ Error only occuring on windows XP

I have some c# code that works fine on Vista & Windows 7 but throws a GDI+ Error on Windows XP (with service pack 3 installed).
Error thrown on XP
System.Runtime.INteropServices.ExternalException(0x80004005): A generic error occured in GDI+
at System.Drawing.Graphics.CheckErrorStatus(Int32Status)
at System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y)
At System.Drawing.Graphics.DrawImageUnscaled(Image image, Int32 x,Int 32 y)
at mysolution.Core.ImageTools.ConvertToBitonal(Bitmap orginal, Int32 threshold)
Code breaks on this line:
using (var g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0); // Error Is Thrown Here
}
WpFAppTestingConvertToBitonalCS
....
Below is the full function I'm calling.
public static Bitmap ConvertToBitonal(Bitmap original, int threshold)
{
Bitmap source;
// If original bitmap is not already in 32 BPP, ARGB format, then convert
if (original.PixelFormat != PixelFormat.Format32bppArgb)
{
source = new Bitmap(original.Width, original.Height, PixelFormat.Format32bppArgb);
source.SetResolution(original.HorizontalResolution, original.VerticalResolution);
using (var g = Graphics.FromImage(source))
{
g.DrawImageUnscaled(original, 0, 0);
}
}
else
{
source = original;
}
// Lock source bitmap in memory
var sourceData = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
// Copy image data to binary array
var imageSize = sourceData.Stride * sourceData.Height;
var sourceBuffer = new byte[imageSize];
Marshal.Copy(sourceData.Scan0, sourceBuffer, 0, imageSize);
// Unlock source bitmap
source.UnlockBits(sourceData);
// Create destination bitmap
var destination = new Bitmap(source.Width, source.Height, PixelFormat.Format1bppIndexed);
destination.SetResolution(original.HorizontalResolution, original.VerticalResolution);
// Lock destination bitmap in memory
var destinationData = destination.LockBits(new Rectangle(0, 0, destination.Width, destination.Height), ImageLockMode.WriteOnly, PixelFormat.Format1bppIndexed);
// Create destination buffer
imageSize = destinationData.Stride * destinationData.Height;
var destinationBuffer = new byte[imageSize];
var sourceIndex = 0;
var destinationIndex = 0;
var pixelTotal = 0;
byte destinationValue = 0;
var pixelValue = 128;
var height = source.Height;
var width = source.Width;
// Iterate lines
for (var y = 0; y < height; y++)
{
sourceIndex = y * sourceData.Stride;
destinationIndex = y * destinationData.Stride;
destinationValue = 0;
pixelValue = 128;
// Iterate pixels
for (var x = 0; x < width; x++)
{
// Compute pixel brightness (i.e. total of Red, Green, and Blue values) - Thanks murx
// B G R
pixelTotal = sourceBuffer[sourceIndex] + sourceBuffer[sourceIndex + 1] + sourceBuffer[sourceIndex + 2];
if (pixelTotal > threshold)
{
destinationValue += (byte)pixelValue;
}
if (pixelValue == 1)
{
destinationBuffer[destinationIndex] = destinationValue;
destinationIndex++;
destinationValue = 0;
pixelValue = 128;
}
else
{
pixelValue >>= 1;
}
sourceIndex += 4;
}
if (pixelValue != 128)
{
destinationBuffer[destinationIndex] = destinationValue;
}
}
// Copy binary image data to destination bitmap
Marshal.Copy(destinationBuffer, 0, destinationData.Scan0, imageSize);
// Unlock destination bitmap
destination.UnlockBits(destinationData);
// Dispose of source if not originally supplied bitmap
if (source != original)
{
source.Dispose();
}
// Return
return destination;
}
I hate GDI+ exception handling, the only error it fires is A generic error occured in GDI+, Try this
Bitmap source = new Bitmap(0, 0);
using (Graphics g = Graphics.FromImage(source))
{ g.Clear(Color.White);
g.Graphics.DrawImageUnscaled(your original source,0,0);
}

Bitmap manipulation in Windows Phone: How to deal with GetPixel, SetPixel, PixelFormat, etc?

im trying to convert one of fully functional desktop apps to a Windows phone app, i was managed to convert most of the things..but one function is not working due to some syntax error.anyone know replacements for
GetPixel,
FromArgb,
SetPixel,
MemoryStream,
Marshal,
ImageLockMode,
PixelFormat
the code is this
private void tresh()
{
int hight = image1.Source.Height;
int width = image1.Source.Width;
BitmapImage img = new BitmapImage(image1.Source);
BitmapImage newImg = new BitmapImage(width, hight);
int threshold = 0;
for (int i = 0; i < hight; i++)
{
for (int j = 0; j < width; j++)
{
int grayScale = (int)((img.GetPixel(j, i).R * 0.3) + (img.GetPixel(j, i).G * 0.59) + (img.GetPixel(j, i).B * 0.11));
Color nc = Color.FromArgb(grayScale, grayScale, grayScale);
newImg.SetPixel(j, i, nc);
}
}
image1.Source = newImg;
MemoryStream ms = new MemoryStream();
newImg.Save(ms, ImageFormat.Bmp);
byte[] bmpBytes = ms.GetBuffer();
threshold = getOtsuNumber(bmpBytes);
byte[] newBytArr = new byte[bmpBytes.Length];
for (int i = 0; i < bmpBytes.Length; i++)
{
if ((0xFF & bmpBytes[i]) >= threshold)
{
newBytArr[i] = ((byte)255);
}
else
{
newBytArr[i] = ((byte)0);
}
}
BitmapImage oldBmp = newImg;
width = oldBmp.Width;
int height = oldBmp.Height;
BitmapData oldData = oldBmp.LockBits(
new Rectangle(0, 0, oldBmp.Width, oldBmp.Height),
ImageLockMode.WriteOnly,
oldBmp.PixelFormat);
int length = oldData.Stride * oldBmp.Height;
byte[] stream = new byte[length];
Marshal.Copy(oldData.Scan0, stream, 0, length);
oldBmp.UnlockBits(oldData);
BitmapImage bmp = new Bitmap(width, height, oldBmp.PixelFormat);
BitmapData bmpData = bmp.LockBits(
new Rectangle(0, 0, width, height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
for (int n = 0; n < length; n++)
{
if ((0xFF & stream[n]) >= 57)
{
Marshal.WriteByte(bmpData.Scan0, n, ((byte)255));
}
else
{
Marshal.WriteByte(bmpData.Scan0, n, ((byte)0));
}
}
bmp.UnlockBits(bmpData);
image1.Source = bmp;
}
you have to change the type int into byte
By using this WriteableBitmapEx GetPixel and SetPixel method extensions can be used

How can I convert an 8-bit grayscale image into a byte[] array in C#?

How can I put the data of an 8-bit grayscale image into a byte array? I have tried the following code:
private byte[] loadBitmap(string filename, int width, int height)
{
byte[] data = new byte[width * height];
BitmapData bmpData = null;
Bitmap slice = new Bitmap(filename);
Rectangle rect = new Rectangle(0, 0, slice.Width, slice.Height);
bmpData = slice.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
int size = bmpData.Height * bmpData.Stride;
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size);
slice.UnlockBits(bmpData);
return data;
}
But the result of the data array has some errors because of Format8bppIndexed. Any ideas?
I don't know if this can help you but I'll try.
byte[] buffer = null;
System.Drawing.Image newImg = img.GetThumbnailImage(width, height, null, new System.IntPtr());
using (MemoryStream ms = new MemoryStream()) {
newImg.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
}
buffer = ms.ToArray();
It's just a way of what I have already done.
Hope it helps
In my application I need for each pixel a byte that represents the gray values from 0-255.
I have solved my problem with ImageSharp
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
private static byte[] GetImageData(byte[] imageData)
{
using (var image = Image.Load<Rgba32>(imageData))
{
var buffer = new byte[image.Width * image.Height];
var index = 0;
image.ProcessPixelRows(accessor =>
{
for (int y = 0; y < accessor.Height; y++)
{
Span<Rgba32> pixelRow = accessor.GetRowSpan(y);
for (int x = 0; x < pixelRow.Length; x++)
{
ref Rgba32 pixel = ref pixelRow[x];
buffer[index] = (byte)((pixel.R + pixel.G + pixel.B) / 3);
index++;
}
}
});
return buffer;
}
}

C# how to show image in picturebox

I'm trying to display dicom image using openDicom.net. What should i correct here?
openDicom.Image.PixelData obraz = new openDicom.Image.PixelData(file.DataSet);
// System.Drawing.Bitmap obrazek = (Bitmap)Bitmap.FromFile(element);
pictureBox1.Image = obraz;
pictureBox1.Show();
PixelData is not an image. PixelData is raw image information. In my experience, most DICOM files will be using jpeg2000 images. In order to convert them to something usable by a PictureBox, you'll need to convert it to an Image. For raw monochrome types, you can make it into a System.Drawing.Bitmap using the following conversion:
openDicom.Image.PixelData obraz = new openDicom.Image.PixelData(file.DataSet);
Bitmap img = new System.Drawing.Bitmap(obraz.Columns, obraz.Rows, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
int resampleval = (int)Math.Pow(2, (obraz.BitsAllocated - obraz.BitsStored));
int pxCount = 0;
int temp = 0;
try
{
unsafe
{
BitmapData bd = img.LockBits(new Rectangle(0, 0, obraz.Columns, obraz.Rows), ImageLockMode.WriteOnly, img.PixelFormat);
for (int r = 0; r < bd.Height; r++)
{
byte* row = (byte*)bd.Scan0 + (r * bd.Stride);
for (int c = 0; c < bd.Width; c++)
{
temp = PixelData16[pxCount] / resampleval;
while (temp > 255)
temp = temp / resampleval;
row[(c * 3)] = (byte)temp;
row[(c * 3) + 1] = (byte)temp;
row[(c * 3) + 2] = (byte)temp;
pxCount++;
}
}
img.UnlockBits(bd);
}
}
catch
{
img = new Bitmap(10, 10);
}
pictureBox1.Image = img;
pictureBox1.Show();
For other image types, you'll need to do a similar conversion with the appropriate values. This conversion is strictly for monochrome types, and only after they have been converted from jpeg2000 to jpeg. Performing this operation on a jpeg2000 image will give you exactly half of the image filled with static and the other half completely empty.

Categories

Resources