自动识别图像中的模式

9 投票
2 回答
20210 浏览
提问于 2025-04-16 01:19

最近我从CIA世界概况下载了一些国旗。现在我想对这些国旗进行“分类”。

  1. 提取颜色
  2. 提取一些形状(比如星星、月亮等)

在浏览的时候,我发现了Python图像库,它可以让我提取颜色(比如奥地利的国旗):

#!/usr/bin/env python
import Image
bild = Image.open("au-lgflag.gif").convert("RGB")
bild.getcolors()
[(44748, (255, 255, 255)), (452, (236, 145, 146)), (653, (191, 147, 149)), ...)]

我觉得奇怪的是,奥地利的国旗只有两种颜色,但上面的输出却显示了十多种颜色。你知道这是为什么吗?我本来想只统计前五种颜色,因为我对每一种颜色都不感兴趣,所以我打算把颜色的数值“归一化”,变成64的倍数(比如把(236, 145, 146)变成(192, 128, 128))。

不过目前我还不知道怎么提取更多的信息(比如图像中有没有星星?等等)。你能给我一些建议吗?

提前谢谢你!

2 个回答

7

首先,简单介绍一些术语,以防你不太了解:

分类器的作用是学习输入和输出之间的关系。你通过提供输入/输出的配对来训练分类器,比如颜色信息这样的特征向量和像“捷克国旗”这样的标签。实际上,这些标签通常用数字来表示。在你的例子中,你面临的是一个多类问题,这意味着可能的标签不止两个(显然,因为有多个国家的国旗)。训练一个多类分类器比普通的二分类器要复杂一些,所以你可能想搜索一下“多类分类器”或者“一个对多个分类器”等相关术语,来找到最适合你的方法。

接下来谈谈问题:

我觉得你的问题可以通过一个简单的分类器来轻松解决,比如k近邻算法,使用颜色直方图作为特征向量。特别是,我建议使用HSV特征向量,而不是RGB特征向量。文献中有很多使用这种简单分类器系统取得良好结果的例子,比如:基于直方图的图像分类中的支持向量机。在那篇论文中,作者使用了一种叫做支持向量机(SVM)的特定分类器和HSV特征向量。HSV特征向量还可以避免图像缩放和旋转的问题,比如一面1024x768的国旗和一面640x480的国旗,或者一面旋转了45度的国旗。

训练算法的伪代码大致如下:

# training simple kNN -- just compute feature vectors, collect labels
X = []    # tuple (input example, label)
for training_image in data:
    x = get_hsv_vector(training_image)
    y = get_label(training_image)
    X.append((x,y))

# classification -- pick k closest feature vectors 
K = 3     # the 'k' in kNN -- how many similar featvecs to use
d = []    # (distance, label) tuples for scoring
x_test = get_hsv_vector(test_image)    # feature vector to be classified
for x_train in X:
    d.append((distance(x_test[0], x_train), x_test[1])

# sort distances, d, by closeness and pick top K labels for scoring
d.sort()
output = get_majority_vote([x[1] for x in d[:K]])

kNN分类器在几个Python库中都有提供,并且文档也很完善。将颜色转换为HSV色彩空间应该也很简单。如果你没有达到预期的结果,可以尝试改进你的特征向量或分类器。

8

Python图像库(PIL)主要用于一些基本的图像处理,比如打开图片、进行一些简单的变换或滤镜处理,以及保存为其他格式。

而模式识别则属于更高级的图像处理领域,它正在不断发展——它使用的算法和PIL的完全不同。

在Python中,有一些库和框架可以用来进行模式识别,比如识别星星、月亮等等。不过我建议你,如果只是想分类一百多个国家的国旗,手动处理会更简单,而不是去尝试复杂的模式识别。

你提到的颜色数量说明你对计算机图像并不熟悉。模式识别是个比较复杂的领域,即使用Python来做也不简单。(你不能指望现有的框架能提前知道什么是“月亮”或“星星”等等)

所以,对于少于500张图片,你可以使用一些软件手动给图片打标签,然后写一些代码把这些标签和每面国旗关联起来。

关于颜色:计算机中的栅格图像是由像素组成的。这些像素是方形的。当不同颜色的边界相遇时,如果一个像素是某种颜色(比如白色),而它的邻居是完全不同的颜色(比如红色),那么这个边界就会显得锯齿状。这种现象叫做“锯齿效应”。为了减少这种现象,计算机软件会在颜色的硬边界处混合颜色,生成中间色——这就是为什么即使一个PNG图像看起来只有两种颜色,内部可能却有多种颜色。对于.JPG格式来说,情况更糟,因为我们使用的RGB颜色的四舍五入小数并不是以原样存储在图像中的。

与模式识别不同,你可以通过只使用每个颜色分量的最重要的几位来减少看到的颜色数量。我认为取前两位就足够了。下面这个Python函数可以使用PIL提供的颜色计数来实现:

def get_main_colors(col_list):
    main_colors = set()
    for index, color in col_list:
        main_colors.add(tuple(component >> 6 for component in color))
    return [tuple(component << 6 for component in color) for color in main_colors]

例如,你可以用“get_main_colors(bild.get_colors())”来调用它。

这里还有一个关于模式识别的问题: python图像识别

撰写回答