这件事情的起因是我想复习一下我在亚太杯数学建模当中使用过的CCV这种方法,但是CSDN平台上找了半天都没有,所以后来决定Google一下,终于找到了,甚至还有实现的代码,因此放上来。原文见Dr. Mahmoud Attia的博客。
一、颜色聚合向量的定义
颜色相干向量(CCV)是一种比颜色直方图更复杂的方法。它通过将每个像素分类为相干或不相干来进行工作。相干像素意味着它是一个大的连通分量(CC)的一部分,而不相干像素意味着它是一个小的连通组件的一部分。这种方法能够正常工作的一个关键步骤是我们决定一个连通分量是否大的标准。
二、颜色聚合向量如何在图像中提取特征
这些步骤旨在构建图像的低维表示。
- 对图像进行模糊处理(通过用周围相邻像素的平均值替换每个像素的值)。
- 将颜色空间(图像的颜色)量化为n个不同的颜色。
- 将每个像素分类为相干或不相干,这是通过以下步骤计算的:
- 对每个量化颜色找到连通分量。
- 确定 τ \tau τ 值( τ \tau τ 是用户指定的值,通常为图像大小的1%),对于像素数大于等于 τ \tau τ 的任何连通组件,其像素被视为相干,否则视为不相干。
- 对于每种颜色,计算两个值(C和N):
- C是相干像素的数量。
N是不相干像素的数量。 - 显然,C和N中所有颜色的总和应等于像素的数量。
以上是这个方法的步骤,用于构建图像的低维表示。
三、聚合向量计算举例
假设我们的图片有30个不同的颜色,见下图:
现在我们将颜色量化为仅三种颜色(0:9、10:19、20:29)。这种量化实质上是将相似的颜色组合为单一的代表性颜色。
假设我们的
τ
\tau
τ 值为4,
-
对于颜色0,我们有2个连通组件(8个相干像素)。
-
对于颜色1,我们有1个连通组件(8个相干像素)。
-
对于颜色2,我们有2个连通组件(6个相干像素和3个不相干像素)。
因此,我们的最终特征向量为:
四、定义一个距离方程
拥有距离函数的目的是量化任意两个图像之间的差异性。它补充了颜色描述符的实用性,例如,颜色描述符可以提取所有图像的特征并将其存储在数据库中,然后在图像检索阶段,距离函数将用于检索与原始查询图像具有最小距离的图像。
为了构建CCV的距离函数,我们使用计算得到的相干性和不相干性特征(每种颜色的C和N)在我们的距离函数中比较任意两个图像(假设它们分别为 a a a 和 b b b,在下面的方程中表示)。
- C i C_i Ci:颜色为 i i i 的相干像素数量
- N i N_i Ni:颜色为 i i i 的非相干像素数量
D ( a , b ) = ∑ i = 0 n ( ∣ a C i − b C i ∣ ) + ( ∣ a N i − b N i ∣ ) D(a, b)=\sum_{i=0}^{n}\left(\left|a_{C_{i}}-b_{C_{i}}\right|\right)+\left(\left|a_{N_{i}}-b_{N_{i}}\right|\right) D(a,b)=i=0∑n(∣aCi−bCi∣)+(∣aNi−bNi∣)
五、颜色聚合向量的缺点
现在我们知道,颜色相干向量方法考虑了像素之间颜色空间分布的信息,但该方法也有一些缺点。本文的剩余部分将讨论其两个主要缺点。
CCV中的相干像素代表图像中可以被注意到的连通分量内的像素。然而,如果我们将所有这些组件合并为一个组件,最终我们将只得到一个更大的组件,其像素数量将等于两个原始大组件中的像素数量。
为了更清楚地说明,让我们看一下以下这些图片(假设
τ
\tau
τ 等于8)。
尽管它们是不同的图片,但它们具有相同的CCV。
可以清楚地看到,这个问题可以通过调整阈值 τ \tau τ 来解决,但调整它并不是一件简单的事情,因为在许多情况下,您需要在多个阈值之间进行选择,而每个阈值仍然不能完全正确地捕捉到图像数据集中大组件和小组件之间的差异。
我们可能遇到的另一个问题是这些可见的连接组件相对于彼此的位置。
以下图片具有相同的CCV,但外观不同:
有许多解决这个问题的方法。例如,可以在特征向量中添加另一个维度,以捕捉组件相对位置的信息,从而打破这种限制关系。
附录
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%ColorCoherenceVector
%====================
%
%Color Coherence Vector is a powerful color-based image retrieval
%Parallel implementation based on this paper : Comparing Images Using Color Coherence Vectors (1996) - http://goo.gl/LkWkbi -
%CCV = getCCV(img, coherentThreshold, numberOfPixels)
%getCCV function takes an image and return the Color Coherence Vector that describe this Image. You can compare images using this vector.
%
%Input:
%img : The Image (3-channel Image)
%
%Optional Input:
%coherentPrec: The percentage of the image size to consider a component's pixels are coherent (default = 1%)
%numberOfColors: The number of different colors in the Color Coherence Vector (default = 27 colors).
% Note it'll be changed a little bit to ensure the same different values for RGB channel
%
%Output :
%CCV: a (2*numberOfColors) matrix represents your image. This can be used for matching.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%coherentPrec,认为一个颜色像素是聚合情况下,图像尺寸大小占比
function CCV = getCCV(img,coherentPrec, numberOfColors)
%
if ~exist('coherentPrec','var')
coherentPrec = 1;
end
if ~exist('numberOfColors','var')
numberOfColors = 27;
end
CCV = zeros(2,numberOfColors);
Gaus = fspecial('gaussian',[5 5],2);%2表示高斯滤波器的标准差
img = imfilter(img,Gaus,'same');
[img, updNumOfPix]= discretizeColors(img,numberOfColors);
imgSize = (size(img,1)*size(img,2));
thresh = int32((coherentPrec/100) *imgSize);%计算出认定颜色是聚合像素的门限值
parfor i=0:updNumOfPix-1
BW = img==i;
CC = bwconncomp(BW);%查找二值图像 BW 中的连通分量 CC 并对其计数
compsSize = cellfun(@numel,CC.PixelIdxList);
incoherent = sum(compsSize(compsSize>=thresh));
CCV(:,i+1) = [incoherent; ...
sum(compsSize) - incoherent];
end
end