(一) Bitmap

1. 先new一塊Bitmap格式記憶體

2. 再利用SetPixel(…) 設定像素, 這是比較沒有效率但卻簡單直覺的函式!

private static void BitmapBW()
{
Bitmap source = new Bitmap(3000, 2000, PixelFormat.Format32bppArgb);
for (int h = 0; h < source.Height; h++)
for (int w = 0; w < source.Width; w++)
{
source.SetPixel(w, h, Color.White);
}
}

測試效能

image

3. 利用MemoryStream加速

3.1 bmp.Save  成MemorStream串流形式

3.2 再利用byte[] byteArray 參考 ms.ToArray()

3.3 接著就可以利用一維陣列設定像素, 前54 bytes為header information

3.4 利用byteArray初始化MemoryStream變數ms

3.5 MemoryStream資料也可以初始化Bitmap物件

private static void BitmapMatrixToArray()
{
Bitmap bmp = new Bitmap(3000, 2000);
//------------------------------------
MemoryStream ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Bmp);
byte[] byteArray = ms.ToArray();
int len = bmp.Width*bmp.Height;
for (int i = 0; i < len; i++)
{
byteArray[54 + i] = 255;
}
//------------------------------------
ms = new MemoryStream(byteArray);
bmp = new Bitmap(ms);
}

測試效能, 一維陣列速度果然快

image

4. BitmapData 二維陣列操作Bitmap, 速度較一維陣列差一些

4.1 bmp.LockBits 第一個參數相當於ROI(感興趣區域)

4.2 利用IntPtr 指標方式指向該ROI的起始記憶體位址

4.3 資料32bppArgb, 第一個為透明度alpha, 接下三個分別為RGB

private static void ImagePtr()
{
Bitmap bmp = new Bitmap(3000, 2000,PixelFormat.Format32bppArgb);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
IntPtr bmpScan = bmpData.Scan0;
unsafe
{
byte* ptr = (byte*)bmpScan.ToPointer();
int i, j;

for(j=0; j<bmp.Height; j++)
for (i = 0; i < bmp.Width; i++)
{
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
/*
*(ptr++) = 255; // A
*(ptr++) = 255; // R
*(ptr++) = 255; // G
*(ptr++) = 255; // B
*/
}
}
}

測試效能

image


(二) Image<Bgr, byte>   <----Emgu CV彩色影像格式

1. 先new一塊彩色影像

2. 支援陣列索引方式直接設定像素

private static void EmguCVImageBW()
{
Image<Bgr, byte> img = new Image<Bgr,byte>(3000,2000);
Bgr color = new Bgr(255, 255, 255);
for (int h = 0; h < img.Height; h++)
for (int w = 0; w < img.Width; w++)
{
img[h, w] = color;
}
}

測試效能

image

3. 利用Parrell 迴圈加速

private static void ParallelBW()
{
Image<Bgr, byte> img = new Image<Bgr,byte>(3000,2000);
Bgr color = new Bgr(255, 255, 255);
Parallel.For(0, img.Height, h =>
{
Parallel.For(0, img.Width, w =>
{
img[h, w] = color;
});
});
}

測試效能

image

4. 試試看另一種 img.Data[i, j, channel]寫法

private static void ImageData()
{
Image<Bgr, byte> img = new Image<Bgr, byte>(3000, 2000);
int i, j;
for(j=0; j<img.Height; j++)
for (i = 0; i < img.Width; i++)
{
img.Data[j, i, 0] = 255;
img.Data[j, i, 1] = 255;
img.Data[j, i, 2] = 255;
}
}

測試效能, 基本上img.Data[i, j, channel]和

img[i, j].Blue  

img[i, j].Green

img[i, j].Red  效能差不多

image

5. MIplImage +指標方式

5.1 在C#用到指標就常看到 Marshal

private static void ImageData2()
{
Image<Bgr, byte> img = new Image<Bgr, byte>(3000, 2000);
MIplImage iplImage = (MIplImage)Marshal.PtrToStructure(img.Ptr, typeof(MIplImage));
unsafe
{
int i, j;
byte* ptr = (byte*)iplImage.ImageData;
int hei = img.Height;
int wid = img.Width;
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
}
}
}

測試效能: 很棒

image

6. MCvMat+指標方式

6.1 一樣是用Marshal.PtrToStructure

private static void ImageData3()
{
Image<Bgr, byte> img = new Image<Bgr, byte>(3000, 2000);
MCvMat mImg = (MCvMat)Marshal.PtrToStructure(img.Mat.Ptr, typeof(MCvMat));
unsafe
{
int i, j;
byte* ptr =(byte*)mImg.Data.ToPointer();
int hei = img.Height;
int wid = img.Width;
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
ptr[0] = 255;
ptr++;
}

}
}

測試效能: 很棒

image


參考資料:

1. Emgu CV: 基礎影像容器Mat

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()