我有Basler acA3800 USB摄像头。
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());
}
此代码部分显示图像自我窗口。
我有拍摄图像的像素数据。原始图像很好,但当我将其转换为图像时,它会损坏。这是我的转换功能。
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;
}
我认为这是关于像素类型的。我选择了PixelFormat.Format8bppIndexed的像素格式。其他人没有工作。
MessageBox.Show(grabResult.PixelTypeValue.ToString());
此消息框为我提供了pixeltype。它说&#34; BayerBG8&#34;。这是什么意思?我该怎么做才能获得清晰的图像?
答案 0 :(得分:2)
你得到的奇怪的颜色是因为Format8bppIndexed
被调色,你永远不会编辑调色板,这意味着它保留了默认生成的Windows调色板。但在你的情况下,这个调色板是无关紧要的,因为图像不是 8位索引格式;需要对其进行处理以将其转换为RGB。
快速google for BayerBG8让我this page。那里的拜耳部分表明,在图像上使用特定图案的指数为R,G和B是一种相当特殊的转换。
维基百科有a whole article关于如何处理这些内容的问题,但this YouTube video显示了基本内容:
请注意,这是一个滑动窗口;对于第一个像素,颜色为
R G G B
但是对于第二个像素,它们将是
G R B G
并且对于一行,第一行将使用
G B R G
由于每行上的最后一个像素和最后一行的所有像素都不具备所需的相邻数据,因此您最终得到的图像的宽度和宽度都比给定尺寸小一个像素。获取他们的全像素数据。显然有更先进的算法可以解决这个问题,但对于这种方法,我只是简单介绍一下基本的滑动窗口方法。
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;
}
参数greenFirst
和blueRowFirst
表示绿色是否是图像上第一个遇到的像素,以及蓝色像素是否位于第一行或第二行。对于你的&#34; BG&#34;格式,这两个都应该是假的。
根据调整后的宽度,高度和步幅,您可以使用已使用的方法将其转换为新图像,但使用Format24bppRgb
作为像素格式。
我个人使用一种更先进的方法,将输入步幅考虑在内并处理索引内容。如果您对此感兴趣,请使用该方法can be found here。
请注意,上面的去马赛克方法是非常基本,并会显示many of the expected artifacts。有更先进的方法来分析数据并根据图像的拍摄方式获得更准确的结果,但它可能会花费你很多研究来计算所有这些并自己实现它。
这是我做的一个小测试,从a Bayer-filtered image I found online开始,我将其转换为8位数组(此处显示为灰度图像)。正如您所看到的,我自己的去马赛克(第二张图片)远不如他们从中得到的修正版本(第三张图片)准确。