問題描述
我有 Basler acA3800 USB 相機.
IGrabResult grabResult = camera.StreamGrabber.RetrieveResult(5000, TimeoutHandling.ThrowException);//圖片抓取成功?如果(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 = 寬度 * Image.GetPixelFormatSize(output.PixelFormat)/8;var ptr = bmpData.Scan0;for (var i = 0; i <高度; i++){Marshal.Copy(arr, i * arrRowLength, ptr, arrRowLength);ptr += bmpData.Stride;}輸出.UnlockBits(bmpData);返回輸出;}
我認為這與像素類型有關.我選擇了 PixelFormat.Format8bppIndexed 的像素格式.其他的不工作.
MessageBox.Show(grabResult.PixelTypeValue.ToString());
這個消息框給了我像素類型.上面寫著BayerBG8".這是什么意思?我應該怎么做才能獲得清晰的圖像?
你得到的奇怪顏色是因為 Format8bppIndexed
是調色板,你從不編輯調色板,這意味著它保留了默認生成的 Windows調色板.但在您的情況下,此調色板無關緊要,因為圖像 不是 8 位索引格式;需要對其進行處理以將其轉換為 RGB.
BayerBG8 的快速 google 找到了我介紹這些內容的一般處理方式,但 .
請注意,上面的去馬賽克方法非常基本,并且會顯示 許多預期的工件.有更先進的方法可以分析數據并根據圖像的拍攝方式獲得更準確的結果,但您可能需要進行大量研究才能弄清楚所有這些并自己實施.
這是我做的一個小測試,從 我在網上找到的經過拜耳過濾的圖像(第一張圖像),我將其轉換為 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 (first image) which I converted to an 8-bit array (shown here as grayscale; second image). As you can see, my own demosaicing (third image) is far less accurate than the corrected version they got out of it (fourth image), and, notably, is one pixel smaller and thus shows a white border.
(Note that, unlike the examples above, this image starts with a green pixel, meaning the parameters to decode it had to be adjusted)
這篇關于Basler USB Camera字節緩沖區到圖像的轉換的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!