close

專案名稱:MatStructureEx


using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Emgu.CV.Util;

宣告

Image<Bgr, byte> img;

開啟一張圖檔

using (OpenFileDialog ofd = new OpenFileDialog())
{
if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
img = new Image<Bgr, byte>(ofd.FileName);
imageBox1.Image = img;
}
}

image

======================================

img內每一點像素值儲存在Mat資料結構內:

宣告一個MCvMat資料格式: managed structure eqivalent to CvMat


MCvMat mImg = (MCvMat)Marshal.PtrToStructure(img.Ptr, typeof(MCvMat));
byte* ptr = (byte*)mImg.Data.ToPointer();
                

private void DispMCvMatInfo(Mat img, DataGridView dgv, int rows, int cols)
{
int i, j;
unsafe
{

MCvMat mImg = (MCvMat)Marshal.PtrToStructure(img.Ptr, typeof(MCvMat));
byte* ptr = (byte*)mImg.Data.ToPointer();
byte Red, Green, Blue;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
Blue = ptr[0];
ptr++;
Green = ptr[0];
ptr++;
Red = ptr[0];
dgv[j, i].Value = string.Format("({0},{1} = ({2},{3},{4})", i + 1, j + 1, Red, Green, Blue);
ptr++;
}

}

}
}

主程式呼叫DispMCvMatInfo(),

可以將像素顯示在dataGridView1元件上, 語法如下:

DispMCvMatInfo(img.Mat, dataGridView1, rows, cols);

image

===================================

利用Split()函式抽取R,G,B

可以宣告一個Mat陣列, 其中

Mat[] mat = img.Mat.Split();

mat[0]: blue channel

mat[1]: green channel

mat[2]: red channel

Mat[] mat = img.Mat.Split();

可以將像素R,G,B顯示在dataGridView1元件上, 語法如下:

DispRGBMatInfo(mat[2], mat[1], mat[0], dataGridView1, rows, cols);

private void DispRGBMatInfo(Mat RedMat, Mat GreenMat, Mat BlueMat, DataGridView dgv, int rows, int cols)
{
int i, j;
unsafe
{
MCvMat MCvMatRed = (MCvMat)Marshal.PtrToStructure(RedMat.Ptr, typeof(MCvMat));
MCvMat MCvMatGreen = (MCvMat)Marshal.PtrToStructure(GreenMat.Ptr, typeof(MCvMat));
MCvMat MCvMatBlue = (MCvMat)Marshal.PtrToStructure(BlueMat.Ptr, typeof(MCvMat));
byte* pRed = (byte*)MCvMatRed.Data.ToPointer();
byte* pGreen = (byte*)MCvMatGreen.Data.ToPointer();
byte* pBlue = (byte*)MCvMatBlue.Data.ToPointer();

byte red, green, blue;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
red = pRed[0];
green = pGreen[0];
blue = pBlue[0];
pRed++;
pGreen++;
pBlue++;
dgv[j, i].Value = string.Format("({0},{1} = ({2},{3},{4})", i + 1, j + 1, red, green, blue);
}
}
}
}

Split()可以用上面提到Mat陣列, 也可以用Image<Gray, byte>陣列去接收

Mat[] mat = img.Mat.Split();

改成

Image<Gray, byte>[] channels = img.Split();

imageBox2.Image = channels[2];
imageBox3.Image = channels[1];
imageBox4.Image = channels[0];

Red channel intensity

image

Blue channel intensity

image

Green channel intensity

image

如果要將R,G,B灰階強度改成對應紅色colormap,綠色colormap,藍色colormap顯示呢?

GetRedChannel();

image
GetGreenChannel();

image
GetBlueChannel();

image

以GetRedChannel為例,

1. 利用img.Split()先丟到channels

2. 將不感興趣的channel設定為零

3. 宣告一個VectorofMat資料型態, 可以輸入三個Gray level的資料,

即VectorofMat vm = new VectorofMat(channels[0].Mat, channels[1].Mat, channels[2].Mat)

其中0,1 channel已經被設定為0

private Image<Gray, byte>[] GetRedChannel()
{
// remove blue and green channels, ie. only red channel is saved
int[] zeroCHs = new int[2] { 0, 1 };

Image<Gray, byte>[] channels;
Mat outMat = new Mat();
channels = img.Split(); // img: original image(color)
for(int i=0; i<2; i++)
channels[ zeroCHs[i] ].SetZero();

using (VectorOfMat vm = new VectorOfMat(channels[0].Mat, channels[1].Mat, channels[2].Mat))
{
CvInvoke.Merge(vm, outMat);
}
imageBox2.Image = outMat;
return channels;
}

private Image<Gray, byte>[] GetGreenChannel()
{
// remove blue and red channels, ie. only green channel is saved
int[] zeroCHs = new int[2] { 0, 2 };

Image<Gray, byte>[] channels;
Mat outMat = new Mat();
channels = img.Split(); // img: original image(color)
for (int i = 0; i < 2; i++)
channels[zeroCHs[i]].SetZero();

using (VectorOfMat vm = new VectorOfMat(channels[0].Mat, channels[1].Mat, channels[2].Mat))
{
CvInvoke.Merge(vm, outMat);
}
imageBox3.Image = outMat;
return channels;
}

private Image<Gray, byte>[] GetBlueChannel()
{
// remove green and red channels, ie. only blue channel is saved
int[] zeroCHs = new int[2] { 1, 2 };

Image<Gray, byte>[] channels;
Mat outMat = new Mat();
channels = img.Split(); // img: original image(color)
for (int i = 0; i < 2; i++)
channels[zeroCHs[i]].SetZero();

using (VectorOfMat vm = new VectorOfMat(channels[0].Mat, channels[1].Mat, channels[2].Mat))
{
CvInvoke.Merge(vm, outMat);
}
imageBox4.Image = outMat;
return channels;
}

=========================================

image

彩色影像整張進行每個像素點簡單減法運算

blue channel – 10

green channel – 20

red channel - 255

image

Mat dstMat = new Mat();

Image<Gray, byte>[] channels;
channels = img.Split();
channels[0] -= 10;
channels[1] -= 20;
channels[2] -= 255;
using (VectorOfMat vm = new VectorOfMat(channels[0].Mat, channels[1].Mat, channels[2].Mat))
{
CvInvoke.Merge(vm, dstMat);
}
imageBox2.Image = dstMat;


1. 如何将检测到的边缘在emgu CV颜色捕捉

2. http://www.robindavid.fr/opencv-tutorial/chapter5-line-edge-and-contours-detection.html

3. Split and Merge functions

4. VectorOfMat Class

5. neumute GitHub: image filter <--- good stuff

arrow
arrow
    全站熱搜

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