简单而快速的方法来比较图像的相似性
我需要一种简单而快速的方式来比较两张图片的相似度。 也就是说,如果它们包含完全相同的东西,但可能会有一些稍微不同的背景,并且可能会被几个像素移动/调整大小,我希望获得高价值。
(更具体一点,如果这很重要:一张图片是一个图标,另一张图片是截图的一个分区,我想知道这个分区究竟是不是图标。)
我手边有OpenCV ,但我仍然不习惯它。
到目前为止,我考虑过的一种可能性是:将两幅图片分成10x10个单元格,对于这100个单元格中的每一个,比较颜色直方图。 然后我可以设置一些补偿阈值,如果我得到的值高于该阈值,我认为它们是相似的。
我还没有尝试过,但它的效果如何,但我想这会足够好。 图像已经非常相似(在我的用例中),所以我可以使用相当高的阈值。
我想有很多其他可能的解决方案可以或多或少地工作(因为任务本身非常简单,因为我只是想检测相似性,如果它们非常相似)。 你会建议什么?
从图像中获取签名/指纹/散列有几个相关/相似的问题:
另外,我偶然发现了这些具有获取指纹功能的实现:
关于感知图像哈希的一些讨论:这里
有点偏离主题:有很多方法可以创建音频指纹。 MusicBrainz,一种为歌曲提供基于指纹的查找的网络服务,在他们的wiki中有很好的概述。 他们现在正在使用AcoustID。 这是为了找到确切的(或者大多数确切的)匹配。 为了找到类似的匹配(或者如果你只有一些片段或高噪音),看看Echoprint。 一个相关的SO问题在这里。 所以这似乎解决了音频。 所有这些解决方案都很好。
一般来说,关于模糊搜索的更通用的问题在这里。 例如存在局部敏感散列和最近邻居搜索。
屏幕截图或图标是否可以转换(缩放,旋转,偏斜...)? 有很多方法可以帮助你:
其中大部分已经在OpenCV中实现 - 例如参见cvMatchTemplate方法(使用直方图匹配):http://dasl.mem.drexel.edu/~noahKuntz/openCVTut6.html。 显着点/区域检测器也可用 - 请参阅OpenCV特征检测。
我最近面临同样的问题,为了解决这个问题(简单而快速的算法来比较两张图片),我贡献了一个img_hash模块来opencv_contrib,你可以从这个链接中找到细节。
img_hash模块提供了六个图像哈希算法,相当容易使用。
代码示例
起源lena
模糊莱娜
调整lena的大小
转移lena
#include <opencv2/core.hpp>
#include <opencv2/core/ocl.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/img_hash.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
void compute(cv::Ptr<cv::img_hash::ImgHashBase> algo)
{
auto input = cv::imread("lena.png");
cv::Mat similar_img;
//detect similiar image after blur attack
cv::GaussianBlur(input, similar_img, {7,7}, 2, 2);
cv::imwrite("lena_blur.png", similar_img);
cv::Mat hash_input, hash_similar;
algo->compute(input, hash_input);
algo->compute(similar_img, hash_similar);
std::cout<<"gaussian blur attack : "<<
algo->compare(hash_input, hash_similar)<<std::endl;
//detect similar image after shift attack
similar_img.setTo(0);
input(cv::Rect(0,10, input.cols,input.rows-10)).
copyTo(similar_img(cv::Rect(0,0,input.cols,input.rows-10)));
cv::imwrite("lena_shift.png", similar_img);
algo->compute(similar_img, hash_similar);
std::cout<<"shift attack : "<<
algo->compare(hash_input, hash_similar)<<std::endl;
//detect similar image after resize
cv::resize(input, similar_img, {120, 40});
cv::imwrite("lena_resize.png", similar_img);
algo->compute(similar_img, hash_similar);
std::cout<<"resize attack : "<<
algo->compare(hash_input, hash_similar)<<std::endl;
}
int main()
{
using namespace cv::img_hash;
//disable opencl acceleration may(or may not) boost up speed of img_hash
cv::ocl::setUseOpenCL(false);
//if the value after compare <= 8, that means the images
//very similar to each other
compute(ColorMomentHash::create());
//there are other algorithms you can try out
//every algorithms have their pros and cons
compute(AverageHash::create());
compute(PHash::create());
compute(MarrHildrethHash::create());
compute(RadialVarianceHash::create());
//BlockMeanHash support mode 0 and mode 1, they associate to
//mode 1 and mode 2 of PHash library
compute(BlockMeanHash::create(0));
compute(BlockMeanHash::create(1));
}
在这种情况下,ColorMomentHash给我们最好的结果
每种算法的优缺点
img_hash的表现也不错
与PHash库进行速度比较(来自ukbench的100张图片)
如果你想知道这些算法的推荐阈值,请查看这篇文章(http://qtandopencv.blogspot.my/2016/06/introduction-to-image-hash-module-of.html)。 如果您对如何衡量img_hash模块的性能(包括速度和不同的攻击)感兴趣,请查看此链接(http://qtandopencv.blogspot.my/2016/06/speed-up-image-hashing-of -opencvimghash.html)。
屏幕截图是否只包含图标? 如果是这样,那么这两个图像的L2距离就足够了。 如果L2距离不起作用,下一步就是尝试一些简单而完善的方法,如:Lucas-Kanade。 我确信在OpenCV中可以找到它。
链接地址: http://www.djcxy.com/p/64023.html上一篇: Simple and fast method to compare images for similarity