在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
问题想编写一个程序,使我可以从图像中提取一组颜色,希望考虑到人类的感知并以一种看起来自然的方式进行操作。配色方案通常可以刻画出整个图像的“氛围”,因此我认为能够从图像提取色彩有趣而且有用。 所以……我花了一些时间思考可以做些什么。我设计了一些相当简单的算法,例如,将图像有规则地切成块,然后输出每个部分的平均颜色。也许还可以添加额外的图层,在这些图层中将块进行比较并组合成组,或者将每种颜色与另一种颜色递归组合,直到达到所需的颜色数量为止。这些基于规则的做法都不太理想,不过我很快发现,这个问题已经有通用的解决方案了,而且通用方案是相当有效的。 那么从图像提取颜色的通用方法是什么呢?请看下文详解。 解决方案K-means聚类就是一种解决此类问题的不错方法,通过该方法可以将一组数据点划分为几个不相交的子集,其中每个子集中的点被视为彼此“接近”(根据某种度量标准)。当处理几何空间中点时,标准欧几里得距离函数是一个常用度量。事实证明,这种方法正是我们需要的从图像提取一组颜色的方法。 具体案例在我们的案例中,“数据点”是颜色,而距离函数则是两种颜色“有多么不同”的度量。我们的任务是将这些颜色分组为给定数量的集合,然后计算每个集合的平均颜色。在每个集合中使用均值似乎是一个相当明智的选择。当然,我们也可以改用任何其他统计量度(众数,中位数或其他任何形式!),也可能得到不错的结果。 以下程序使用JavaScript!代码编写✨ 数据点每个数据点都是一种颜色,可以表示为RGB色彩空间。 在JavaScript中,单个数据点可能看起来像这样:
距离函数由于我们希望能够计算两种颜色的相似程度,因此我们需要一个函数。一个简单的选择就是使用每种颜色的成分值来计算欧式距离。 我们的距离函数如下所示:
由于我们尚未在函数中指定固定数量的组件,因此该组件可用于n-dimensional数据点(具有n个分量)。如果以后我们要用其他方式表示颜色,这很有用。 算法用于k-means聚类的最常见算法称为劳埃德(Lloyd)算法(尽管通常简称为的k-means算法)。我们将在这里使用该算法。 我们将创建一组称为“质心”的对象,每个对象都定义一个唯一的簇。 一个质心与之相关的两件事:
该算法包括三个主要步骤: 1。初始化。选择质心的初始值。在这种情况下,我们只为每个簇选择一个随机点作为质心。 2。分配。将每个数据点分配给离簇均值(质心)距离最小的聚类。 3。更新。将每个质心设置为与其相关联的所有数据点的均值(即质心的所在的簇中点的均值)。 该算法将执行初始化一次,然后执行分配和更新并依次重复,直到算法收敛为止。 当分配质心不再有任何变化时,该算法“收敛”。 辅助函数让我们定义一些辅助函数:用于计算给定数据集范围的函数,另一个用于在给定范围内生成随机整数的函数。 n-dimensional数据集的“范围”——即每个维度对应一个范围。
有了上述准备之后,可以给算法的三个步骤编写代码了。 第一步-初始化对于所需的每个质心(假设质心数为k),我们在提供的数据集范围内生成一个随机的整数值点,并将其附加到数组中。数组中的每个点代表一个质心的位置。当然,质心与数据的维数相同。
第二步-分配这是我们将数据点分配给簇的阶段。对于每个点,我们选择距离最短的质心,然后将点附加到对应的簇。 注:这里我们使用了数组的Map功能以及箭头功能如果您不太确定发生了什么,请点击链接快速浏览一下。
第三步-更新对于每个簇,我们计算其内部数据点的平均值,并将其设置为簇的质心位置。然后,我们返回新的质心集。 实际上,这里使用了另一个函数均值(这里没有给出)。它返回一个点,其成分是每个传递的点中相应成分值的均值。
注意点!这种算法有一个问题,就是有时候簇会变空。对于发生这种情况时该怎么做尚无共识,但是一些可能的方法是:
尽管最后一个选项似乎有些困难,但是该算法(带有随机初始化)是不确定的,因此只需重启就可以很好地工作。 汇总现在,我们已经定义了基本功能,剩下的就是编写一些汇总代码,以根据算法定义在需要时调用每个函数。 我将把它留给您作为练习,参考这里。 🌈 参考资料
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13