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;

如下图,预处理切割出了四个字母和一个干扰项,干扰项的对比度和能量还是差异挺明显的。 

Emgucv不完整图像分割试验(十八)——非标GLCM(C#版本)_第1张图片

Emgucv不完整图像分割试验(十八)——非标GLCM(C#版本)_第2张图片

 

你可能感兴趣的:(Emgucv不完整图像分割试验(十八)——非标GLCM(C#版本))