您的位置:首页 > 其它

基于图像形状的一种比较漂亮的分类算法

2017-09-22 19:24 399 查看
原文:http://blog.csdn.net/lishuhuakai/article/details/53573241

 


基于图像形状的一种比较漂亮的分类算法

我首先讲一下我所遭遇到的情况吧:

有n类似于下图的图片:



我这里有一个需求就是,将这些图片分类,分类的效果至少也应该是这样的:



将一些形状非常类似的图片分在一起.

我大致查阅了一下挺多的分类算法,这些算法大致分为了两类:

一类是通过对分类器进行训练,比如说要识别猫,那就要喂给分类器非常多的猫的图片,得到一些参数之后才能够比较精确地对图片进行识别.当然,这一大类的方法对于我们所拥有的数据来说,并不适合,我们并没有用于训练的图片.

另外一种方法不用训练,思想和机器学习里面的聚类差不太多,主要通过比较图片的一些特征,计算出与相似度类似的一个度量,来对图片进行分类.

好吧,我们大致只能使用聚类之类的东西来分类了.

究竟怎么来分呢?

说实话,我尝试了一些比较有名的聚类算法,效果都不怎么理想,然后我看到了Hausdorff Distance,这是一种在图像处理中轨迹识别什么的经常用到的距离度量,我只是抱着试一试的心态尝试了一下[b]Hausdorff
Distance加上k均值聚类,结果效果出乎我的意料,效果拔群.上面的效果你也看到了,至少在眼睛上看起来,非常不错.
[/b]

[b]关于[b]Hausdorff Distance,推荐你看这里:[/b][/b]

[b]http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/98/normand/main.html
[/b]

有中文翻译版的:

http://blog.sina.com.cn/s/blog_4062094e0102vkpf.html


k均值聚类应该不用我来讲了,差不多都烂了.

我这里给出Hausdorff Distance的Python代码实现吧:

[python] view
plain copy

 print?

  

[python] view
plain copy

 print?

""" 

    目标: 

    ~~~~~~~~~ 

    实现 Hausdorff 距离.该距离的定义如下: 

    A = {a1, a2, ..., an}, B = {b1, b2, ..., bm} 

    两者的 Hausdorff 距离为: 

    H(A, B) = max{h(A, B), h(B, A)}, 

    其中 

    h(A, B)的定义如下,无法用数学公式来展现,我这里用语言来描述一下得了. 

    对于A中的每一个点a,首先在B中找到一个距离a最近的点b,得到a,b它们之间的距离dist(a, b),这里的dist定义如下: 

    dist(a, b) = sqrt((xa - xb)^2, (ya - yb)^2),就是欧氏距离啦. 

    通过计算得到n个这样的距离,找出其中最大的一个,作为h(A, B),h(B, A)同理. 

"""  

from math import sqrt  

  

def euclidean_metric(pa, pb):  

    ''''' 

    计算两个点的欧式距离. 

    关于输入的pa以及pb,它们应该是一个list或者tuple,长度应该相等. 

    '''  

    return sqrt((pa[0] - pb[0])**2 + (pa[1] - pb[1])**2)  

  

def one_way_hausdorff_distance(sa, sb):  

    '''''计算单向hausdorff距离'''  

    distance = 0.0  

    for pa in sa: # 对于a集合中的每一个点,要求出这个点到  

        shortest = 9999999  

        for pb in sb:  

            dis = euclidean_metric(pa, pb)  

            if dis < shortest:  

                shortest = dis  

        if shortest > distance:  

            distance = shortest  

    return distance  

  

def hausdorff_distance(sa, sb):  

    ''''' 

    计算两个集合中的点的 hausdorff 距离. 

    关于输入的sa以及sb,两者应该是点的list或者tuple,而点的定义参照euclidean_metric. 

    '''  

    dis_a = one_way_hausdorff_distance(sa, sb)  

    dis_b = one_way_hausdorff_distance(sb, sa)  

    return dis_a if dis_a > dis_b else dis_b  

  

  

if __name__ == '__main__':  

    assert(euclidean_metric((1, 1), (1, 6)) == 5)  

    A = [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0)]  

    B = [(0, 3), (1, 3), (2, 3), (3, 3), (3, 2), (4, 2)]  

    C = [(4, 2), (4, 1), (4, 0)]  

    D = [(0, 2), (1, 2), (2, 2), (2, 3), (2, 4)]  

    one_way_hausdorff_distance(A, B)  

另外还有一种度量公式,那就是Fréchet distance.

这是最近才找到的一种距离,将这种距离运用于分类,效果其实比上面的还要好.

它的python实现代码如下:



[python] view
plain copy

 print?

""" 

    Fréchet distance 

"""  

import math  

import numpy as np  

  

# Euclidean distance.  

def euc_dist(pt1,pt2):  

    return math.sqrt((pt2[0]-pt1[0])**2+(pt2[1]-pt1[1])**2)  

  

def _c(ca,i,j,P,Q):  

    if ca[i,j] > -1:  

        return ca[i,j]  

    elif i == 0 and j == 0:  

        ca[i,j] = euc_dist(P[0],Q[0])  

    elif i > 0 and j == 0:  

        ca[i,j] = max(_c(ca,i-1,0,P,Q),euc_dist(P[i],Q[0]))  

    elif i == 0 and j > 0:  

        ca[i,j] = max(_c(ca,0,j-1,P,Q),euc_dist(P[0],Q[j]))  

    elif i > 0 and j > 0:  

        ca[i,j] = max(min(_c(ca,i-1,j,P,Q),_c(ca,i-1,j-1,P,Q),_c(ca,i,j-1,P,Q)),euc_dist(P[i],Q[j]))  

    else:  

        ca[i,j] = float("inf")  

    return ca[i,j]  

  

""" Computes the discrete frechet distance between two polygonal lines 

Algorithm: http://www.kr.tuwien.ac.at/staff/eiter/et-archive/cdtr9464.pdf 

P and Q are arrays of 2-element arrays (points) 

"""  

def frechet_distance(P,Q):  

    ca = np.ones((len(P),len(Q)))  

    ca = np.multiply(ca,-1)  

    return _c(ca,len(P)-1,len(Q)-1,P,Q)  

函数的调用方法和上面Hausdorff Distance的代码一致.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: