I have a monochrome camera in my project that I read images of at either 8bit/16bit depth. I'm using EmguCV library to create a Mat object out of byte array that I read off the camera and want to display the images on an EmguCV PictureBox control.
When I work in 8bit mode everything looks fine, but when I try to work in 16bit the picture box display turn black. If I save the mat object of the 16bit image to a file, the image looks good, so I'm not sure what the issue may be.
Here is the code I'm using:
//This function run on a separate thread and continuously acquires frames from the camera.
private int CatureVideoWorker()
{
while(captureImages)
{
//buffer address is pinned using GCMarshal to variable called pinnedImgBuffer.
buffer = readFrameFromCamera();
//acquire exclusive lock so GUI thread won't access mat object while it's being written to.
lock (syncRoot) {
lastFrame.Dispose();
if (8bitMode == true)
lastFrame = new Mat(_height, _width, Emgu.CV.CvEnum.DepthType.Cv8U, 1, pinnedImgBuffer.AddrOfPinnedObject(), _width);
else
lastFrame = new Mat(_height, _width, Emgu.CV.CvEnum.DepthType.Cv16U, 1, pinnedImgBuffer.AddrOfPinnedObject(), _width * 2);
}
}
return 1;
}
//Timer event that run on the main GUI thread ~33ms to load the lastFrame to the Emgu PictureBox.
private void tmrCaptureFrame_Tick(object sender, EventArgs e)
{
//make sure to get exclusive lock so the mat object won't get written/disposed while
//cloning it to the picture box.
lock (syncRoot)
{
pbx.Image = lastFrame.Clone();
}
}
As mentioned, when in 8bit mode, the picture box show a live view from the camera but when switching to 16bit the picture box is all black.
Saving the Mat object to a file in either 8bit/16bit mode works fine and the16bit image looks good when opening the file in msPaint, so not sure what the issue with the picture box.
Few software can display 16 bit images well. Most seem to just take the upper 8 bits, and this only works well if the max value in the image is ushort.MaxValue
. If you are saving a 16bit image to a file and it looks good in msPaint, I would double check that it is actually an 16-bit image. Many pieces of software tend to silently convert high dynamic range images to 8-bits. You need to be careful to ensure all components in a processing chain can handle 16-bit images.
In any case, 16 bit images need to be converted to 8 bits to be displayed. A fairly simple way to do this is to do a linear scaling between the min and max values. EmguCV has this in the normalize function
normalize(src, dst, NORM_MINMAX, 0, 255)
More advanced method would be to scale between say the 0.01 and 0.99 percentile pixel values. Or to do some limited form of historgram equalization.