图像特征提取算法:颜色和边缘的方向性描述符CEDD

CEDD,全称是颜色和边缘的方向性描述符(Color and Edge Directivity Descriptor),具有抽取特征速度较快,特征描述符占用空间较小的优势。

本文内容总结2012北邮李东阳的硕士论文《Android手机上图像分类技术的研究》,与CEDD特征相关的主要内容目录如下:
在这里插入图片描述

1.颜色信息

CEDD特征结合了颜色和纹理两方面信息,本小结将给出颜色信息提取的过程,重点分析RGB-HSV模型转换、10-bins模糊过滤器和24-bins模糊过滤器的原理。

1.1.RGB模型转换为HSV模型

RGB模型可以说是我们最熟悉、使用也最多的颜色模型,它们分别代表组成一个颜色的三个分量,(0,0,0)代表黑色,(255,255,255)代表白色,(255,0,0)代表红色,(0,255,0)代表绿色,(0,0,255)代表蓝色,其它颜色也可通过调整这三个分量表示出来。RGB颜色模型的设计是根据色彩发光原理而来的,且与硬件相关,一般情况下,计算机都会釆用这种空间模型在屏幕上显示某种颜色的定义,即人们所熟悉的三色组合。所以,当从一幅图像中提取像素点时首先提取的一般也是像素点的RGB信息。

HSV模型中,H (Hue)代表色调,指通过物体传播或从物体射出的颜色,一般在使用中是由颜色名称来标识的。S (Saturation)代表饱和度,表示色调中灰色成分的比例,指颜色的纯度或强度。V (Value)代表亮度,指颜色相对的明暗程度。HSV模型能够较好地反应人对颜色的感知和鉴别能力,所以非常适合于比较基于颜色的图像相似性,在图像分类中也得到了广泛应用。

综合上述两点,在提取颜色信息前就需要对图像像素进行RGB-HSV的模型转换。在此特征提取算法中RGB-HSV转换的方式稍有不同,且最后得出的S、V取值范围也有差别,都是(0,255),但基本原理不变,这是为了方便于后面在模糊过滤器中的运算,转换公式如下:
在这里插入图片描述
这里所有的HSV值最后都取整数。

通过上面的计算,便可以得出像素点的HSV值,下面将用HSV值进行模糊过滤,得出颜色信息的直方图。

1.2. 10-bins模糊过滤器

在这里插入图片描述
10-bins模糊过滤器的工作过程是通过三个通道输入HSV信息,然后输出10个模糊的直方图信息值。10个直方图信息值的含义如下:(0)黒色(Black),(1)灰色(Gray),(2)白色(White),(3)红色(Red), (4)橙色(Orange),(5)黄色(Yellow),(6)绿色(Green),(7)青色(Cyan),(8)蓝色(Blue),(9)品红色(Magenta)。其原理如图所示。

10-bins模糊过滤器是基于模糊理论的,我们先来分析一下模糊理论中颜色径向边缘的生成。由于H代表的是色调,从它的计算方法可以看出H的取值范围为0-360,则当一张图片上出现由一种颜色向另一种颜色过渡时,H值的变化就会较快,这时就会出现所谓的颜色径向边缘。根据模糊理论可以找出这些径向边缘的位置。如图所示,图(a)为提取出的H通道值的图像,图(b)是将图(a)通过CLF过滤器模糊处理后得出的。CLF的英文全称为Coordinatelogic filters,它的方法就是将图像上每个3*3方块的九个像素点的二进制值进行逻辑“与”运算,这样,在H通道的颜色边缘处就会出现较小的H值,也就是我们看到的图 (b)的效果。再将原H值图像与过滤后的H图像进行差运算即可得如图(c)所示的较明显的颜色径向边缘。图 (d)为H通道理论上的径向边缘位置。
在这里插入图片描述
通过上述原理反复实验可以得到H径向边缘的范围,如图所示,将H通道的值分为八个模糊区域,每一区域依次命名为:(0)红色-橙色(Redto Orange),(1)橙色(Orange),(2)黄色(Yellow),(3)绿色(Green),(4)青色(Cyan),(5)蓝色(Blue),(6)品红色(Magenta),(7)蓝色-红色(Blueto Red)。每两个相邻区域都有交叉的部分。

1.3. 24-bins模糊过滤器

24-bins模糊过滤器就是将10-bins模糊过滤器输出的每种色区再分为3个H值区域,输入一个10维向量和S、V通道值,输出的是一个24维向量,其系统模型如图3-7所示。它输出的每一维所代表的信息分别是:(0)黑色(Black),(1)灰色(Grey),(2)白色(White),(3)暗红色(Dark Red),(4)红色(Red),(5)浅红(Light Red),(6)暗橙色(DarkOrange),(7)橙色(Orange),(8)浅橙色(Light Orange),(9)暗黄色(Dark Yellow),(10)黄色(Yellow), (11)浅黄色(LightYellow),(12)深绿色(Dark Green),(13)绿色(Green),(14)浅绿色(Light Green),(15)暗青色(Dark Cyan),(16)青色(Cyan),(17)浅青色(Light Cyan),(18)深蓝色(Dark Blue),(19)蓝色(Blue),(20)淡蓝色(LightBlue),(21)暗品红色(DarkMagenta),(22)品红色(Magenta),(23)浅品红色(Light Magenta)。
在这里插入图片描述

2.纹理信息

本小结将介绍CEDD特征中纹理信息的提取过程,通过YIQ模型计算出像素灰度值,再提取图像的边缘方向直方图纹理信息。

2.1.YIQ彩色空间

YIQ色彩空间属于NTSC (国际电视标准委员会)系统。Y(Luminace)代表了颜色的明视度,直观点说就是图像的灰度值。I和Q (Chrominace)代表了色调信息,它们分别描述图像色彩以及饱和度的属性。在YIQ色彩空间模型中,Y分量表示图像的亮度信息,I和Q分量表示颜色信息,I分量是指从橙色到青色,Q分量则是指从紫色到黄绿色[24]。

通过对彩色图像从RGB到YIQ空间的转换,可以分开彩色图像中的亮度信息与色度信息,并对其各自进行独立处理。RGB转换到YIQ空间模型的对应关系如下面方程所示:
在这里插入图片描述
提取纹理特征时,最常用的就是图像的灰度值,这里引出YIQ空间也只为求出Y值,以便后面进行纹理信息的提取。

2.2.边缘方向直方图

在这里将提出一种计算速度较快捷的纹理信息提取方法,EHD( Edge Histogram Descriptor),即边缘直方图描述符,将会用到5个数字滤波器,如图所示。
在这里插入图片描述
这五个数字滤波器是用来提取纹理边缘信息的,它们能够将其所作用的区域分为垂直方向、水平方向、45度方向、135度方向和无方向五个类别。在对图像进行纹理信息提取时会将图像分为若干小区。然后每个小区再分为如图3-9的四个大小相等的子小区。然后每个小区再分为如图3-9的四个大小相等的子小区。用g0 (i,j),g1(i,j),g2(i,j),g3(i,j)分别表示在第(i,j)个小区内四个子小区的平均灰度值。av (k),ah(k),ad-45 (k),ad-135 (k)和and (k)分别代表四个子小区平均灰度值经过过滤器时的参数,图中每个子小区中的数值便是滤波器的参数,其中k的取值范围是0到3整数,表示小区内的四个子小区。nv (i, j),nh (i,j),nd-45(i,j),nd-135(i,j)和nnd(i,j)为第(i,j)个小区内所判定各方向的取值。计算方法如下:
在这里插入图片描述
找出最大值,
在这里插入图片描述
再对所有n值规范化,
在这里插入图片描述
通过上面的计算公式,可以得出每个小区内图像边缘的信息。CEDD中纹理信息提取的是一个6维直方图,直方图中各维信息的含义分别是:(0)无边缘信息,(1)无方向的边缘信息,(2)水平方向的边缘信息,(3)垂直方向的边缘信息,(4) 45度方向的边缘信息,(5) 135度方向的边缘信息。判断每个小区纹理信息所属的直方图区域的方法如图所示:
在这里插入图片描述
首先设定4个阈值:T0=14,检验该小区是否含有边缘信息;T1=0.68,判断该小区是否含有无方向信息;T2=T3=0.98,用来判断该小区是否含有其它四个方向的信息。如果mmax大于T0,则该小区含有纹理信息,如果不大于则是非含有纹理信息的小区,那么6维直方图第一维的值会加1。如果该区域是有边缘信息的,即mmax大于等于T0,便可以计算其它各方向信息的值,如图3-10所示。此原理图是一个发散的五边形,每个顶点代表一个边缘方向类别,每个小区内计算出的nnd、nh、nv、nd-45、nd-135值便分别落在五个点与中心原点的连线上。中心点的值为1,五边形边界线上的值为0。如果n值大于它相应边缘方向类别上的阈值,则可判定该小区属于这个边缘方向类别,可想而知,一个小区可以同时属于几个类别。由此,便有如下划分方法:若nnd大于T1,则直方图中含有无方向信息的区域值加1;若nh大于T2,则直方图中含有水平方向边缘信息的区域值加1;若nv大于T2,则直方图中含有垂直方向边缘信息的区域值加1;若nd-45大于T3,则直方图中含有45度方向边缘信息的区域值加1;若nd-135大于T3,则直方图中含有135度方向边缘信息的区域值加1。

3. CEDD 特征

CEDD的英文全称是Color and Edge Directivity Descriptor,即颜色和边缘方向特征描述符。它结合了图像的颜色和纹理信息,生成一个144位的直方图。这个特征提取方法可以分为两个子模块系统,提取颜色信息的是颜色模块,提取纹理信息的是纹理模块,这两个单元的具体算法已经在3.1小节和3.2小节进行了详细讲述。CEDD直方图信息由六个区域组成,也就是3.2中讲到的纹理模块,六个区域就是提取出的6维向量直方图,然后在这些纹理信息的每一维中再加入颜色模块提取出的24维颜色信息,这样就可以将颜色和纹理有效结合起来,最终得出6*24=144维的直方图信息。其原理如图3-11所示。
在这里插入图片描述
在实现过程中先将图片分成若干小区,小区的数量是根据图像具体情况和计算机能力综合决定的,每一个图像小区都会经过纹理模块和颜色模块的处理。

小区在纹理模块特征提取过程中会先分为4个子小区。根据YIQ计算公式得出每个像素的灰度值,求出每个子小区的平均灰度值。再经过5个数字滤波器过滤后,根据图3-10的原理判断该子小区属于哪些纹理信息类别。

在颜色模块中,每个图像小区都会转换为HSV色彩空间,系统会将小区内HSV各通道的平均值通过10-bins模糊过滤器输出的10维向量再通过24-bins模糊过滤器中。通过10-bins模糊过滤器后根据H值得出了 10个色彩类别,当通过24-bins模糊过滤器时会根据S和V的区域判定对H进行再分类输出24维的直方图。

图像的每一个小区都会经过颜色模块的处理,处理后将24个数据分别加入到该小区所属的各纹理类别中,最后对直方图进行归一化处理。

如果只进行到归一化这一步并不能体现出CEDD的优越性,因为这里面的值含有小数部分,要占用大量的存储空间。如果对其进行量化,则量化后的整数值既方便存储,又可以让人们直观的读取特征值。表3-1是CEDD特征提取后的量化表,量化范围是0-7的整数。可以看出它并不是一个均匀量化,向量中每一纹理区域的量化范围都是不同的,而且区域内的量化级也不是等比递增,有关它的原理可以参考文献。

在这里插入图片描述

原文引用

李东阳. (2012). Android 手机上图像分类技术的研究 [D] (Doctoral dissertation, 北京邮电大学).

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Python实现的SM4算法加密和解密的示例代码: ```python import struct def left_rotate(x, n): """左旋转n位操作""" return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n)) def sm4_key_schedule(key): """生成32个轮密钥""" # 固定轮密钥 FK = [0xA3B1BAC6, 0x56AA3350, 0x677D9197, 0xB27022DC] # 扩展轮密钥 CK = [ 0x00070E15, 0x1C232A31, 0x383F464D, 0x545B6269, 0x70777E85, 0x8C939AA1, 0xA8AFB6BD, 0xC4CBD2D9, 0xE0E7EEFD, 0xFC030A11, 0x181F262D, 0x343B4249, 0x50575E65, 0x6C737A81, 0x888F96AD, 0xA4ABB2C9, 0xC0C7CEDD, 0xDCE3FAF1, 0xF8FF060D, 0x141B2229, 0x30373E45, 0x4C535A61, 0x686F767D, 0x848B9289, 0xA0A7B4A5, 0xBCC9D0C1, 0xD8DFECFD, 0xF4FB0219, 0x10171E35, 0x2C333A51, 0x484F566D, 0x646B7289, ] # 轮密钥初始化 K = [0] * 36 for i in range(4): K[i] = key[i] ^ FK[i] for i in range(32): K[i + 4] = K[i] ^ left_rotate(K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i], 15) return K def sm4_round(X): """SM4加密轮函数""" # 置换函数 def Sbox(x): SboxTable = [ 0xD6, 0x90, 0xE9, 0xFE, 0xCC, 0xE1, 0x3D, 0xB7, 0x16, 0xB6, 0x14, 0xC2, 0x28, 0xFB, 0x2C, 0x05, 0x2B, 0x67, 0x9A, 0x76, 0x2A, 0xBE, 0x04, 0xC3, 0xAA, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9C, 0x42, 0x50, 0xF4, 0x91, 0xEF, 0x98, 0x7A, 0x33, 0x54, 0x0B, 0x43, 0xED, 0xCF, 0xAC, 0x62, 0xE4, 0xB3, 0x1C, 0xA9, 0xC9, 0x08, 0xE8, 0x95, 0x80, 0xDF, 0x94, 0xFA, 0x75, 0x8F, 0x3F, 0xA6, 0x47, 0x07, 0xA7, 0xFC, 0xF3, 0x73, 0x17, 0xBA, 0x83, 0x59, 0x3C, 0x19, 0xE6, 0x85, 0x4F, 0xA8, 0x68, 0x6B, 0x81, 0xB2, 0x71, 0x64, 0xDA, 0x8B, 0xF8, 0xEB, 0x0F, 0x4B, 0x70, 0x56, 0x9D, 0x35, 0x1E, 0x24, 0x0E, 0x5E, 0x63, 0x58, 0xD1, 0xA2, 0x25, 0x22, 0x7C, 0x3B, 0x01, 0x21, 0x78, 0x87, 0xD4, 0x00, 0x46, 0x57, 0x9F, 0xD3, 0x27, 0x52, 0x4C, 0x36, 0x02, 0xE7, 0xA0, 0xC4, 0xC8, 0x9E, 0xEA, 0xBF, 0x8A, 0xD2, 0x40, 0xC7, 0x38, 0xB5, 0xA3, 0xF7, 0xF2, 0xCE, 0xF9, 0x61, 0x15, 0xA1, 0xE0, 0xAE, 0x5D, 0xA4, 0x9B, 0x34, 0x1A, 0x55, 0xAD, 0x93, 0x32, 0x30, 0xF5, 0x8C, 0xB1, 0xE3, 0x1D, 0xF6, 0xE2, 0x2E, 0x82, 0x66, 0xCA, 0x60, 0xC0, 0x29, 0x23, 0xAB, 0x0D, 0x53, 0x4E, 0x6F, 0xD5, 0xDB, 0x37, 0x45, 0xDE, 0xFD, 0x8E, 0x2F, 0x03, 0xFF, 0x6A, 0x72, 0x6D, 0x6C, 0x5B, 0x51, 0x8D, 0x1B, 0xAF, 0x92, 0xBB, 0xDD, 0xBC, 0x7F, 0x11, 0xD9, 0x5C, 0x41, 0x1F, 0x10, 0x5A, 0xD8, 0x0A, 0xC1, 0x31, 0x88, 0xA5, 0xCD, 0x7B, 0xBD, 0x2D, 0x74, 0xD0, 0x12, 0xB8, 0xE5, 0xB4, 0xB0, 0x89, 0x69, 0x97, 0x4A, 0x0C, 0x96, 0x77, 0x7E, 0x65, 0xB9, 0xF1, 0x09, 0xC5, 0x6E, 0xC6, 0x84, 0x18, 0xF0, 0x7D, 0xEC, 0x3A, 0xDC, 0x4D, 0x20, 0x79, 0xEE, 0x5F, 0x3E, 0xD7, 0xCB, 0x39, 0x48, ] return SboxTable[x] # 线性变换函数 def L(x): return x ^ left_rotate(x, 2) ^ left_rotate(x, 10) ^ left_rotate(x, 18) ^ left_rotate(x, 24) # 置换P函数 def P(x): return x ^ left_rotate(x, 13) ^ left_rotate(x, 23) # S盒变换 for i in range(4): X[i] = Sbox(X[i]) # 线性变换 X[0] ^= L(X[1] ^ X[2] ^ X[3]) X[1] ^= L(X[0] ^ X[2] ^ X[3]) X[2] ^= L(X[0] ^ X[1] ^ X[3]) X[3] ^= L(X[0] ^ X[1] ^ X[2]) # 置换P函数 for i in range(4): X[i] = P(X[i]) return X def sm4_encrypt_block(M, K): """SM4加密一个分组""" # 分组拆分 X = struct.unpack('>IIII', M) # 生成轮密钥 RK = sm4_key_schedule(K) # 32次加密轮函数 for i in range(32): X = sm4_round(X) X[0], X[1], X[2], X[3] = X[1], X[2], X[3], X[0] ^ RK[i + 4] # 合并分组 C = struct.pack('>IIII', X[3], X[2], X[1], X[0]) return C def sm4_decrypt_block(C, K): """SM4解密一个分组""" # 分组拆分 X = struct.unpack('>IIII', C) # 生成轮密钥 RK = sm4_key_schedule(K) # 32次解密轮函数 for i in range(31, -1, -1): X[0] = X[0] ^ RK[i + 4] ^ left_rotate(X[1] ^ X[2] ^ X[3], 13) X[1], X[2], X[3], X[0] = X[0], X[1], X[2], X[3] X = sm4_round(X) # 合并分组 M = struct.pack('>IIII', X[3], X[2], X[1], X[0]) return M def sm4_encrypt(M, K): """SM4加密""" # 补位 padding_len = 16 - len(M) % 16 M = M + bytes([padding_len] * padding_len) # 分组加密 C = b'' for i in range(0, len(M), 16): C += sm4_encrypt_block(M[i:i+16], K) return C def sm4_decrypt(C, K): """SM4解密""" # 分组解密 M = b'' for i in range(0, len(C), 16): M += sm4_decrypt_block(C[i:i+16], K) # 去除填充 padding_len = M[-1] return M[:-padding_len] ``` 使用示例: ```python key = bytes.fromhex('0123456789abcdef0123456789abcdef') plaintext = b'Hello, SM4!' ciphertext = sm4_encrypt(plaintext, key) decryptedtext = sm4_decrypt(ciphertext, key) print(ciphertext.hex()) # 输出: 6576d8548afcd64f0e6b8711f0d2e5a3 print(decryptedtext) # 输出: b'Hello, SM4!' ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值