美文网首页
图像颜色、灰度共生矩阵、lbp和Hu特征提取

图像颜色、灰度共生矩阵、lbp和Hu特征提取

作者: 小小杨树 | 来源:发表于2021-09-29 09:06 被阅读0次
插播广告

图像颜色特征

调用def color_moments函数提取图像颜色特征(hsv)

程序流程:

1.读取图像
2.RGB空间转换为HSV空间
3.初始化颜色特征
4.获取一阶矩(均值 mean)并放置在特征数组
5.获取二阶矩 (标准差 std)并放置在特征数组
6.三阶矩 (斜度 skewness)并放置在特征数组

import cv2
import numpy as np


def color_moments(img):   
    # img = cv2.imread(filename)   
    if img is None:
        return
    hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)   
    h, s, v = cv2.split(hsv)
    color_feature = []   
 
    h_mean = np.mean(h)  # np.sum(h)/float(N)
    s_mean = np.mean(s)  # np.sum(s)/float(N)
    v_mean = np.mean(v)  # np.sum(v)/float(N)
    color_feature.extend([h_mean, s_mean, v_mean])   
 
    h_std = np.std(h)  # np.sqrt(np.mean(abs(h - h.mean())**2))
    s_std = np.std(s)  # np.sqrt(np.mean(abs(s - s.mean())**2))
    v_std = np.std(v)  # np.sqrt(np.mean(abs(v - v.mean())**2))
    color_feature.extend([h_std, s_std, v_std])   
 
    h_skewness = np.mean(abs(h - h.mean()) ** 3)
    s_skewness = np.mean(abs(s - s.mean()) ** 3)
    v_skewness = np.mean(abs(v - v.mean()) ** 3)
    h_thirdMoment = h_skewness ** (1. / 3)
    s_thirdMoment = s_skewness ** (1. / 3)
    v_thirdMoment = v_skewness ** (1. / 3)
    color_feature.extend([h_thirdMoment, s_thirdMoment, v_thirdMoment])   
    return color_feature


if __name__ == '__main__':
    img = cv2.imread("2.jpg")
    color_data = color_moments(img)
    print(color_data)

—————————————————————————————————————————————————————————————————

—————————————————————————————————————————————————————————————————

灰度共生矩阵

1.定义灰度共生矩阵
2.定义八小类灰度共生矩阵
fast_glcm_mean(img)
fast_glcm_std(img)
fast_glcm_contrast(img)
fast_glcm_dissimilarity(img)
fast_glcm_homogeneity(img)
fast_glcm_ASM(img)
fast_glcm_max(img)
fast_glcm_entropy(img)
3.读取图像并获取H和W值
4.计算八小类灰度共生矩阵
import numpy as np
import cv2
from skimage import data



def fast_glcm(img):
    vmin = 0
    vmax = 255
    nbit = 8
    kernel_size = 5
    mi, ma = vmin, vmax
    ks = kernel_size
    h,w = img.shape

    # digitize
    bins = np.linspace(mi, ma+1, nbit+1)
    gl1 = np.digitize(img, bins) - 1
    gl2 = np.append(gl1[:,1:], gl1[:,-1:], axis=1)

    # make glcm
    glcm = np.zeros((nbit, nbit, h, w), dtype=np.uint8)
    for i in range(nbit):
        for j in range(nbit):
            mask = ((gl1==i) & (gl2==j))
            glcm[i,j, mask] = 1

    kernel = np.ones((ks, ks), dtype=np.uint8)
    for i in range(nbit):
        for j in range(nbit):
            glcm[i,j] = cv2.filter2D(glcm[i,j], -1, kernel)

    glcm = glcm.astype(np.float32)
    return glcm


def fast_glcm_mean(img):
    '''
    calc glcm mean
    '''
    nbit = 8
    h,w = img.shape
    glcm = fast_glcm(img)
    mean = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            mean += glcm[i,j] * i / (nbit)**2

    return mean


def fast_glcm_std(img):
    '''
    calc glcm std
    '''
    nbit = 8
    h,w = img.shape
    glcm = fast_glcm(img)
    mean = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            mean += glcm[i,j] * i / (nbit)**2

    std2 = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            std2 += (glcm[i,j] * i - mean)**2

    std = np.sqrt(std2)
    return std


def fast_glcm_contrast(img):
    '''
    calc glcm contrast
    '''
    nbit = 8
    h,w = img.shape
    glcm = fast_glcm(img)
    cont = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            cont += glcm[i,j] * (i-j)**2

    return cont


def fast_glcm_dissimilarity(img):
    '''
    calc glcm dissimilarity
    '''
    nbit = 8
    h,w = img.shape
    glcm = fast_glcm(img)
    diss = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            diss += glcm[i,j] * np.abs(i-j)

    return diss


def fast_glcm_homogeneity(img):
    '''
    calc glcm homogeneity
    '''
    nbit = 8
    h,w = img.shape
    glcm = fast_glcm(img )
    homo = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            homo += glcm[i,j] / (1.+(i-j)**2)

    return homo


def fast_glcm_ASM(img):
    '''
    calc glcm asm, energy
    '''

    nbit = 8

    h,w = img.shape
    glcm = fast_glcm(img )
    asm = np.zeros((h,w), dtype=np.float32)
    for i in range(nbit):
        for j in range(nbit):
            asm  += glcm[i,j]**2

    ene = np.sqrt(asm)
    return asm, ene


def fast_glcm_max(img):
    '''
    calc glcm max
    '''
    glcm = fast_glcm(img )
    max_  = np.max(glcm, axis=(0,1))
    return max_


def fast_glcm_entropy(img):
    '''
    calc glcm entropy
    '''
    ks = 5
    glcm = fast_glcm(img )
    pnorm = glcm / np.sum(glcm, axis=(0,1)) + 1./ks**2
    ent  = np.sum(-pnorm * np.log(pnorm), axis=(0,1))
    return ent


if __name__ == '__main__':
    img = data.camera() #
    h,w = img.shape

    glcm_mean = fast_glcm_mean(img)
    print(glcm_mean)

    glcm_std = fast_glcm_std(img)
    print(glcm_std)

    glcm_contrast = fast_glcm_contrast(img)
    print(glcm_contrast)

    glcm_dissimilarity = fast_glcm_dissimilarity(img)
    print(glcm_dissimilarity)

    glcm_homogeneity = fast_glcm_homogeneity(img)
    print(glcm_homogeneity)

    glcm_ASM = fast_glcm_ASM(img)
    print(glcm_ASM)

    glcm_max = fast_glcm_max(img)
    print(glcm_max)

    glcm_entropy = fast_glcm_entropy(img)
    print(glcm_entropy)

—————————————————————————————————————————————————————————————————

—————————————————————————————————————————————————————————————————

LBP特征:

1.revolve_map为旋转不变模式的36种特征值从小到大进行序列化编号得到的字典
2.uniform_map为等价模式的58种特征值从小到大进行序列化编号得到的字典
3.将图像载入,并转化为灰度图,获取图像灰度图的像素信息
4.图像的LBP原始特征计算算法:将图像指定位置的像素与周围8个像素比较
5.比中心像素大的点赋值为1,比中心像素小的赋值为0,返回得到的二进制序列
6.获取值r的二进制中1的位数
import cv2
from PIL import Image
from pylab import *


class LBP:
    def __init__(self):
        
        self.revolve_map = {0: 0, 1: 1, 3: 2, 5: 3, 7: 4, 9: 5, 11: 6, 13: 7, 15: 8, 17: 9, 19: 10, 21: 11, 23: 12,
                            25: 13, 27: 14, 29: 15, 31: 16, 37: 17, 39: 18, 43: 19, 45: 20, 47: 21, 51: 22, 53: 23,
                            55: 24,
                            59: 25, 61: 26, 63: 27, 85: 28, 87: 29, 91: 30, 95: 31, 111: 32, 119: 33, 127: 34, 255: 35}
        
        self.uniform_map = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 6: 5, 7: 6, 8: 7, 12: 8,
                            14: 9, 15: 10, 16: 11, 24: 12, 28: 13, 30: 14, 31: 15, 32: 16,
                            48: 17, 56: 18, 60: 19, 62: 20, 63: 21, 64: 22, 96: 23, 112: 24,
                            120: 25, 124: 26, 126: 27, 127: 28, 128: 29, 129: 30, 131: 31, 135: 32,
                            143: 33, 159: 34, 191: 35, 192: 36, 193: 37, 195: 38, 199: 39, 207: 40,
                            223: 41, 224: 42, 225: 43, 227: 44, 231: 45, 239: 46, 240: 47, 241: 48,
                            243: 49, 247: 50, 248: 51, 249: 52, 251: 53, 252: 54, 253: 55, 254: 56,
                            255: 57}

   
    def describe(self, image):
        image_array = np.array(Image.open(image).convert('L'))
        return image_array

    def calute_basic_lbp(self, image_array, i, j):
        sum = []
        if image_array[i - 1, j - 1] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i - 1, j] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i - 1, j + 1] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i, j - 1] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i, j + 1] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i + 1, j - 1] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i + 1, j] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        if image_array[i + 1, j + 1] > image_array[i, j]:
            sum.append(1)
        else:
            sum.append(0)
        return sum


    def get_min_for_revolve(self, arr):
        values = []
        circle = arr
        circle.extend(arr)
        for i in range(0, 8):
            j = 0
            sum = 0
            bit_num = 0
            while j < 8:
                sum += circle[i + j] << bit_num
                bit_num += 1
                j += 1
            values.append(sum)
        return min(values)

    
    def calc_sum(self, r):
        num = 0
        while (r):
            r &= (r - 1)
            num += 1
        return num

    # 获取图像的LBP原始模式特征
    def lbp_basic(self, image_array):
        basic_array = np.zeros(image_array.shape, np.uint8)
        width = image_array.shape[0]
        height = image_array.shape[1]
        for i in range(1, width - 1):
            for j in range(1, height - 1):
                sum = self.calute_basic_lbp(image_array, i, j)
                bit_num = 0
                result = 0
                for s in sum:
                    result += s << bit_num
                    bit_num += 1
                basic_array[i, j] = result
        return basic_array

    # 获取图像的LBP旋转不变模式特征
    def lbp_revolve(self, image_array):
        revolve_array = np.zeros(image_array.shape, np.uint8)
        width = image_array.shape[0]
        height = image_array.shape[1]
        for i in range(1, width - 1):
            for j in range(1, height - 1):
                sum = self.calute_basic_lbp(image_array, i, j)
                revolve_key = self.get_min_for_revolve(sum)
                revolve_array[i, j] = self.revolve_map[revolve_key]
        return revolve_array

    # 获取图像的LBP等价模式特征
    def lbp_uniform(self, image_array):
        uniform_array = np.zeros(image_array.shape, np.uint8)
        basic_array = self.lbp_basic(image_array)
        width = image_array.shape[0]
        height = image_array.shape[1]

        for i in range(1, width - 1):
            for j in range(1, height - 1):
                k = basic_array[i, j] << 1
                if k > 255:
                    k = k - 255
                xor = basic_array[i, j] ^ k
                num = self.calc_sum(xor)
                if num <= 2:
                    uniform_array[i, j] = self.uniform_map[basic_array[i, j]]
                else:
                    uniform_array[i, j] = 58
        return uniform_array

    # 获取图像的LBP旋转不变等价模式特征
    def lbp_revolve_uniform(self, image_array):
        uniform_revolve_array = np.zeros(image_array.shape, np.uint8)
        basic_array = self.lbp_basic(image_array)
        width = image_array.shape[0]
        height = image_array.shape[1]
        for i in range(1, width - 1):
            for j in range(1, height - 1):
                k = basic_array[i, j] << 1
                if k > 255:
                    k = k - 255
                xor = basic_array[i, j] ^ k
                num = self.calc_sum(xor)
                if num <= 2:
                    uniform_revolve_array[i, j] = self.calc_sum(basic_array[i, j])
                else:
                    uniform_revolve_array[i, j] = 9
        return uniform_revolve_array

    # 绘制指定维数和范围的图像灰度归一化统计直方图
    def show_hist(self, img_array, im_bins, im_range):
        hist = cv2.calcHist([img_array], [0], None, im_bins, im_range)
        hist = cv2.normalize(hist, None).flatten()
        plt.plot(hist, color='r')
        plt.xlim(im_range)
        plt.show()

    # 绘制图像原始LBP特征的归一化统计直方图
    def show_basic_hist(self, img_array):
        self.show_hist(img_array, [256], [0, 256])

    # 绘制图像旋转不变LBP特征的归一化统计直方图
    def show_revolve_hist(self, img_array):
        self.show_hist(img_array, [36], [0, 36])

    # 绘制图像等价模式LBP特征的归一化统计直方图
    def show_uniform_hist(self, img_array):
        self.show_hist(img_array, [60], [0, 60])

    # 绘制图像旋转不变等价模式LBP特征的归一化统计直方图
    def show_revolve_uniform_hist(self, img_array):
        self.show_hist(img_array, [10], [0, 10])

    # 显示图像
    def show_image(self, image_array):
        cv2.imshow('Image', image_array)
        cv2.waitKey(0)


if __name__ == '__main__':
    image = "2.jpg"
    lbp = LBP()
    image_array = lbp.describe(image)

    # 获取图像原始LBP特征,并显示其统计直方图与特征图像
    basic_array = lbp.lbp_basic(image_array)
    basic_data = basic_array
    print(basic_data)

—————————————————————————————————————————————————————————————————

—————————————————————————————————————————————————————————————————

Hu特征提取

自定义求矩函数,主要是根据公式将一个个参数求出

param img_gray: 灰度图像,对于二值图像来说就只有两个灰度0和255
return: 返回以10为底对数化后的hu不变矩

由于7个不变矩的变化范围很大,为了便于比较,可利用取对数的方法进行数据压缩;
同时考虑到不变矩有可能出现负值的情况,因此,在取对数之前先取绝对值
经修正后的不变矩特征具有平移 、旋转和比例不变性

import cv2
import numpy as np


def def_moments(img_gray):

    # 标准矩定义为m_pq = sumsum(x^p * y^q * f(x, y))其中f(x,y)为像素点处的灰度值
    row, col = img_gray.shape
    # 计算图像的0阶几何矩
    m00 = 0.0
    ##初始化一到三阶几何矩
    # 计算一阶矩阵
    m10 = m01 = 0.0
    # 计算图像的二阶、三阶几何矩
    m11 = m20 = m02 = m12 = m21 = m30 = m03 = 0.0
    for i in range(row):
        for j in range(col):
            m00 += img_gray[i][j]
            m10 += i * img_gray[i][j]
            m20 += i ** 2 * img_gray[i][j]
            m30 += i ** 3 * img_gray[i][j]
            m11 += i * j * img_gray[i][j]
            m12 += i * j ** 2 * img_gray[i][j]
            m21 += i ** 2 * j * img_gray[i][j]
    for j in range(col):
        for i in range(row):
            m01 += (j * img_gray[i, j])
            m02 += (j ** 2 * img_gray[i, j])
            m03 += (j ** 3 * img_gray[i, j])
    # 由标准矩我们可以得到图像的"重心"
    u10 = m10 / m00
    u01 = m01 / m00
    # 计算图像的二阶中心矩、三阶中心矩
    y00 = y10 = y01 = y11 = y20 = y02 = y30 = y12 = y21 = y03 = 0.0
    for x in range(row):
        for y in range(col):
            x_ = x - u10
            y_ = y - u01
            y00 += img_gray[x][y]
            y10 += x_ * img_gray[x][y]
            y01 += y_ * img_gray[x][y]
            y11 += x_ * y_ * img_gray[x][y]
            y02 += y_ ** 2 * img_gray[x][y]
            y20 += x_ ** 2 * img_gray[x][y]
            y03 += y_ ** 3 * img_gray[x][y]
            y30 += x_ ** 3 * img_gray[x][y]
            y12 += x_ * y_ ** 2 * img_gray[x][y]
            y21 += x_ ** 2 * y_ * img_gray[x][y]
    # 计算图像的归一化中心矩
    n20 = y20 / (y00 ** 2)
    n02 = y02 / (y00 ** 2)
    n11 = y11 / (y00 ** 2)
    n30 = y30 / (y00 ** 2.5)
    n03 = y03 / (y00 ** 2.5)
    n12 = y12 / (y00 ** 2.5)
    n21 = y21 / (y00 ** 2.5)
    # 计算图像的七个不变矩
    h1 = n20 + n02
    h2 = (n20 - n02) ** 2 + 4 * (n11 ** 2)
    h3 = (n30 - 3 * n12) ** 2 + (3 * n21 - n03) ** 2
    h4 = (n30 + n12) ** 2 + (n21 + n03) ** 2
    h5 = (n30 - 3 * n12) * (n30 + n12) * ((n30 + n12) ** 2 - 3 * (n21 + n03) ** 2) + (3 * n21 - n03) * (n21 + n03) \
         * (3 * (n30 + n12) ** 2 - (
            n21 + n03) ** 2)
    h6 = (n20 - n02) * ((n30 + n12) ** 2 - (n21 + n03) ** 2) + 4 * n11 * (n30 + n12) * (n21 + n03)
    h7 = (3 * n21 - n03) * (n30 + n12) * ((n30 + n12) ** 2 - 3 * (n21 + n03) ** 2) + (3 * n12 - n30) * (n21 + n03) \
         * (3 * (n30 + n12) ** 2 - (
            n21 + n03) ** 2)
    inv_m7 = [h1, h2, h3, h4, h5, h6, h7]
    humoments = np.log(np.abs(inv_m7))
    return humoments

if __name__ == '__main__':
    img = cv2.imread("2.jpg")
    img_gary = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    color_data = def_moments(img_gary)
    print(color_data)

转自:https://blog.csdn.net/qq_45769063/article/details/107405546

相关文章

网友评论

      本文标题:图像颜色、灰度共生矩阵、lbp和Hu特征提取

      本文链接:https://www.haomeiwen.com/subject/olodnltx.html