您的位置:首页 > 其它

LIRe图像检索:FCTH算法原理与源码分析

2017-04-21 11:46 501 查看
本文节选自论文《基于半监督和主动学习相结合的图像的检索研究》,并结合我对LIRe中FCTH源码进行分析、解读和研究。
       模糊颜色和纹理直方图(Fuzzy Color and Texture Histogram,FCTH),FCTH特征可从3个模糊单元的组合求得结果。先将图像划分成若干分块,在第一个模糊单元中以HSV颜色空间的三个信道为输入,经模糊系统最终产生10-bin的直方图。在第二个模糊单元修改每个颜色的色调后,经模糊系统最终产生24-bin的直方图。以上两个模糊单元在颜色描述子中章节中已详细作了解释,且模糊颜色描述子与CEDD中所提的颜色描述子是同一个概念,在此不再累述。在第三个模糊单元中,将图像分块经Harr小波变换成一组纹理元素,模糊系统以这些纹理元素集为输入将24-bin直方图转换成192-bin的直方图。最后是描述FCTH特征提取的实现。

1 FCTH原理

1.1 模糊纹理分割

模糊系统如图2-8所示,展示了模糊纹理直方图的求解过程,图像分块经Harr小波变换得到三个纹理元素fLH,fHL和fHH。这三个纹理元素作为模糊系统的输入,可得到8-bin直方图,8bins对应的区域分别是:(0)低能量线性区,(1)低能量水平激活区,(2)低能量垂直激活区,(3)低能量水平和垂直激活区,(4)高能量线性区,(5)高能量水平激活区,(6)高能量垂直激活区,(7)高能量水平和垂直激活区。事实证明fLH,fHL和fHH等纹理元素能够有效辨别图像的纹理。



1.2 FCTH的实现

       首先定义与提取颜色信息相关的单元为颜色单元,与提取纹理信息相关的单元为纹理单元,如图2-9所示,纹理单元所在的模糊系统产生了8个区间,颜色单元所在的模糊系统产生了24个独立的区间,这样最终的直方图将产生8*24=192bin区域。为了塑造这个直方图,衡量图像的细节与计算要求,现将图像分割成1600个分块。如果定义纹理单元的bin为N并且颜色单元的bin为M,那么该图像分块的直方图位置将为:N*24+M。

整个FCTH的实现模型如图2-9所示,分为纹理单元模块与颜色单元模块。



a) 在纹理单元模块中,每个图像分块经Harr小波变换得到三个纹理元素fLH,fHL和fHH的值,经模糊关联系统分类可将该图像分块归类于8-bin直方图中的一种。假设该图像分块被归类到第二bin中,则它对应的纹理应为低能量水平激活区。

b)在颜色单元模块中,每个图像分块被转换到HSV颜色空间。信道色调H,饱和度S,亮度V组成模糊系统的输入,得到输出为10-bin的直方图。假设输出结果为第4bin,对应的颜色为红色。第二个模糊系统(24-bin 模糊关联)将原先的每个色调再次分割成3色调,改变亮度V为两个模糊区间,得出输出为24-bin直方图。再假设输出结果为第4bin,此时对应的颜色却为深红色。合并这三个模糊系统最终可将该图像分块归类为27bin(1*24+3)。

c) 反复对图像的所有分块执行(a),(b)两个步骤,得到整张图像的直方图,直方图会归一于{0-1}区间内,而每个直方图可量化为3比特。

1.3 FCTH特征的相似度量

      为了计算FCTH特征向量的相似性距离我们选择使用Tanimoto 系数。

2 源码分析

在lire.jar中FCTH源码的位置如下:



以下为我对源码的分析和解读。

public void extract(BufferedImage bimg) {
bimg = ImageUtils.get8BitRGBImage(bimg);
this.histogram = this.Apply(bimg);
}

public double[] Apply(BufferedImage image) {
//10-bin的直方图
Fuzzy10Bin Fuzzy10 = new Fuzzy10Bin(false);
//24-bin的直方图
Fuzzy24Bin Fuzzy24 = new Fuzzy24Bin(false);
FuzzyFCTHpart FuccyFCTH = new FuzzyFCTHpart();
double[] Fuzzy10BinResultTable = new double[10];
double[] Fuzzy24BinResultTable = new double[24];
//192-bin的直方图
double[] FuzzyHistogram192 = new double[192];
byte Method = 2;
int width = image.getWidth();
int height = image.getHeight();

for(int HSVConverter = 0; HSVConverter < 192; ++HSVConverter) {
FuzzyHistogram192[HSVConverter] = 0.0D;
}

RGB2HSV var48 = new RGB2HSV();
int[] HSV = new int[3];
new WaveletMatrixPlus();
double[][] ImageGrid = new double[width][height];
int[][] ImageGridRed = new int[width][height];
int[][] ImageGridGreen = new int[width][height];
int[][] ImageGridBlue = new int[width][height];
BufferedImage image_rgb = new BufferedImage(width, height, 4);
image_rgb.getGraphics().drawImage(image, 0, 0, (ImageObserver)null);
int[] pixels = ((DataBufferInt)image_rgb.getRaster().getDataBuffer()).getData();

int Step_X;
int Step_Y;
for(int NumberOfBlocks = 0; NumberOfBlocks < width; ++NumberOfBlocks) {
for(Step_X = 0; Step_X < height; ++Step_X) {
int pixel = pixels[Step_X * width + NumberOfBlocks];
int b = pixel >> 16 & 255;
int g = pixel >> 8 & 255;
int r = pixel & 255;
ImageGridRed[NumberOfBlocks][Step_X] = r;
ImageGridGreen[NumberOfBlocks][Step_X] = g;
ImageGridBlue[NumberOfBlocks][Step_X] = b;
Step_Y = (int)(0.114D * (double)b + 0.587D * (double)g + 0.299D * (double)r);
ImageGrid[NumberOfBlocks][Step_X] = (double)Step_Y;
}
}
/*
* 最终的直方图将产生 8*24=192bin 区域。为了塑造这个直方图,
* 衡量图像的细节与计算要求,先将图像分割成 1600 个分块。
*/
short var49 = 1600;
Step_X = (int)Math.floor((double)width / Math.sqrt((double)var49));
Step_Y = (int)Math.floor((double)height / Math.sqrt((double)var49));
if(Step_X % 2 != 0) {
--Step_X;
}

if(Step_Y % 2 != 0) {
--Step_Y;
}

if(Step_Y < 4) {
Step_Y = 4;
}

if(Step_X < 4) {
Step_X = 4;
}

for(int TotalSum = 0; TotalSum < height - Step_Y; TotalSum += Step_Y) {
for(int x = 0; x < width - Step_X; x += Step_X) {
double[][] Quant = new double[4][4];
int[][] BlockR = new int[4][4];
int[][] BlockG = new int[4][4];
int[][] BlockB = new int[4][4];
int[][] BlockCount = new int[4][4];
int[] CororRed = new int[Step_Y * Step_X];
int[] CororGreen = new int[Step_Y * Step_X];
int[] CororBlue = new int[Step_Y * Step_X];
int[] CororRedTemp = new int[Step_Y * Step_X];
int[] CororGreenTemp = new int[Step_Y * Step_X];
int[] CororBlueTemp = new int[Step_Y * Step_X];
int MeanRed = 0;
int MeanGreen = 0;
int MeanBlue = 0;
boolean CurrentPixelX = false;
boolean CurrentPixelY = false;

int TempSum;
int i;
for(TempSum = 0; TempSum < 4; ++TempSum) {
for(i = 0; i < 4; ++i) {
Quant[TempSum][i] = 0.0D;
BlockCount[TempSum][i] = 0;
}
}

TempSum = 0;

int j;
for(i = 0; i < Step_X; ++i) {
for(j = 0; j < Step_Y; ++j) {
byte var53 = 0;
byte var54 = 0;
if(i >= Step_X / 4) {
var53 = 1;
}

if(i >= Step_X / 2) {
var53 = 2;
}

if(i >= 3 * Step_X / 4) {
var53 = 3;
}

if(j >= Step_Y / 4) {
var54 = 1;
}

if(j >= Step_Y / 2) {
var54 = 2;
}

if(j >= 3 * Step_Y / 4) {
var54 = 3;
}

Quant[var53][var54] += ImageGrid[x + i][TotalSum + j];
++BlockCount[var53][var54];
BlockR[var53][var54] = ImageGridRed[x + i][TotalSum + j];
BlockG[var53][var54] = ImageGridGreen[x + i][TotalSum + j];
BlockB[var53][var54] = ImageGridBlue[x + i][TotalSum + j];
CororRed[TempSum] = BlockR[var53][var54];
CororGreen[TempSum] = BlockG[var53][var54];
CororBlue[TempSum] = BlockB[var53][var54];
CororRedTemp[TempSum] = BlockR[var53][var54];
CororGreenTemp[TempSum] = BlockG[var53][var54];
CororBlueTemp[TempSum] = BlockB[var53][var54];
++TempSum;
}
}

for(i = 0; i < 4; ++i) {
for(j = 0; j < 4; ++j) {
Quant[i][j] /= (double)BlockCount[i][j];
}
}

WaveletMatrixPlus Matrix = this.singlePassThreshold(Quant, 1);

for(i = 0; i < Step_Y * Step_X; ++i) {
MeanRed += CororRed[i];
MeanGreen += CororGreen[i];
MeanBlue += CororBlue[i];
}

MeanRed /= Step_Y * Step_X;
MeanGreen /= Step_Y * Step_X;
MeanBlue /= Step_Y * Step_X;
HSV = var48.ApplyFilter(MeanRed, MeanGreen, MeanBlue);
if(!this.Compact) {
//在第一个模糊单元中以 HSV 颜色空间的三个信道为输入,经模糊系统最终产生 10-bin 的直方图。
Fuzzy10BinResultTable = Fuzzy10.ApplyFilter((double)HSV[0], (double)HSV[1], (double)HSV[2], Method);
//在第二个模糊单元修改每个颜色的色调后,经模糊系统最终产生 24-bin 的直方图。
Fuzzy24BinResultTable = Fuzzy24.ApplyFilter((double)HSV[0], (double)HSV[1], (double)HSV[2], Fuzzy10BinResultTable, Method);
//在第三个模糊单元中,将图像分块经 Harr 小波变换成一组纹理元素,模糊系统以这些纹理元素集为输入将 24-bin 直方图转换成 192-bin 的直方图。
FuzzyHistogram192 = FuccyFCTH.ApplyFilter(Matrix.F3, Matrix.F2, Matrix.F1, Fuzzy24BinResultTable, Method, 24);
} else {
Fuzzy10BinResultTable = Fuzzy10.ApplyFilter((double)HSV[0], (double)HSV[1], (double)HSV[2], Method);
FuzzyHistogram192 = FuccyFCTH.ApplyFilter(Matrix.F3, Matrix.F2, Matrix.F1, Fuzzy10BinResultTable, Method, 10);
}
}
}

double var50 = 0.0D;

int var51;
for(var51 = 0; var51 < 192; ++var51) {
var50 += FuzzyHistogram192[var51];
}

for(var51 = 0; var51 < 192; ++var51) {
FuzzyHistogram192[var51] /= var50;
}

FCTHQuant var52 = new FCTHQuant();
FuzzyHistogram192 = var52.Apply(FuzzyHistogram192);
return FuzzyHistogram192;
}
Reference:

http://blog.csdn.net/leixiaohua1020/article/details/16883143
http://kns.cnki.net/KCMS/detail/detail.aspx?dbcode=CMFD&dbname=CMFD2011&filename=1011042472.nh&uid=WEEvREcwSlJHSldRa1FhdXNXYXJwTmxwNmcxQUU0VCtNVGNPSmIvM3pORT0=$9A4hF_YAuvQ5obgVAqNKPCYcEjKensW4ggI8Fm4gTkoUKaID8j8gFw!!&v=MTk2MjRIN084SE5YTHJaRWJQSVI4ZVgxTHV4WVM3RGgxVDNxVHJXTTFGckNVUkwyZlkrUnVGeW5uVXJ6TFZGMjY=
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: