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

本文节选自论文《基于半监督和主动学习相结合的图像的检索研究》,并结合我对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=

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DaveBobo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值