多分辨率图像的快速查询
原始论文:http://research.microsoft.com/apps/pubs/?id=69465
原始项目介绍:http://grail.cs.washington.edu/projects/query/
基于该成果的一些实现:
http://www.visgraf.impa.br/Courses/ipcg-query-1998/(课程作业,没有找到源码)
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.107.2241&rep=rep1&type=pdf (源码链接失效,python)
http://eikon.recursion.org/ (有源码,实现较为复杂,且运行出错,没有仔细研究出错原因,java)
基于该成果的扩展实现:
Fast Nonparametric Machine Learning Algorithms for High-dimensional Massive Data and Applications(Ting liu)(重点是knn)
目的:由扫描的低分辨率图像或者手绘的粗糙图像搜索到相应的高分辨率图像
算法描述:
包括预处理与搜索两部分,预处理是对图像信息的提取,搜索是计算匹配程度
预处理:
1、调整图片为预定义的大小(64×64)
调整图片意味着分辨率的下降,也意味着处理数据的减少,我采用的参数是64×64,或许128×128效果更好。
以下两种方法我都试了,差别不大,不过鉴于第一种是eikon用过的,最后还是采用它了
public static BufferedImage scale(BufferedImage image)
{
double xscale;
double yscale;
xscale = (double)64 / (double)image.getWidth();
yscale = (double)64 / (double)image.getHeight();
AffineTransformOp op = new
AffineTransformOp(AffineTransform.getScaleInstance(xscale, yscale),
null);
return op.filter(image, null);
}
public BufferedImage resize(Image original, int width, int height, ImageObserver observer) {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bufferedImage.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(original, 0, 0, width, height, observer);
return bufferedImage;
}
2、将BGR颜色转换为YIQ颜色
通过实验,论文认为YIQ颜色模型效果最好。
YIQ与BGR的转换:
array_YIQ[0][i][j]=(0.299*array_BGR[0][i][j]+0.587*array_BGR[1][i][j]+0.114*array_BGR[2][i][j])/256;
array_YIQ[1][i][j]=(0.596*array_BGR[0][i][j]-0.274*array_BGR[1][i][j]-0.322*array_BGR[2][i][j])/256;
array_YIQ[2][i][j]=(0.212*array_BGR[0][i][j]-0.523*array_BGR[1][i][j]+0.311*array_BGR[2][i][j])/256;
得到三个矩阵,分别对应Y、I、Q颜色通道
3、进行haar小波分解
依次处理各矩阵,先对每一行分解,再对每一列分解
private static double[] decomposeArray(double[] bs) {
int h=bs.length;
double t=Math.sqrt(h);
final double SQRT_2=Math.sqrt(2);
double[] bs_new=new double[h];
for(int i=0;i<h;i++)
bs[i]=bs[i]/t;
while(h>1){
h=h/2;
for(int i=0;i<h-1;i++){
bs_new[i]=(bs[2*i]+bs[2*i+1])/SQRT_2;
bs_new[h+i]=(bs[2*i]-bs[2*i+1])/SQRT_2;
}
}
return bs_new;
}
4、保留除(0,0)以外的最大的m个系数
对每个颜色矩阵,元素(0,0)为该颜色的平均值。
选择除(0,0)以外最大的m个元素,其他元素全部置为0。试了两种方法:1是选择排序,选m个最大值;2是先全部排好序,再保留前m个值。第二种实现比较容易。
作者建议m=60甚至40,但我的实验结果看来m=200比较合适(因为我的查询图片既不是扫描也不是素描,我想查到相似的多副图片,不一定是原图)如果不考虑效率m还可以更大一点,其实图片数目很少机器配置又不错的时候,m=2000也可以很快跑完。
5、量化系数为+1/-1
对颜色矩阵进一步处理:
value>0 +1
value<0 -1
6、将图片添加到6个搜索数组中,每个数组对应一个颜色通道的正/负值,如Y+对应系数为+的Y通道,若图片Y通道的(8,9)为+1,它将被添加到Y+的元素(8,9)中
信息也不多,用数据库太麻烦,我将处理过的图片信息保存为磁盘文件,当查询时再读入
搜索:
1、获取查询图像
2、通过预处理得到查询图像信息
同样是进行预处理,获得三个量化过的颜色矩阵
3、根据查询图像,计算已存图像的度量分数(计算公式见论文)
4、按分数由低到高排列,越低越匹配
5、返回前n个结果给用户
结果分析:
这种方法在查找相同但是有些变化的图片(比如太阳、同一建筑物)时表现理想,但对相似的图片(如风格相似的不同图片)基本没有作用。此外,当背景颜色范围广、相差大时,效果也不理想。