C# 處理映像三種方法對比

來源:互聯網
上載者:User

標籤:

C#本身內建有一定的影像處理能力,即使在不依賴Emgu CV的情況下,也是有很大的潛質的。

不過,最近在處理大量圖片時,發現圖片數量較少時,處理本身所帶來的延時不會讓人敏感,但是數量較大時,程式花費大量時間在預先處理圖片上,導致程式很容易誤判線程時延過大,導致誤判程式異常。對於這個問題苦惱很久,畢竟不是CS專業出身,對於影像處理以及一些演算法和庫的運用上感到畢竟吃力。

今天在閱讀了一些數位影像處理的書之後感到收益很大,現在來做點實驗對照一下之前自己的錯誤在哪裡。

之前看MS的C#API時候發現有一個Graphics挺適合我現在使用,於是便二話不說開幹,今天才發現越來封裝的太好,反而會帶來許多拖累,不如操起指標暢快的運行。

不多說,實驗對比的是Graphics、操作記憶體、操作指標三者在效能上差距。

實驗內容:對同一張照片進行灰階處理,直接看三者之間延時有多大

 

1.實驗基本情境,比較醜陋,就湊合看著。。。

2.提取像素Button中,調用Graphics灰階化處理

private void button2_Click(object sender, EventArgs e)        {            if (curBitMap1 != null)            {                Color curColor;                int ret;                //個人已耗用時間判斷類                GetRunTime getRunTime = new GetRunTime();                //stopWatch啟動                getRunTime.Start();                //Graphics//灰階化                for (int i = (int)(0); i < (int)(curBitMap1.Width ); i++)                {                    for (int j = 0; j < curBitMap1.Height; j++)                    {                        //擷取像素                        curColor = curBitMap1.GetPixel(i, j);                        //擷取RGB                        ret = (int)(curColor.R * 0.299 + curColor.G * 0.587 + curColor.B * 0.114);                        //設定像素                        curBitMap1.SetPixel(i, j, Color.FromArgb(ret, ret, ret));                    }                }                Invalidate();                labelGetPixel.Text = "提取像素花費時間:" + getRunTime.getRunTime() + "ms";            }        }

  

3.記憶體法Button中,直接複製資料到記憶體,直接操作

private void button5_Click(object sender, EventArgs e)        {            if (curBitMap2 != null)            {                GetRunTime getRunTime = new GetRunTime();                getRunTime.Start();                Rectangle rect = new Rectangle(0, 0, curBitMap2.Width, curBitMap2.Height);                //以讀寫方式鎖定位元影像                System.Drawing.Imaging.BitmapData bmpData =                    curBitMap2.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, curBitMap2.PixelFormat);                //首地址                IntPtr ptr = bmpData.Scan0;                //24位bmp的總位元組數                int bytes = curBitMap2.Width * curBitMap2.Height * 3;                byte[] rgbValues = new byte[bytes];                //複製被鎖定的映像到rgbValues                System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);                double colorTemp = 0;                //灰階化                for (int i = 0; i < bmpData.Height; i++)                {                    for (int j = 0; j < bmpData.Width * 3; j+=3)                    {                        //跳過空白塊                        colorTemp = rgbValues[i * bmpData.Stride + j + 2] * 0.299                             + rgbValues[i * bmpData.Stride + j + 1] * 0.587                             + rgbValues[i * bmpData.Stride + j] * 0.114;                        rgbValues[i * bmpData.Stride + j + 2]                             = rgbValues[i * bmpData.Stride + j + 1]                             = rgbValues[i * bmpData.Stride + j] = (byte)colorTemp;                    }                }                //複製回位元影像                System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);                curBitMap2.UnlockBits(bmpData);                Invalidate();                labelCaChe.Text = "提取像素記憶體法花費時間:" + getRunTime.getRunTime() + "ms";            }        }

  

4.指標法Button中,直接複製資料到記憶體,指標操作 

private void button6_Click(object sender, EventArgs e)        {            GetRunTime getRunTime = new GetRunTime();            getRunTime.Start();            Rectangle rect = new Rectangle(0, 0, curBitMap3.Width, curBitMap3.Height);            //以讀寫方式鎖定位元影像            System.Drawing.Imaging.BitmapData bmpData =                    curBitMap3.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, curBitMap3.PixelFormat);            byte temp = 0;            unsafe            {                //首地址                byte* ptr = (byte*)(bmpData.Scan0);                //灰階化                for (int i = 0; i < bmpData.Height; i++)                {                    for (int j = 0; j < bmpData.Width;j++ )                    {                        temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);                        ptr[0] = ptr[1] = ptr[2] = temp;                        ptr += 3;                    }                    //跳過空白塊                    ptr += bmpData.Stride - bmpData.Width * 3;                }            }            //解鎖位元影像            curBitMap3.UnlockBits(bmpData);            Invalidate();            labelPoint.Text = "提取像素記憶體法花費時間:" + getRunTime.getRunTime() + "ms";        }

5,簡單完善一下就開始開啟圖片看看已耗用時間之間的對比吧

總結:雖然電腦爛,但還是看得出三者之間的差距吧。複製進記憶體直接操作和用指標操作都是極大的提高效率,如果處理一張圖片節約60ms,那處理大量的圖片時候將會節約多少時間?所以今後處理映像的時候,如果不用Emgu,盡量也別用Graphics,還是自己動手操作記憶體。(肯定會有人說,你為毛不去用C++,好吧,我其實就是在黑Graphics,你咬我呀~)

 

C# 處理映像三種方法對比

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.