loading...

Selasa, 06 November 2018

BAB 4 - Geometri Moment Invariant

Geometri Moment Invariant

Geometri Moment Invariant bisa digunakan untuk shape analyst lho, mari kita bahas mengenai moment


Moment

Momen suatu objek dapat menggambarkan luas area, posisi, orientasi, dan paramater yang  lainnya. Persamaan dasar dari momen sebagai berikut

Dengan i dan j adalah posisi dari suatu pixel dengan nilai intensitas axy. Momen tingkat ke 0 dan ke 1 didefinisikan sebagai berikut
Titik pusat (center of gravity) x’ dan y’ sebagai berikut

Misalkan
maka
Area  = 2
M00 = 2
M10 = 7
M01 = 4

akan dilanjutkan berikutnya
 Posisi x’ dan y’ adalah koordinat layar bukan koordinat kartesius.
Momen Pusat ยต
Momen yang bersesuai dengan titik tengah suatu area

 Momen ternormalisasi dinyatakan dengan persamaan berikut
 Maka vector ciri untuk pengenalan objek dari momen - momen invarian sebagai berikut
Berikut disajikan potongan code untuk perhitungan Moment, sedangkan untuk Center of Gravity dibuat tersendiri

    class Moment
    {
        private double moment1, moment2, moment3, moment4, moment5, moment6, moment7;

        public double Moment1 { get => Math.Round(moment1, 2); }
        public double Moment2 { get => Math.Round(moment2, 2); }
        public double Moment3 { get => Math.Round(moment3, 2); }
        public double Moment4 { get => Math.Round(moment4, 2); }
        public double Moment5 { get => Math.Round(moment5, 2); }
        public double Moment6 { get => Math.Round(moment6, 2); }
        public double Moment7 { get => Math.Round(moment7, 2); }



        /// <summary>
        /// 
        /// </summary>
        /// <param name="x">lokasi titik tengah x</param>
        /// <param name="y">lokasi titik tengah y</param>
        /// <param name="data">data dengan rentang nilai 0 dan 1 </param>
        public void Process(double x, double y, double[,] data)
        {
            double n20 = 0;
            double n02 = 0;
            double n11 = 0;
            double n12 = 0;
            double n21 = 0;
            double n30 = 0;
            double n03 = 0;
            double moment00 = 0;
            for (int X = 0; X < data.GetLength(0); X++)
            {
                for (int Y = 0; Y < data.GetLength(1); Y++)
                {
                    if (data[X, Y] > 0) //karena format biner
                    {
                        n20 += (Math.Pow(X - x, 2)) * (Math.Pow(Y - y, 0)) * 1; //axy --> diubah menjadi angka 1 karena biner
                        n02 += (Math.Pow(X - x, 0)) * (Math.Pow(Y - y, 2)) * 1;
                        n11 += (Math.Pow(X - x, 1)) * (Math.Pow(Y - y, 1)) * 1;
                        n12 += (Math.Pow(X - x, 1)) * (Math.Pow(Y - y, 2)) * 1;
                        n21 += (Math.Pow(X - x, 2)) * (Math.Pow(Y - y, 1)) * 1;
                        n30 += (Math.Pow(X - x, 3)) * (Math.Pow(Y - y, 0)) * 1;
                        n03 += (Math.Pow(X - x, 0)) * (Math.Pow(Y - y, 3)) * 1;

                        moment00 += (Math.Pow(X - x, 0)) * (Math.Pow(Y - y, 0)) * 1;
                    }
                    else
                    {
                        n20 += (Math.Pow(X - x, 2)) * (Math.Pow(Y - y, 0)) * 0; //axy --> diubah menjadi angka 0 karena biner
                        n02 += (Math.Pow(X - x, 0)) * (Math.Pow(Y - y, 2)) * 0;
                        n11 += (Math.Pow(X - x, 1)) * (Math.Pow(Y - y, 1)) * 0;
                        n12 += (Math.Pow(X - x, 1)) * (Math.Pow(Y - y, 2)) * 0;
                        n21 += (Math.Pow(X - x, 2)) * (Math.Pow(Y - y, 1)) * 0;
                        n30 += (Math.Pow(X - x, 3)) * (Math.Pow(Y - y, 0)) * 0;
                        n03 += (Math.Pow(X - x, 0)) * (Math.Pow(Y - y, 3)) * 0;

                        moment00 += (Math.Pow(X - x, 0)) * (Math.Pow(Y - y, 0)) * 0;
                    }


                }

            }
            //update hasil
            n20 = n20 / Math.Pow(moment00, ((2 + 0) / 2) + 1);
            n02 = n02 / Math.Pow(moment00, ((0 + 2) / 2) + 1);
            n11 = n11 / Math.Pow(moment00, ((1 + 1) / 2) + 1);
            n12 = n12 / Math.Pow(moment00, ((1 + 2) / 2) + 1);
            n21 = n21 / Math.Pow(moment00, ((2 + 1) / 2) + 1);
            n30 = n30 / Math.Pow(moment00, ((3 + 0) / 2) + 1);
            n03 = n03 / Math.Pow(moment00, ((0 + 3) / 2) + 1);
            //update moment
            moment1 = n20 + n02;
            moment2 = Math.Pow(n20 + n02, 2) + 4 * Math.Pow(n11, 2);
            moment3 = Math.Pow(n30 - 3 * n12, 2) + Math.Pow(3 * n21 - n03, 2);
            moment4 = Math.Pow(n30 + n12, 2) + Math.Pow(n21 + n03, 2);

            double a, b, c, d, e, f, g, h;
            a = n30 - 3 * n21;
            b = n30 + n12;
            c = Math.Pow(n30 + n21, 2);
            d = 3 * Math.Pow(n21 + n03, 2);
            e = 3 * n21 - n03;
            f = n21 + n03;
            g = 3 * Math.Pow(n30 + n21, 2);
            h = n21 + n03;

            moment5 = (a * b * (c - d)) + (e * f * (g - h));

            a = n20 - n02;
            b = Math.Pow(n30 + n21, 2);
            c = Math.Pow(n21 + n03, 2);
            d = n30 + n12;
            e = n21 + n03;
            moment6 = (a * (b - c)) + (4 * n11) * (d * e);

            a = 3 * n21 - n30;
            b = n30 + n12;
            c = Math.Pow(n30 + n12, 2);
            d = 3 * Math.Pow(n21 + n03, 2);
            e = 3 * n21 - n03;
            f = n21 + n03;
            g = 3 * Math.Pow(n30 + n12, 2);
            h = n21 + n03;
            moment7 = (a * b * (c - d)) + (e * f * (g - h));




        }
    }
    ///<summary>
    /// perhitungan titik pusat massa
    /// </summary>
    public class CenterOfGravity
    {
        private double x;
        private double y;
        private double area;
        /// <summary>
        /// perhitungan titik pusat massa 
        /// </summary>
        /// <param name="data"></param>
        public void Process(double[,] data)
        {
            int rows = data.GetLength(0);
            int cols = data.GetLength(1);
            double tmpSumX, tmpSumY, tmpSumArea = 0;
            double m10 = 0;
            double m01 = 0;
            double m00 = 0;
            int i = 1;
            int j = 1;
            for (int X = 0; X < rows; X++)
            {
                for (int Y = 0; Y < cols; Y++)
                {
                    tmpSumX = (double)(Math.Pow(Y, j) * data[X, Y]);
                    m10 = m10 + tmpSumX;

                    tmpSumY = (double)(Math.Pow(X, i) * data[X, Y]);
                    m01 = m01 + tmpSumY;

                    tmpSumArea = (double) (tmpSumArea + data[X, Y]);
                    m00 = tmpSumArea;
                }
            }

            //update
            this.x = (double)m10 / (double)m00;
            this.y = (double)m01 / (double)m00;
            this.area = m00;
            //location = new Point(x, y);
        }

        /// <summary>
        /// 
        /// </summary>
        public double X
        {
            get { return this.x; }
        }
        /// <summary>
        /// 
        /// </summary>
        public double Y
        {
            get { return this.y; }
        }
        /// <summary>
        /// 
        /// </summary>
        public double Area
        {
            get { return this.area; }
        }
    }
Untuk menghitung Center Of gravity sebagai berikut

double[,] data = new double[,]
{
   { 0,0,0,0,0,0,0},
    { 0,0,0,0,0,0,0},
    { 0,0,0,1,1,0,0},
    { 0,0,0,0,0,0,0},
    { 0,0,0,0,0,0,0},
    { 0,0,0,0,0,0,0},
    { 0,0,0,0,0,0,0}
};
CenterOfGravity cog = new CenterOfGravity();
cog.Process(data);
Console.WriteLine(cog.X+ ";" + cog.Y);
Menghasilkan


3.5; 2

Sedangkan untuk perhitungan Moment, kita langsung menggunakan gambar berikut




Kita akan menguji 3 shape yaitu lingkaran, segitiga, dan persegi panjang dengan variasi rotasi, tentu biar lebih mudah kita akan memanfaatkan Accord untuk menentukan lokasi Center of Gravity serta menentukan objek nya, berikut potongan kode nya

Bitmap image = (Bitmap)Bitmap.FromFile("D:/moment.png");

if (image.PixelFormat != PixelFormat.Format8bppIndexed) //jika truecolor, maka convert dulu
{
 Grayscale rgb2grayscale = new Grayscale(0.2125, 0.7154, 0.0721);
 image = rgb2grayscale.Apply(image);

}

//penerapan BW
OtsuThreshold tr = new OtsuThreshold();
Bitmap black_white = tr.Apply(image);
BlobCounter blobCounter = new BlobCounter();
blobCounter.ProcessImage(black_white);
AForge.Imaging.Blob[] blobs = blobCounter.GetObjectsInformation();
Bitmap target;
Moment moment = new Moment();
ImageToMatrix conv = new ImageToMatrix(0, 1);
double[,] matrix;
int i = 1;
foreach (AForge.Imaging.Blob blob in blobs)
{
 Rectangle cropRect = blob.Rectangle;
 target = black_white.Clone(cropRect, black_white.PixelFormat);
 conv.Convert(target, out matrix);
 moment.Process(blob.CenterOfGravity.X, blob.CenterOfGravity.Y, matrix);
 Console.WriteLine(i + ": " + moment.Moment1 + "; \t" +
      moment.Moment2 + "; \t" +
      moment.Moment3 + "; \t" +
      moment.Moment4 + "; \t" +
      moment.Moment5 + "; \t" +
      moment.Moment6 + "; \t" +
      moment.Moment7);

 Accord.Controls.ImageBox.Show(new Bitmap(target)).SetTitle("no : " + i);
 i++;
}
Kita memanfaatkan Blob untuk mendeteksi keberadaan objek2

Berikut hasil moment 1 sampai moment 7

Perhatikan no 2 (lingkaran) mempunyai nilai yang paling berbeda


dari semunya bentuk, lingkaran mempunyai bentuk yang lebih mudah dikenali karena mempunyai nilai terendah.

Tidak ada komentar: