高斯判别算法GDA(吴恩达机器学习c#实践,生成高斯模板显示同心圆马氏距离,一)
首先實現P(x|y)=高斯函數(正態分布),即y是正態分布,是條件,我們把它還原到圖像界面I(i,j)每一個像素,是結果。
這個實際就是生成高斯模板,我們前面有3*3的高斯生成算法,但是根本沒有辦法顯示,3*3=9個像素,針尖一樣,我們在這個基礎上,生成11*11的高斯模板,并放大16倍,生成圖像,在界面顯示出來,看是否是同心圓,二維高斯像一個大鐘,我們用平面平行xy平面,切割大鐘很多次,感到很像核磁共振人體切片,把這些等高線,讓z=0,在xy平面畫出來,驗證一下,發現圖像的高斯離散型和高斯的連續函數還是有差別(顆粒感很強,我們把模板數據變成了灰度),請看圖:
c#完整代碼如下:
namespace 畫高斯同心圓
{
? ? public partial class Form1 : Form
? ? {
? ? ? ? public Form1()
? ? ? ? {
? ? ? ? ? ? InitializeComponent();
? ? ? ? }
? ? ? ? private void Form1_Load(object sender, EventArgs e)
? ? ? ? {
? ? ? ? ? ? //生成二維高斯濾波系數// ?
? ? ? ? ? ? // int nWidowSize = 3;
? ? ? ? ? ? int nWidowSize = 11;
? ? ? ? ? ? // double nSigma = 0.4;
? ? ? ? ? ? double nSigma = 3.3;
? ? ? ? ? ? // double nSigma = 1.4;
? ? ? ? ? ? // ?double* pdKernal_2 = new double[nWidowSize*nWidowSize]; //定義二維高斯核數組 ??
? ? ? ? ? ? double[] pdKernal_2 = new double[11 * 11];
? ? ? ? ? ? //double[] pdKernal_2 = new double[3 * 3];
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ///二維高斯函數公式 ? ? ??
? ? ? ? ? ? // ? ? ? ? ? ? ? ? ? ? ? ?x*x+y*y ? ? ? ? ? ? ? ? ? ? ? ?/// ??
? ? ? ? ? ? // ? ? ? ? ? ? ?-1*-------------- ? ? ? ? ? ? ? ?/// ??
? ? ? ? ? ? // ?1 ? ? ? ? ? ? 2*nSigma*nSigma ? ? ? ? ? ? ? ?/// ??
? ? ? ? ? ? // ---------------- e ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /// ??
? ? ? ? ? ? // 2*pi*nSigma*nSigma ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /// ??
? ? ? ? ? ? /// ??
? ? ? ? ? ? int nCenter = (nWidowSize) / 2;
? ? ? ? ? ? for (int i = 0; i < nWidowSize; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int j = 0; j < nWidowSize; j++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? int nDis_x = i - nCenter;
? ? ? ? ? ? ? ? ? ? int nDis_y = j - nCenter;
? ? ? ? ? ? ? ? ? ? double temp = (nDis_x * nDis_x + nDis_y * nDis_y);
? ? ? ? ? ? ? ? ?? temp = temp / (nSigma * nSigma);
? ? ? ? ? ? ? ? ? ? double r = Math.Sqrt(temp);//馬氏距離
? ? ? ? ? ? ? ? ? ? double 指數 = Math.Exp(-(1 / 2.0) * temp);
? ? ? ? ? ? ? ? ? ? double temp2 = 指數 / (2 * 3.1415926 * nSigma * nSigma);
? ? ? ? ? ? ? ? ? ? pdKernal_2[i + j * nWidowSize] = (int)(temp2 * 1000);
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ?
? ? ? ? ? ? //因為是11*11,不妥,X12,所以改為44*44*3*3,最終放大了16倍
? ? ? ? ? ? byte[] gaos = new byte[11 ?* 11 ];
? ? ? ? ?
? ? ? ? ? ? for (int j = 0; j < 11; j++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? for (int i = 0; i < 11; i = i + 1)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? int nn = j * 11 + i;
? ? ? ? ? ? ? ? ? ? int temp3 = (int)(pdKernal_2[nn] * 10);
? ? ? ? ? ? ? ? ? ? gaos[nn] = temp3 > 255 ? (byte)255 : (byte)temp3;//? ? ? ? ? ? ??
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? int ww = 132 + 44;
? ? ? ? ? ? int hh = 132 + 44;
? ? ? ? ? ? //int ww = 132 ;
? ? ? ? ? ? //int hh = 132 ;
? ? ? ? ? ? byte[] glob_buffer8 = new byte[ww * hh];
? ? ? ? ? ? //ZoomNormal(gaos, ref glob_buffer8, 11, 11,
? ? ? ? ? ? // ? ? ? ? ? ref ?ww, ref hh, 12, 12);
? ? ? ? ? ? ZoomNormal(gaos, ref glob_buffer8, 11, 11,
? ? ? ? ? ? ? ? ? ? ? ? ref ?ww, ref hh, 16, 16);
? ? ? ? ??
? ? ? ? ? ? ///測試8位顯示
? ? ? ? ? ? Bitmap cutPic88 = new Bitmap(ww, hh, PixelFormat.Format8bppIndexed);
? ? ? ? ? ? System.Drawing.Imaging.ColorPalette cp = cutPic88.Palette;
? ? ? ? ? ? for (int i = 0; i < 256; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? cp.Entries[i] = Color.FromArgb(255, i, i, i);
? ? ? ? ? ? }
? ? ? ? ? ? cutPic88.Palette = cp;
? ? ? ? ? ? BitmapData _cutPic8 = cutPic88.LockBits(new Rectangle(0, 0, ww, hh), ImageLockMode.ReadWrite,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?cutPic88.PixelFormat);
? ? ? ? ? ? IntPtr ptr00 = _cutPic8.Scan0;//得到首地址 ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? //把cutvalues數組給ptr
? ? ? ? ? ? System.Runtime.InteropServices.Marshal.Copy(glob_buffer8, 0, ptr00, ww * hh);
? ? ? ? ? ? cutPic88.UnlockBits(_cutPic8);
? ? ? ? ? ? pictureBox顯示gaos.Image = cutPic88;//pictureBox顯示gaos
? ? ? ? }
? ? ? ? void ZoomNormal(byte[] image0, ref byte[] image1, int w, int h,
? ? ? ? ? ? ? ? ? ? ? ?ref ?int outwidth, ref int outheight, double ZoomX, double ZoomY)
? ? ? ? {
? ? ? ? ? ? outwidth = (int)(w * ZoomX + 0.5);
? ? ? ? ? ? outheight = (int)(h * ZoomY + 0.5);
? ? ? ? ?
? ? ? ? ? ? int newbuffersize = outwidth * outheight ;
? ? ? ? ? ? image1 = new byte[newbuffersize]; ? ? ? ?
? ? ? ? ? ? int x = 0;
? ? ? ? ? ? int y = 0;
? ? ? ? ? ? int tempY;
? ? ? ? ? ? int tempJ;
? ? ? ? ? ? for (int j = 0; j < outheight; j++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? y = (int)(j / ZoomY + 0.5);
? ? ? ? ? ? ? ? if (y >= h) y--;
? ? ? ? ? ? ? ? tempY = y * w ;
? ? ? ? ? ? ? ? tempJ = j * outwidth ;
? ? ? ? ? ? ? ? for (int i = 0; i < outwidth; i++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? x = (int)(i / ZoomX + 0.5);
? ? ? ? ? ? ? ? ? ? if (x >= w)
? ? ? ? ? ? ? ? ? ? ? ? x--;
? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? image1[tempJ + i ] = image0[tempY + x ];
? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? private void pictureBox顯示gaos_Paint(object sender, PaintEventArgs e)
? ? ? ? {
? ? ? ? ? ? Graphics g = e.Graphics;//馬氏距離r=1.21,70.10*10E-4(概率),位置(1,5),放大16倍后如圖
? ? ? ? ? ? g.DrawEllipse(new Pen(Color.Red), new Rectangle( 16, ?16, 4 * 16 * 2, 4 * 16 * 2));
? ? ? ? ? ? //馬氏距離r=0.9,96.67*10E-4(概率),位置(2,5),放大16倍后如圖
? ? ? ? ? ? g.DrawEllipse(new Pen(Color.Red), new Rectangle(16*2, 16*2, 3 * 16 * 2, 3 * 16 * 2));
? ? ? ? }
? ? }
}
說明:當? double nSigma = 3.3;更改為:double nSigma = 1;圖像變成如下:
這是什么意思呢?也就是說3*nSigma+1=3*1+1=4單元,模板矩陣4*4沒有中心,所以模板變成5*5,對比前邊,5*5之外,高斯模板就不起作用了,為什么我們nSigma=3.3?原因在此,3.3*3+1=11,所以我們使用11*11的模板。3*3的模板,nSigma=0.4.
另外,當nSigma=1時,重點是:協方差矩陣=協方差矩陣的逆==I=單位矩陣,馬氏距離的平方=(x y),正態分布變成了Gaos(x,y)=0.5*(1/3.1416)*exp((-0.5)(x y)),這里有一個非凡的發現,就是中的1變成了特征值,什么是特征值,就是橢圓的長短軸a,b,為什么這樣說?因為(x y)=+=f(x,y),這個曲線是什么?同心圓,橢圓長短軸為1的特殊現象,即/1+/1=f(x,y),若f(x,y)為任意實數Z,則/Z+/Z=1,像極了橢圓。
那么怎樣讓同心圓變成同心橢圓?改變協方差矩陣,比如,改為,這里一個小小的改變,簡直是天大的變化,不信請看協方差矩陣的定義,P(協方差系數)不等于零了,即變量x和y不獨立了,相關了,但這仍然是高斯分布,不再是同心圓,而是同心橢圓了。
回到我們的程序中的協方差矩陣=,特征值a+b=A+C=矩陣的跡,a*b=矩陣的行列式值=A*C-B*B,可以解得a=3.3,b=3.3,長軸等于短軸,圓一個,變化為=,可以解得a=3.3+0.5=3.8,b=3.3-0.5=2.8;長短軸不等,圓回歸常態橢圓。
下一節,把這個同心橢圓畫出來。
總結
以上是生活随笔為你收集整理的高斯判别算法GDA(吴恩达机器学习c#实践,生成高斯模板显示同心圆马氏距离,一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Node读取和写入json文件
- 下一篇: springboot+mysql “友书