Basler USB Camera字节缓冲区到图像转换 [英] Basler USB Camera byte buffer to image conversion

查看:724
本文介绍了Basler USB Camera字节缓冲区到图像转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有Basler acA3800 USB相机。

  IGrabResult grabResult = camera.StreamGrabber.RetrieveResult(5000,TimeoutHandling.ThrowException); 
//图像成功抓取了吗?
if(grabResult.GrabSucceeded)
{
byte [] buffer = grabResult.PixelData as byte [];
ImageWindow.DisplayImage(0,grabResult);

pictureBox1.Image = ImageFromRawBgraArray(buffer,3840,2748,PixelFormat.Format8bppIndexed);
MessageBox.Show(grabResult.PixelTypeValue.ToString());
}

此代码部分显示图像自我窗口。



我有拍摄图像的像素数据。原始图像很好,但当我将其转换为图像时,它会损坏。这是我的转换函数。

  public Image ImageFromRawBgraArray(byte [] arr,int width,int height,PixelFormat pixelFormat)
{
var output = new Bitmap(width,height,pixelFormat);
var rect = new Rectangle(0,0,width,height);
var bmpData = output.LockBits(rect,ImageLockMode.ReadWrite,output.PixelFormat);

//逐行复制
var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat)/ 8;
var ptr = bmpData.Scan0;
for(var i = 0; i< height; i ++)
{
Marshal.Copy(arr,i * arrRowLength,ptr,arrRowLength);
ptr + = bmpData.Stride;
}

output.UnlockBits(bmpData);
返回输出;
}





我认为它与像素类型有关。我选择了PixelFormat.Format8bppIndexed的像素格式。其他的不工作。

  MessageBox.Show(grabResult.PixelTypeValue.ToString()); 

此消息框为我提供了pixeltype。它说BayerBG8。这是什么意思?我该怎么做才能获得清晰的图像?

解决方案

你得到的奇怪颜色是因为 Format8bppIndexed 是调色板,您永远不会编辑调色板,这意味着它会保留默认生成的Windows调色板。但在你的情况下,这个调色板是无关紧要的,因为图像不是 8位索引格式;它需要被处理才能将其转换为RGB。



快速google for BayerBG8让我,但方法。



<请注意,上面的去马赛克方法是非常基本的,并将显示许多预期的文物。有更先进的方法来分析数据,并根据图像的拍摄方式得到更准确的结果,但是你可能需要花费大量的研究来计算出所有这些并自己实现它。



这是我做过的一个小测试,从我在网上找到的拜耳滤波图像,我将其转换为8位数组(此处显示为灰度图像)。正如你所看到的,我自己的去马赛克(第二张图片)远不如他们从中得到的修正版本(第三张图片)准确。




I have Basler acA3800 USB camera.

            IGrabResult grabResult = camera.StreamGrabber.RetrieveResult(5000, TimeoutHandling.ThrowException);
            // Image grabbed successfully?
            if (grabResult.GrabSucceeded)
            {
                byte[] buffer = grabResult.PixelData as byte[];
                ImageWindow.DisplayImage(0, grabResult);

                pictureBox1.Image = ImageFromRawBgraArray(buffer,3840,2748,PixelFormat.Format8bppIndexed);
                MessageBox.Show(grabResult.PixelTypeValue.ToString());
            }

This code section shows image self window.

I have pixel data of captured image. Original image is good but when I convert it to Image, it corrupt. And here is my conversion function.

    public Image ImageFromRawBgraArray(byte[] arr, int width, int height, PixelFormat pixelFormat)
    {
        var output = new Bitmap(width, height, pixelFormat);
        var rect = new Rectangle(0, 0, width, height);
        var bmpData = output.LockBits(rect, ImageLockMode.ReadWrite, output.PixelFormat);

        // Row-by-row copy
        var arrRowLength = width * Image.GetPixelFormatSize(output.PixelFormat) / 8;
        var ptr = bmpData.Scan0;
        for (var i = 0; i < height; i++)
        {
            Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);
            ptr += bmpData.Stride;
        }

        output.UnlockBits(bmpData);
        return output;
    }

I think it is about pixel type. I have selected pixel format of PixelFormat.Format8bppIndexed. The others is not working.

                MessageBox.Show(grabResult.PixelTypeValue.ToString());

This messagebox gives me the pixeltype. and it says "BayerBG8". What does it mean? What should I do to get clear image?

解决方案

The odd colours you are getting are because Format8bppIndexed is paletted, and you never edit the palette, meaning it retains the default generated Windows palette. But in your case, this palette is irrelevant, because the image is not an 8-bit indexed format; it needs to be processed to convert it to RGB.

A quick google for BayerBG8 got me this page. The Bayer section there shows it's a rather peculiar transformation to use specifically patterned indices on the image as R, G and B.

Wikipedia has a whole article on how this stuff is generally processed, but this YouTube video shows the basics:

Note that this is a sliding window; for the first pixel, the colours are

R G
G B

but for the second pixel, they'll be

G R
B G

and for one row down, the first one will use

G B
R G

You'll end up with an image that is one pixel less wide and high than the given dimensions, since the last pixel on each row and all pixels on the last row won't have the neighbouring data needed to get their full pixel data. There are apparently more advanced algorithms to get around that, but for this method I'll just go over the basic sliding window method.

public static Byte[] BayerToRgb(Byte[] arr, ref Int32 width, ref Int32 height, ref Int32 stride, Boolean greenFirst, Boolean blueRowFirst)
{
    Int32 actualWidth = width - 1;
    Int32 actualHeight = height - 1;
    Int32 actualStride = actualWidth*3;
    Byte[] result = new Byte[actualStride*actualHeight];
    for (Int32 y = 0; y < actualHeight; y++)
    {
        Int32 curPtr = y*stride;
        Int32 resPtr = y*actualStride;
        Boolean blueRow = y % 2 == (blueRowFirst ? 0 : 1);
        for (Int32 x = 0; x < actualWidth; x++)
        {
            // Get correct colour components from sliding window
            Boolean isGreen = (x + y) % 2 == (greenFirst ? 0 : 1);
            Byte cornerCol1 = isGreen ? arr[curPtr + 1] : arr[curPtr];
            Byte cornerCol2 = isGreen ? arr[curPtr + stride] : arr[curPtr + stride + 1];
            Byte greenCol1 = isGreen ? arr[curPtr] : arr[curPtr + 1];
            Byte greenCol2 = isGreen ? arr[curPtr + stride + 1] : arr[curPtr + stride];
            Byte blueCol = blueRow ? cornerCol1 : cornerCol2;
            Byte redCol = blueRow ? cornerCol2 : cornerCol1;
            // 24bpp RGB is saved as [B, G, R].
            // Blue
            result[resPtr + 0] = blueCol;
            // Green
            result[resPtr + 1] = (Byte) ((greenCol1 + greenCol2)/2);
            // Red
            result[resPtr + 2] = redCol;
            curPtr++;
            resPtr+=3;
        }
    }
    height = actualHeight;
    width = actualWidth;
    stride = actualStride;
    return result;
}

The parameters greenFirst and blueRowFirst indicate whether green is the first encountered pixel on the image, and whether the blue pixels are on the first or second row. For your "BG" format, both of these should be false.

From the result of this, with the adjusted width, height and stride, you can convert that to a new image using the method you already used, but with Format24bppRgb as pixel format.

Personally I use a somewhat more advanced method that takes the input stride into account and can handle indexed content. If you're interested, that method can be found here.

Note that the demosaicing method above is very basic, and will show many of the expected artifacts. There are more advanced methods out there to analyse the data and get more accurate results based on how the image was taken, but it'll probably cost you quite some research to figure all that out and implement it yourself.

Here's a little test I did, starting from a Bayer-filtered image I found online which I converted to an 8-bit array (shown here as grayscale image). As you can see, my own demosaicing (second image) is far less accurate than the corrected version they got out of it (third image).

这篇关于Basler USB Camera字节缓冲区到图像转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆