How to go through each and every pixel of an image efficiently?
專案名稱: SpeedUpPixelAcess
Unmaged code:
第一種方式: MIplImage
(1) MIplImage: managed structure equivalent to IplImage
利用Marshal.PtrToStructure指向來源影像指標img.Ptr, 資料結構型態為 MIplImage,
記得前面強迫轉型(MIplImage)
(2) IntPtr intPtr = mImg.ImageData;
C#利用IntPtr指標型態指向 ImageData: 存放影像像素資料起始位置
(3) byte* ptr = (byte*)intPtr.ToPointer();
影像像素資料為byte, (3)表示將C# intPtr格式轉成C++的byte*指標格式
(4) 可以將(2)(3)變成byte* ptr = (byte*)mImg.ImageData.ToPointer();
再次強調 mImg資料型態為MIplImage
private static void RemoveBGUnmanagedVersion1(Image<Bgr, byte> img)
{
MIplImage mImg = (MIplImage)Marshal.PtrToStructure(img.Ptr, typeof(MIplImage));
int hei = img.Height;
int wid = img.Width;
int i, j;
unsafe
{
//IntPtr intPtr = mImg.ImageData;
//byte* ptr = (byte*)intPtr.ToPointer();
byte* ptr = (byte*)mImg.ImageData.ToPointer();
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
ptr[0] = 0; // remove Blue channel
ptr++;
ptr[0] = 0; // remove Green channel
ptr++;
ptr++; // do nothing to Red channel
}
}
}
第二種方式: MCvMat
類似第一種方法MIplImage
(1) MCvMat: Mananged structure equivalent to CvMat
利用Marshal.PtrToStructure指向來源影像指標img.Mat.Ptr, 資料結構型態為 MCvMat,
記得前面強迫轉型(MCvMat)
(2) byte* ptr = (byte*)mImg.Data.ToPointer(); 再次強調:其中mImg資料型態為MCvMat
影像像素資料為byte, (3)表示將C# intPtr格式轉成C++的byte*指標格式
private static void RemoveBGUnmanagedVersion12(Image<Bgr, byte> img)
{
MCvMat mImg = (MCvMat)Marshal.PtrToStructure(img.Mat.Ptr, typeof(MCvMat));
int hei = img.Height;
int wid = img.Width;
int i, j;
unsafe
{
byte* ptr = (byte*)mImg.Data.ToPointer();
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
ptr[0] = 0; // remove Blue channel
ptr++;
ptr[0] = 0; // remove Green channel
ptr++;
ptr++; // do nothing to Red channel
}
}
}
第三種方式: BitmapData
(1) 採用Image裡面成員Bitmap屬性, 搭配BitmapData資料格式進行感性區域(ROI)內的像素操作, 一般來說
ROI即原始影像大小new Rectangle(0, 0, wid, hei)
(2) BitmapData bmpData = bmp.LockBits(…) 利用LockBits將記憶體中的資料鎖住, 並回傳BitmapData
(3) byte* ptr = (byte*)bmpData.Scan0.ToPointer(); 取得影像陣列起始指標位址,即Scan0.ToPointer
(4) 接下來就可以針對BGR進行讀寫囉
(5) 全部完成後, 將記憶體中資料解鎖: bmp.UnlockBits(bmpData);
private static void RemoveBGUnmanagedVersion2(Image<Bgr, byte> img)
{
int hei = img.Height;
int wid = img.Width;
Bitmap bmp = img.Bitmap;
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, wid, hei), ImageLockMode.ReadOnly, img.Bitmap.PixelFormat);
int i, j;
unsafe
{
//IntPtr bmpDataScan0 = bmpData.Scan0;
//byte* ptr = (byte*)bmpDataScan0.ToPointer();
byte* ptr = (byte*)bmpData.Scan0.ToPointer();
for (j = 0; j < hei; j++)
{
for (i = 0; i < wid; i++)
{
try
{
ptr[0] = 0; // remove Blue channel
ptr++;
ptr[0] = 0; // remove Green channel
ptr++;
ptr++; // do nothing to Red channel
}
catch (Exception exception) { MessageBox.Show(exception.Message); }
}
}
try
{
bmp.UnlockBits(bmpData);
}
catch (Exception exception) {
MessageBox.Show(exception.Message);
}
}
}
==========================================================
Managed code:
第一種方式
像素排列方式: img.Data[row, column, channel]
private static void RemoveBGChannelsMangedVersion1(Image<Bgr, byte> img)
{
int hei = img.Height;
int wid = img.Width;
int i, j;
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
img.Data[j, i, 0] = 0; // remove Blue channel
img.Data[j, i, 1] = 0; // remove Green channel
}
}
第二種方式
private static void RemoveBGChannelsMangedVersion2(Image<Bgr, byte> img)
{
int hei = img.Height;
int wid = img.Width;
int i, j;
byte[, ,] pImg = img.Data;
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
pImg[j, i, 0] = 0; // remove Blue channel
pImg[j, i, 1] = 0; // remove Green channel
//pImgCopy[j, i, 2];
}
}
==========================================================
彩色轉灰階
private static void RGB2Gray(Bitmap src)
{
int wid = src.Width;
int hei = src.Height;
int i, j;
BitmapData bmpData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, src.PixelFormat);
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
double gray;
for (j = 0; j < hei; j++)
for (i = 0; i < wid; i++)
{
gray = 0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0];
ptr[0] = ptr[1] = ptr[2] = (byte)gray;
ptr+=3;
}
}
src.UnlockBits(bmpData);
}
pixel[i] – pixel[i+1] + 128
int wid = src.Width;
int hei = src.Height;
int i, j;
BitmapData bmpData = src.LockBits(new Rectangle(0, 0, src.Width, src.Height), ImageLockMode.ReadWrite, src.PixelFormat);
unsafe
{
byte* ptr = (byte*)bmpData.Scan0;
byte* ptrNext = ptr+3;
double gray, grayNext;
int total = hei * wid;
//for (j = 0; j < hei; j++)
// for (i = 0; i < wid; i++)
for(i=0; i<total-1;i++)
{
gray = 0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0];
grayNext = 0.299 * ptrNext[2] + 0.587 * ptrNext[1] + 0.114 * ptrNext[0];
ptr[0] = ptr[1] = ptr[2] = (byte)(gray - grayNext+128);
ptr += 3;
ptrNext = ptr + 3;
}
}
src.UnlockBits(bmpData);
參考資料:
留言列表