草庐IT

【OpenCV 例程 300篇】231. 特征描述之灰度共生矩阵(GLCM)

youcans_ 2023-08-15 原文

『youcans 的 OpenCV 例程200篇 - 总目录』


【youcans 的 OpenCV 例程 300篇】231. 特征描述之灰度共生矩阵(GLCM)


4.2.4 灰度共生矩阵(GLCM)

灰度共生矩阵(Gray level co-occurrence matrix,GLCM)是特征检测与分析的重要方法,在纹理分析、特征分类、图像质量评价中应用广泛 。

灰度共生矩阵是一种典型的统计方法,描述空间上具有某种分布规律的灰度值组合出现的概率。

图像的像素具有不同的灰度级,灰度共生矩阵表示不同灰度组合同时出现的频率。简单地说,灰度共生矩阵反映灰度图像中某种形状的像素对在整个图像中出现的次数

灰度共生矩阵的定义是,从灰度为 i i i 的像素点出发,距离 ( a , b ) (a,b) (a,b) 的另一像素点 ( x + a , y + b ) (x+a,y+b) (x+a,y+b) 的灰度为 j j j 的概率。所有的估计值表示为矩阵矩式,称为灰度共生矩阵。

灰度共生矩阵在点 (x,y) 处的值,表示了特定灰度值组合在图像中出现的频次:
P ( i , j ∣ a , b , θ ) = { ( x , y ) ∣ f ( x , y ) = i , f ( x + a , y + b ) = j } , x , y = 0 , 1... L − 1 P(i,j|a,b,\theta) = \{ (x,y)|f(x,y)=i,f(x+a,y+b)=j \}, \quad x,y =0,1...L-1 P(i,ja,b,θ)={(x,y)f(x,y)=i,f(x+a,y+b)=j},x,y=0,1...L1
式中:

a , b a, b a,b 为距离差分值,也称相邻间隔、偏移量,要根据纹理周期分布的特性来选择,无特性参数时取 1(像素);

θ \theta θ 为扫描方向,通常选择 0 o 、 4 5 o 、 9 0 o 、 13 5 o 0^o、45^o、90^o、135^o 0o45o90o135o ,对应以水平、垂直和左右对角线方向扫描像素对组合;

i , j = 0 , . . . L − 1 i,j=0,...L-1 i,j=0,...L1 表示像素的灰度级。灰度级 L=256 时即为灰度值,也可以取其它灰度级如 L=8,16。共生矩阵有方向和步长的组合,是一个稀疏矩阵,灰度级划分常常减少到8级。显然,灰度共生矩阵的尺寸为 L*L,而与图像尺寸无关。

例如,取 a = 1 , b = 1 , θ = 0 o a=1, b=1, \theta=0^o a=1,b=1,θ=0o 时, P ( 1 , 1 ) P(1,1) P(1,1) 是水平相邻像素对的灰度级为 (1,1) 的组合数量, P ( 2 , 8 ) P(2,8) P(2,8) 是水平相邻像素对的灰度级为 (2,8) 的组合数量, P ( i , j ) P(i,j) P(i,j) 是水平相邻像素对的灰度级为 (i,j) 的组合数量。

也就是说,灰度共生矩阵中点 (i,j) 的值,就是灰度值为 i,j 的联合概率密度。因此,灰度共生矩阵能反映出图象灰度关于方向、相邻间隔、变化幅度的综合信息,是分析图象的局部模式和它们排列规则的基础。

粗纹理的区域,像素对趋于具有相同的灰度,灰度共生矩阵对角线上的数值较大;细纹理的区域,对角线上的数值相对较小,对角线两侧的值相对较大。

灰度共生矩阵的数据量很大,一般不直接用它来描述纹理特征,而是构建一些统计量作为纹理分类特征。例如,能量、熵、对比度、均匀性、相关性、方差等。

(1)能量(Energy), 是灰度共生矩阵元素值的平方和,反映图像灰度分布均匀程度和纹理粗细。ASM值大表明一种较均一和规则变化的纹理模式。
E n e r g y = ∑ i , j = 0 N − 1 ( P i j ) 2 Energy = \sum ^{N-1} _{i,j=0} (P_{ij})^2 Energy=i,j=0N1(Pij)2

(2)熵(Entropy),是图像所具有的信息量的度量,反映图像中纹理的非均匀程度或复杂程度。共生矩阵中的元素分布越分散,随机性越大,熵值就越大。
E n t r o p y = ∑ i , j = 0 N − 1 − l n ( P i j ) P i j Entropy = \sum ^{N-1} _{i,j=0} -ln(P_{ij})P_{ij} Entropy=i,j=0N1ln(Pij)Pij

(3)对比度(Contrast),度量灰度共生矩阵的局部变化,反映了图像的清晰度和纹理沟纹深浅的程度。纹理的沟纹越深,对比度越大,视觉效果越清晰。
C o n t r a s t = ∑ i , j = 0 N − 1 P j j ( i − j ) 2 Contrast = \sum ^{N-1} _{i,j=0} P_{jj}(i-j)^2 Contrast=i,j=0N1Pjj(ij)2

(4)相关性(Correlation),度量灰度共生矩阵在行或列方向上的相似程度, 反映了图像中局部灰度相关性 。如果图像具有水平方向的纹理,则水平方向的相关性就会显著地大于其它方向的相关性。
C o r r e l a t i o n = ∑ i , j = 0 M − 1 P ( i , j ) ( i − μ ) ( j − μ ) σ 2 Correlation = \sum_{i,j=0}^{M-1} P(i,j)\frac{(i-\mu)(j-\mu)}{\sigma ^2} Correlation=i,j=0M1P(i,j)σ2(iμ)(jμ)

(5)反差分矩阵(Inverse Differential Moment, IDM),反映了纹理的清晰程度和规则程度。

(6)同质性(Homogeneity),反映了图像纹理的同质性,度量图像纹理局部变化的程度。


例程 14.11:特征描述之灰度共生矩阵(skimage)

skimage 的特征提取库 skimage.feature 提供了函数 greycomatrix 和 greycoprops,可以 计算灰度共生矩阵并提取特征统计量 。

函数说明:

skimage.feature.graycomatrix(image, distances, angles, levels=256, symmetric=False, normed=False)
skimage.feature.graycoprops(P[, prop])

参数说明:

  • image:整型单通道图像,推荐使用 uint8 灰度图像
  • distances:像素对的距离偏移量的列表,计算列表中每个偏移量的 GLCM
  • angles:像素对扫描角度(弧度)列表,计算列表中每个角度值的 GLCM
  • levels:灰度级,默认值为 256
  • symmetric:对称性选项,默认值 False 表示将像素对 (i,j) 与 (j,i) 分别计算,True 表示忽略像素对顺序,将 (i,j) 与 (j,i) 视为相同
  • normed:归一化选项,默认值 False,True 表示对矩阵归一化。
  • prop:元组,灰度共生矩阵 P 的特征统计量, 包括:对比度 ‘contrast’、相异性 ‘dissimilarity’、同质性 ‘homogeneity’、能量 ‘energy’、相关性 ‘correlation’、能量的平方 ‘ASM’}
  • 返回值是 4维数组,即不同偏移量、不同角度的 GLCM。 P [ i , j , d , θ ] P[i,j,d,\theta] P[i,j,d,θ] 是灰度 j 在偏移量 d、角度 θ \theta θ 处出现灰度 i 的次数。

    # 14.11 特征描述之灰度共生矩阵 (skimage)
    from skimage.feature import greycomatrix, greycoprops

    img = cv2.imread("../images/fabric1.png", flags=1)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像
    height, width = gray.shape
    table16 = np.array([(i//16) for i in range(256)]).astype("uint8")  # 16 levels
    gray16 = cv2.LUT(gray, table16)  # 灰度级压缩为 [0,15]

    # 计算灰度共生矩阵 GLCM
    dist = [1, 4]  # 计算 2 个距离偏移量 [1, 2]
    degree = [0, np.pi/4, np.pi/2, np.pi*3/4]  # 计算 4 个方向
    glcm = greycomatrix(gray16, dist, degree, levels=16)  # 灰度级 L=16
    print(glcm.shape)  # (16,16,2,4)

    # 由灰度共生矩阵 GLCM 计算特征统计量
    for prop in ['contrast', 'dissimilarity','homogeneity', 'energy', 'correlation', 'ASM']:
        feature= greycoprops(glcm, prop).round(4)  # (2,4)
        print("{}: {}".format(prop, feature))

    plt.figure(figsize=(9, 6))
    plt.suptitle("GLCM by skimage, youcans")
    for i in range(len(dist)):
        for j in range(len(degree)):
            plt.subplot(2,4,i*4+j+1), plt.axis('off')
            plt.title(r"d={},$\theta$={:.2f}".format(dist[i], degree[j]))
            plt.imshow(glcm[:,:,i,j], 'gray')
    plt.tight_layout()
    plt.show()

运行结果:

(16, 16, 2, 4)
contrast: [[ 4.5689 3.8755 1.7764 7.0276], [12.2668 12.6184 8.0537 13.614 ]]
dissimilarity: [[1.3346 1.3228 0.8727 1.7466], [2.3169 2.4697 1.9752 2.5845]]
homogeneity: [[0.5843 0.5477 0.6474 0.5072], [0.4539 0.4051 0.4422 0.3948]]
energy: [[0.1262 0.1186 0.1388 0.1103], [0.1003 0.0936 0.0997 0.0907]]
correlation: [[0.8558 0.8778 0.9439 0.7783], [0.6133 0.6031 0.7465 0.5717]]
ASM: [[0.0159 0.0141 0.0193 0.0122], [0.0101 0.0088 0.0099 0.0082]]



【本节完】

版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125693533)
Copyright 2022 youcans, XUPT
Crated:2022-7-9

227. 特征描述之 LBP 纹理特征算子
229. 特征描述之 LBP 算子比较(skimage)
231. 特征描述之 灰度共生矩阵(GLCM)

有关【OpenCV 例程 300篇】231. 特征描述之灰度共生矩阵(GLCM)的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  3. ruby - cucumber 特征和步骤定义 - 2

    我是Cucumber测试的新手。我创建了两个特征文件:events.featurepartner.feature并将我的步骤定义放在step_definitions文件夹中:./step_definitions/events.rbpartner.rbCucumber似乎在所有.rb文件中查找步骤信息。有没有办法限制该功能查看特定的步骤定义文件?我之所以要这样做,是因为即使我使用了--guess标志,我也会遇到不明确的匹配错误。我之所以要这样做,有以下几个原因。我正在测试CMS,并希望在不同的功能中测试每种不同的内容类型(事件和合作伙伴)。事件.特征Feature:AddpartnerA

  4. ruby-on-rails - 特征未注册 : attribute name - 2

    完成这个有困难。我正在使用seed.rb+factory_girl来使用rakedb:seed填充数据库。(我知道固定装置存在,但我想以这种方式完成,这只是一个示例,数据库将填充复杂的关联对象。)我的种子.rb:require'factory_girl_rails'["QM","CDC","SI","QS"].eachdo|n|FactoryGirl.create(:grau,nome:n)end还有我的/factories/graus.rbFactoryGirl.definedofactory:graudonomeendend但是当我运行时:rakedb:seed我得到:rakeab

  5. ruby-on-rails - FactoryGirl工厂特征内的序列不使用主序列计数器 - 2

    我有以下工厂:FactoryGirl.definedofactory:foodosequence(:name){|n|"Foo#{n}"}trait:ydosequence(:name){|n|"Fooy#{n}"}endendend如果我跑create:foocreate:foocreate:foo,:y我得到Foo1,Foo2,Fooy1。但我想要Foo1,Foo2,Fooy3。我怎样才能做到这一点? 最佳答案 经过smile2day'sanswer的一些提示后和thisanswer,我得出以下解决方案:FactoryGirl.

  6. ruby-on-rails - Fork、Ruby、ActiveRecord 和 Fork 上的文件描述符 - 2

    我知道当我们fork一个进程时,子进程会继承父进程的打开文件描述符和偏移量的副本。根据手册页,这指的是父级使用的相同文件描述符。基于以下程序中的理论puts"Process#{Process.pid}"file=File.open('sample','w')forked_pid=forkdosleep(10)puts"Writingtofilenow..."file.puts("HelloWorld.#{Time.now}")endfile.puts("Welcometowinterofmydiscontent#{Time.now}")file.closefile=nil问题一:当父进

  7. ruby - 在描述之外使用 RSpec 的 "expect"等...它会阻止 - 2

    我正在构建一个网络应用程序自动化框架,旨在允许:当然是自动化任务轻松构建测试场景我正在使用Capybara与浏览器通信,我有一个组件库,其中包含许多辅助函数(login_to_the_back_office、create_customer等)。现在我希望我的组件可以独立使用,也可以在RSpec测试中使用。这意味着我的组件(包含在库中)没有环绕describe...it...默认情况下会阻塞,但在测试使用它们时它们会在某个时候出现,因此它们应该使用expect和friend尽可能多。我关注了rspec's.shouldfails(outsidedescribe/itblock)inRub

  8. ruby - Ruby 守护进程中的错误文件描述符 - 2

    在MacOSXLion上使用Rubyv1.8.7和Daemonsv1.1.8,我试图编写一个消费者进程并让它作为守护进程运行:#config[:name]=>'idx_my_delete_consumer'#config[:daemon]=>{:multiple=>false,#:backtrace=>true,#:dir_mode=>:normal,#:log_dir=>'/Users/pprakash/consumer.log',#:monitor=>true,#:dir=>'/Users/pprakash/pids'}Daemons.run_proc(config[:name],

  9. ruby - 写密集型特征的架构 - 2

    我在当前项目中使用由Oracle数据库和memcached支持的RubyonRails。有一个非常常用的功能,它依赖于单个数据库View作为数据源,并且该数据源内部有其他数据库View和表。这是一个虚拟数据库View,能够从一个地方访问所有内容,而不是物化数据库View。大多数情况下,如果用户正在使用他们希望更新的功能,那么让数据保持最新很重要。从这个View获取数据时,我将安全表内部连接到View(安全表不是View本身的一部分),其中包含一些我们用来在更细粒度级别上控制数据访问的字段。例如,安全表有user_id,prop_1,prop_2列,其中prop_1,prop_2是数据库

  10. ruby-on-rails - 如何为 Rails 编写 cucumber (最佳实践)。特征和步骤 - 2

    我目前正在尝试学习cucumber以及如何正确利用它。在搜索最佳实践时,大多数旧方法都被描述了,但我还没有真正找到一个好的指南。我阅读了有关执行此操作的新方法,但我对最佳实践有一些疑问。以下是我一直在研究的一些基本cucumber场景。Scenario:UnsuccessfulloginGivenauserhasanaccountWhentheusertriestologinwithinvalidinformationThentheusershouldseeanloginerrormessageScenario:SuccessfulloginGivenauserhasanaccount

随机推荐