Emgucv 圖像操作筆記


這里記下一些學習過程中的心得和技巧。我用VS2008,C#的平台進行編寫。

1、將圖片載入PictureBox的方法:

Image<Bgr, byte> img = new Image<Bgr, byte>("lena.jpg");

//讀入一張BGR圖像,要將lena.jpg放入DEBUG目錄下。

pictureBox1.Image = img.ToBitmap();

//ToBitmap()將IImage格式轉換為Bitmap格式,便能為PictureBox所用了。或者

下面這樣:

pictureBox1.Image=img.Bitmap;

發現EmguCV的IImage格式確實很強大呀。。。

2、圖片的數據處理

Bgr color=img[y,x];

Img[y,x]=color;

//對Image<Bgr,byte>的第y行第x列進行讀取和寫入操作。

Bgr格式的數據可以通過

Bgr.Blue,Bgr.Green,Bgr.Red訪問

Gray格式的數據可以通過Gray.intensity訪問

所有數據都是可以讀寫的。

3、IntPtr到Image格式的轉換

這個當然在現在的新版本已經用不着這么麻煩了,不過還是把代碼貼過來,感覺

寫的很不錯的說,雖然是unsafe的……

private Image ShowIplImageInWindow(IntPtr src)

        {

            Emgu.CV.Structure.MIplImage img =

(Emgu.CV.Structure.MIplImage)Marshal.PtrToStructure(src,

typeof(Emgu.CV.Structure.MIplImage));

            

            Bitmap disp = new Bitmap(img.width, img.height,

PixelFormat.Format24bppRgb);

            BitmapData bmp = disp.LockBits(new Rectangle(0, 0, img.width,

img.height), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb);

            long linebytes = (img.width * 24 + 31) / 32 * 4;

            unsafe

            {

                byte* pixel = (byte*)bmp.Scan0.ToPointer();

                if (img.nChannels == 3)

                {

                    for (int i = 0; i < img.height; i++)

                    {

                        for (int j = 0, n = 0; j < img.width; j++, n++)

                        {                             byte b = ((byte*)img.imageData + img.widthStep *

i)[3 * j];

                            byte g = ((byte*)img.imageData + img.widthStep *

i)[3 * j + 1];

                            byte r = ((byte*)img.imageData + img.widthStep *

i)[3 * j + 2];

                            *(pixel + linebytes * (i) + n) = b;

                            n++;

                            *(pixel + linebytes * (i) + n) = g;

                            n++;

                            *(pixel + linebytes * (i) + n) = r;

                        }

                    }

                }

                else if (img.nChannels == 1)

                {

                    for (int i = 0; i < img.height; i++)

                    {

                        for (int j = 0, n = 0; j < img.width; j++, n++)

                        {

                            byte g = ((byte*)img.imageData + img.widthStep *

i)[j];

                            *(pixel + linebytes * (i) + n) = g;

                            n++;

                            *(pixel + linebytes * (i) + n) = g;

                            n++;

                            *(pixel + linebytes * (i) + n) = g;

                        }

                    }

                }

                else

                {

                    return null;

                }

            }

            disp.UnlockBits(bmp);

            return (Image)disp;

        }

當然,Emgu還提供了一個巨強大無比的ImageBox,可以在工具欄里直接使用。詳

細介紹在emgu的官網上都有,大家有興趣的自己去看吧

 

終於把之前用OpenCV寫的兩個算法用EmguCV實現了,而且似乎效率還說得過

去,當然了,差不多得比之前慢幾倍哈,這就是效率和便捷的取舍了。 最近主要的兩個程序,一個是兩張圖比較差異度,生成一個灰度圖,然后計算不

同的像素個數;另一個是統計一張圖片中有多少人,用框框圈住就行,然后給個

統計總數。

第一個實現比較簡單,算法比較重要;第二個實現比較麻煩,分類器比較重要,

算法其次了。

首先上第一個程序的核心代碼

            Image<Gray, byte> temp=new

Image<Gray,byte>(back.Bitmap.Width,back.Bitmap.Height);

            for (int i = 0; i < back.Bitmap.Height; i++)

            {

                for (int j = 0; j < back.Bitmap.Width; j++)

                {

                    Bgr backColor = back[i, j];

                    Bgr frontColor = front[i, j];

                    temp[i,j]=new Gray(

                        (Math.Sqrt(backColor.Blue-frontColor.Blue)

                        +Math.Sqrt(backColor.Green-frontColor.Green)

                       

+Math.Sqrt(backColor.Red-frontColor.Red)>0.2)?0:255);

                }

            }

上次講到了,灰度圖的點是Gray格式,BGR當然就是Bgr格式了……

Gray和Bgr都可以直接定義,並且可以按照二維數組從圖中讀取和更改。

每個Image都有一個成員:Bitmap,是將這個圖轉換為Bitmap的數據,這個非

常強大,因為Bigmap就是C#里面的數據類型而與EmguCV無關。

上次提過一句ImageBox,這個是一個非常強大的東西,可以直接將EmguCV支持

的圖像輸出在ImageBox里面,更主要的是,可以有非常強大的右鍵功能,在圖

片框里單擊右鍵可以有幾乎所有圖像處理的基本功能,圖像讀取、圖像smooth,

圖像變換,圖像放縮,圖像存儲等等。不試不知道一試嚇一跳啊~~~

然后就是人數統計的那個程序了:

Image<Bgr, byte> img = new Image<Bgr, byte>("lena.jpg");

        HaarCascade mm = new HaarCascade("data.xml");

        Bgr[] colors = 

        { 

            new Bgr(0, 0, 255), 

            new Bgr(0, 128, 255), 

            new Bgr(0, 255, 255), 

            new Bgr(0, 255, 0), 

            new Bgr(255, 128, 0), 

            new Bgr(255, 255, 0), 

            new Bgr(255, 0, 0), 

            new Bgr(255, 0, 255) }; 上面這堆東西全部是初始化。Image不用講了,HaarCascade就是載入一個分類

器,使用方法非常簡單,一句話的事。可以輸入路徑讀取。至於colors數組純

粹是為了創建幾個框框的顏色防止過於單調……

var faces = img.DetectHaarCascade(

                            mm, 1.1, 2,

                            HAAR_DETECTION_TYPE.DO_CANNY_PRUNING,

                            new Size(30, 30)

                            )[0];

            for (int i = 0; i < faces.Length; i++)

            {

                img.Draw(faces[i].rect, colors[i % 8], 3);

            }

           imageBox1.Image = img;

            label1.Text = "人數是:"+faces.Length.ToString();

這里我們發現,原來每個Image還有一個DetectHaarCascade方法啊~~~很神奇

吧,都把模式識別的東西封裝到如此地步了,我們還用寫什么呢。。。里面的參

數我就不細講了,給出一個表吧。

 

HaarCascade

Haar classifier cascade in internal representation

 

Double

The factor by which the search window is scaled between the

subsequent scans, for example, 1.1 means increasing window by 10%

 

Int32

Minimum number (minus 1) of neighbor rectangles that makes up an

object. All the groups of a smaller number of rectangles than

min_neighbors-1 are rejected. If min_neighbors is 0, the function

does not any grouping at all and returns all the detected candidate

rectangles, which may be useful if the user wants to apply a

customized grouping procedure

 

HAAR_DETECTION_TYPE

Mode of operation. Currently the only flag that may be specified

is CV_HAAR_DO_CANNY_PRUNING. If it is set, the function uses Canny

edge detector to reject some image regions that contain too few or

too much edges and thus can not contain the searched object. The

particular threshold values are tuned for face detection and in this

case the pruning speeds up the processing.

 

Size

Minimum window size. By default, it is set to the size of samples

the classifier has been trained on (~20x20 for face detection) 

The objects detected, one array per channel 然后嘛,就把faces里面的東西搞出來就行啦~~~啦啦啦,太方便了太方便了~~~ 就是這些吧,好困。。。明天又是美好的一天嗯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM