Emgucv不完整圖像分割試驗(十八)——非標GLCM(C#版本)

圖像切割無外乎用顏色(rgb,hsv等)形狀(凹點,凸包,各種矩)區分,

紋理也很多,常用GLCM灰度共生矩陣,欺負人,又是opencv版本有,適合C#版本的沒有,

即便有,也大多是基於標準矩形的,但實際應用的時候,我們往往要分析不規則圖形。

本來想做個mask圖像後,把灰度0-0(意思是某像素爲0,該左側的像素也爲零,具體參考GLCM)剔除就行了,後來想想不對,萬一圖像內部也有0-0的像素,剔除了會造成干擾的。

水平不高,硬寫了一段c#版本的非標GLCM,各位讀者先湊合用吧,有心的幫我完善一下。

寫成類了,如下:

256表示灰度級數,bp是灰度圖,mask是灰度圖的蒙版,a和b表示灰度值

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;

namespace Count_Num
{
    public class GLCM
    {
        public double[,] glmc;
        double energy;      // 能量 
        double entropy;     // 熵
        double contrast;    // 對比度
        double idMoment;    // 逆差分矩, inverse difference moment

        public double Energy { get => energy; set => energy = value; }
        public double Entropy { get => entropy; set => entropy = value; }
        public double Contrast { get => contrast; set => contrast = value; }
        public double IdMoment { get => idMoment; set => idMoment = value; }

        public GLCM(int size)
        {
            glmc = new double[size, size];
        }


        public unsafe double[,] calGLCM(Bitmap bp, Bitmap mask,int Size,int kind)
        {
            double[,] glmc = new double[Size, Size];

            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    if (kind == 0)
                        glmc[i, j] = get_Oglmc(bp,mask,i,j);
                    if (kind == 90)
                        glmc[i, j] = get_9Oglmc(bp, mask, i, j);
                    if (kind == 45)
                        glmc[i, j] = get_45glmc(bp, mask, i, j);
                    if (kind == 135)
                        glmc[i, j] = get_135glmc(bp, mask, i, j);

                }
            }

            return glmc;
        }

        public unsafe int get_Oglmc(Bitmap bp, Bitmap mask,int a,int b)
        {
            int sum = 0;

            BitmapData dstData = bp.LockBits(new Rectangle(0, 0, bp.Width, bp.Height), ImageLockMode.ReadWrite, bp.PixelFormat);
            BitmapData maskData = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, mask.PixelFormat);
            byte* data = (byte*)(dstData.Scan0);
            byte* maskdata = (byte*)(maskData.Scan0);

            int step = dstData.Stride;

            for (int i = 0; i < dstData.Height; i++)
            {
                for (int j = 0; j < dstData.Width - 1; j++)
                {
                    if (maskdata[i * step + j] == 0 || maskdata[i * step + j+1] == 0)
                        if (data[i * step + j] == a && data[i * step + j+1] == b)
                            sum++;
                }
            }

            bp.UnlockBits(dstData);
            mask.UnlockBits(maskData);

            return sum;
        }

        public unsafe int get_9Oglmc(Bitmap bp, Bitmap mask, int a, int b)
        {
            int sum = 0;

            BitmapData dstData = bp.LockBits(new Rectangle(0, 0, bp.Width, bp.Height), ImageLockMode.ReadWrite, bp.PixelFormat);
            BitmapData maskData = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, mask.PixelFormat);
            byte* data = (byte*)(dstData.Scan0);
            byte* maskdata = (byte*)(maskData.Scan0);

            int step = dstData.Stride;

            for (int i = 0; i < dstData.Height-1; i++)
            {
                for (int j = 0; j < dstData.Width; j++)
                {
                    if (maskdata[i * step + j] == 0 || maskdata[(i+1) * step + j] == 0)
                        if (data[i * step + j] == a && data[(i+1) * step + j] == b)
                            sum++;
                }
            }

            bp.UnlockBits(dstData);
            mask.UnlockBits(maskData);

            return sum;
        }

        public unsafe int get_45glmc(Bitmap bp, Bitmap mask, int a, int b)
        {
            int sum = 0;

            BitmapData dstData = bp.LockBits(new Rectangle(0, 0, bp.Width, bp.Height), ImageLockMode.ReadWrite, bp.PixelFormat);
            BitmapData maskData = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, mask.PixelFormat);
            byte* data = (byte*)(dstData.Scan0);
            byte* maskdata = (byte*)(maskData.Scan0);

            int step = dstData.Stride;

            for (int i = 0; i < dstData.Height-1; i++)
            {
                for (int j = 0; j < dstData.Width - 1; j++)
                {
                    if (maskdata[i * step + j] == 0 || maskdata[(i+1) * step + j+1] == 0)
                        if (data[i * step + j] == a && data[(i+1) * step + j+1] == b)
                            sum++;
                }
            }

            bp.UnlockBits(dstData);
            mask.UnlockBits(maskData);
            return sum;
        }

        public unsafe int get_135glmc(Bitmap bp, Bitmap mask, int a, int b)
        {
            int sum = 0;

            BitmapData dstData = bp.LockBits(new Rectangle(0, 0, bp.Width, bp.Height), ImageLockMode.ReadWrite, bp.PixelFormat);
            BitmapData maskData = mask.LockBits(new Rectangle(0, 0, mask.Width, mask.Height), ImageLockMode.ReadWrite, mask.PixelFormat);
            byte* data = (byte*)(dstData.Scan0);
            byte* maskdata = (byte*)(maskData.Scan0);

            int step = dstData.Stride;

            for (int i = 0; i < dstData.Height-1; i++)
            {
                for (int j = 1; j < dstData.Width ; j++)
                {
                    if (maskdata[i * step + j] == 0 || maskdata[(i+1) * step + j-1] == 0)
                        if (data[i * step + j] == a && data[(i+1) * step + j-1] == b)
                            sum++;
                }
            }
            bp.UnlockBits(dstData);
            mask.UnlockBits(maskData);

            return sum;
        }

        public void getGLCMFeatures(double[,] glmc, int Size)
        {
            double total = 0;


            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    total += glmc[i, j];
                }
            }


            double[,] temp = new double[Size, Size];
            // 歸一化
            for (int i = 0; i < Size; ++i)
            {
                for (int j = 0; j < Size; ++j)
                {
                    temp[i,j] = glmc[i,j] / total;
                }
            }

            for (int i = 0; i < Size; ++i)
            {
                for (int j = 0; j < Size; ++j)
                {
                    energy += temp[i,j] * temp[i,j];

                    if (temp[i,j] > 0)
                        entropy -= temp[i,j] * Math.Log(temp[i,j]);               //熵     

                    contrast += (double)(i - j) * (double)(i - j) * temp[i,j];        //對比度
                    idMoment += temp[i,j] / (1 + (double)(i - j) * (double)(i - j));//逆差矩
                }
            }


           
        }
    }
}

調用:

 GLCM glmc = new GLCM(256);
 DataGridViewRow Temp_Row1 = new DataGridViewRow();      
 dataGridView1.Rows.Add(Temp_Row1);
  
 glmc.glmc = glmc.calGLCM(mask0[i], mask0[i+1], 256, 0);
 glmc.getGLCMFeatures(glmc.glmc, 256);

 this.dataGridView1.Rows[i/2].Cells[0].Value = glmc.Energy;
 this.dataGridView1.Rows[i/2].Cells[1].Value = glmc.Entropy;
 this.dataGridView1.Rows[i/2].Cells[2].Value = glmc.Contrast;
 this.dataGridView1.Rows[i/2].Cells[3].Value = glmc.IdMoment;

如下圖,預處理切割出了四個字母和一個干擾項,干擾項的對比度和能量還是差異挺明顯的。 

 

發佈了35 篇原創文章 · 獲贊 16 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章