zoukankan      html  css  js  c++  java
  • Atitit 判断判断一张图片是否包含另一张小图片

    Atitit 判断判断一张图片是否包含另一张小图片 

     

    1. keyword1

    2.  模板匹配是在图像中寻找目标的方法之一(切割+图像相似度计算)1

    3. 匹配效果2

    4. 图片相似度的算法(感知哈希算法Perceptual hash algorithm2

    5. 性能结果2

    6. 如何提升性能3

    6.1. 可以采用简化的算法。二次匹配法,先大概确定区域3

    6.2. 切割图片设置一个step3

    7. 参考资料3

    8. ------code3

     

    1. keyword

     

    图像匹配

    图片是否另外一张图片的一部分

    如果是标准图片,模板匹配就好

     

    2.  模板匹配是在图像中寻找目标的方法之一(切割+图像相似度计算)

    Come On, Boy.我们一起来看看模板匹配到底是怎么回事。

    模板匹配的工作方式
        模板匹配的工作方式跟直方图的反向投影基本一样,大致过程是这样的:通过在输入图像上滑动图像块对实际的图像块和输入图像进行匹配。
        假设我们有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
      1)从输入图像的左上角(0,0)开始,切割一块(0,0)(10,10)的临时图像;
      2)用临时图像和模板图像进行对比,对比结果记为c
      3)对比结果c,就是结果图像(0,0)处的像素值;
      4)切割输入图像从(0,1)(10,11)的临时图像,对比,并记录到结果图像;
      5)重复(1)~(4)步直到输入图像的右下角。
        大家可以看到,直方图反向投影对比的是直方图,而模板匹配对比的是图像的像素值;模板匹配比直方图反向投影速度要快一些,但是我个人认为直方图反向投影的鲁棒性会更好。

     

    3. 匹配效果

    效果不错,基本可以确定查找到对应的区域坐标。。对于彩色图片,可以使用色彩空间信息排除掉其他错误的匹配图片,几乎可以精确的确定一个图片了。。

    4. 图片相似度的算法(感知哈希算法Perceptual hash algorithm

    感知哈希算法Perceptual hash algorithm),它的作用是对每张图片生成一个“指纹”(fingerprint)字符串,然后比较不同图片的指纹。结果越接近,就说明图片越相似。

    下面是一个最简单的实现:

    第一步,缩小尺寸。将图片缩小到8×8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。

    第二步,简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。

    第三步,计算平均值。计算所有64个像素的灰度平均值。

    第四步,比较像素的灰度。将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为。

    第五步,计算哈希值。将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。

    得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。在理论上,这等同于计算汉明距离。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。

     

     

    5. 性能结果

    在我机子上,语言java ,纯java实现。匹配变换dct算法size 8

    每次移动step=5  。。使用了并行库。。

    速度大概在120s。。懒得继续调整性能了,主要是测试思路,不过总结了思路,暂时先用着,理想的目标应该在3秒内。。

     

    这个是参考文章的说法大概70秒。。语言是c#调用opencv接口

    模板匹配和直方图反向投影的效率
        总的来说,模板匹配和直方图反向投影的效率都不高。在我的机器上,在1136*852大小的输入图像上匹配104*132的大小的模板图像(都是单通道灰度图像),大约需要700毫秒;而直方图反向投影大约需要75000毫秒(1.25分钟)。看来还需要继续学习,寻找更好的处理方法

     

    6. 如何提升性能

    主要算法消耗在匹配小图片上。。

    6.1. 可以采用简化的算法。二次匹配法,先大概确定区域

    。首先可以大幅度的就确定几张疑似图像坐标。。然后对疑似图像进行高精度算法匹配,就可以几乎匹配到唯一的一张。。如果图片是彩色图片,再使用颜色信息二次匹配相似度。。以及直方图等算法补充来匹配。。

    6.2. 切割图片设置一个step

    比如要寻找的图片大小60*60,可以设置一个20%以内的不敬step来跳跃切割,可以大幅度提升性能, 60/0.05=12.。 可以立马提升12倍的性能。。

     

    然后大概选定了区域后,在使用精确移动step来切割图片。

     

    7. 参考资料

     

    如何判断一张图片是否包含另一张小图片?图像匹配?-CSDN论坛-CSDN.NET-中国最大的IT技术社区.html

    模板匹配(Match Template) - Wuya - 博客园.html

    算法 - JPEGDCT压缩原理,谁能通俗易懂解释一下? - SegmentFault.html

    作者:: 绰号:老哇的爪子 ( 全名::Attilax Akbar Al Rapanui 阿提拉克斯 阿克巴 阿尔 拉帕努伊 ) 

    汉字名:艾提拉(艾龙)   EMAIL:1466519819@qq.com

    转载请注明来源: http://blog.csdn.net/attilax

     

    8. ------code

     

    private void t() throws IOException {

    String big = "c:\t.jpeg";

    String lit = "c:\lit.jpg";

    // diff==484

     

    BufferedImage lit_img = ImageIO.read(new File(lit));

     

    int w2 = lit_img.getWidth();

    int h2 = lit_img.getHeight();

     

    imgx imgx = new imgx();

    BufferedImage img = ImageIO.read(new File(big));

    int width = img.getWidth();

    int h = img.getHeight();

    ImagePHash imagePHash = new ImagePHash(8, 8);

    ImageReader ImageReader1 = imgx.ImgReader(new File(big));

     

    String ext = filex.getExtName(big);

    imgx.save(lit_img, "c:\0tmpPic\" + filex.getUUidName() + "." + ext, ext);

    ExecutorService es=Executors.newFixedThreadPool(3);

    lab: for (int i = 0; i < width; i = i + 5) {

    for (int j = 0; j < h; j = j + 5) {

    // BufferedImage tmp =

    // (BufferedImage) imgx.cutImage_retImg(big,

    // i, j, w2, h2);

    n++;

    int x = i;

    int y = j;

    int nowCount=n;

    Runnable ra = () -> {

     

    process(lit_img, w2, h2, imgx, imagePHash, ImageReader1, nowCount,

    ext, x, y);

    };

    es.execute(ra);

     

    }

    }

    es.shutdown();

    }

     

    private int process(BufferedImage lit_img, int w2, int h2, imgx imgx,

    ImagePHash imagePHash, ImageReader ImageReader1, int n, String ext,

    int i, int j) {

    Rectangle rect = new java.awt.Rectangle(i, j, w2, h2);

    BufferedImage tmp = imgx.cutImg(rect, ImageReader1);

     

    int dis = imagePHash.distance(tmp, lit_img);

     

    if (dis < 5) {

    log.info(" count:" + String.valueOf(n) + " dis:"

    + String.valueOf(dis) + " rect:" + String.valueOf(i) + "_"

    + String.valueOf(j));

    // break lab;

    }

    if (dis < 10) {

    String out = "c:\0tmpPic\" + filex.getUUidName() + "." + ext;

    imgx.save(tmp, out, ext);

    log.info(" count:" + String.valueOf(n) + " dis:"

    + String.valueOf(dis) + " rect:" + String.valueOf(i) + "_"

    + String.valueOf(j) + " file:" + out);

    }

     

    int cnt = n;

    if (cnt % 100 == 0) {

    String count = String.valueOf(cnt);

     

    log.info(" count:" + count + " dis:" + String.valueOf(dis)

    + " rect:" + String.valueOf(i) + "_" + String.valueOf(j));

    }

    return n;

    }

     

    }

     

    Atiend

     

     

  • 相关阅读:
    mysql从一张表查出数据存到另一张表和inner join的用法
    pycharm 看函数列表
    git删除本地所有的更改
    mysql create的几种用法和将字段设为插入时间
    python 装饰器
    pycharm退出unittest模式
    股票基础知识
    linux中查找路径下包含某字符串的所有文件
    SQL distinct用法
    SQL update用法
  • 原文地址:https://www.cnblogs.com/attilax/p/5963231.html
Copyright © 2011-2022 走看看