專案名稱: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;
}
}
======================================
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);
===================================
利用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
Blue channel intensity
Green channel intensity
如果要將R,G,B灰階強度改成對應紅色colormap,綠色colormap,藍色colormap顯示呢?
GetRedChannel();
以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;
}
=========================================
彩色影像整張進行每個像素點簡單減法運算
blue channel – 10
green channel – 20
red channel - 255
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
留言列表