图像相似度比较和检测图像中的特定物

简介: 图像相似度比较和检测图像中的特定物

对普通人而言,识别任意两张图片是否相似是件很容易的事儿。但是从计算机的角度来识别的话,需要先识别出图像的特征,然后才能进行比对。在图像识别中,颜色特征是最为常见的。每张图像都可以转化成颜色分布直方图,如果两张图片的直方图很接近,就可以认为它们很相似。这有点类似于判断文本的相似程度。


图像比较



先来比对两张图片,一张是原图另一张是经过直方图均衡化之后的图片。


image.png

原图和直方图均衡化比较.png


二者的相关性因子是-0.056,这说明两张图的相似度很低。在上一篇文章 图像直方图与直方图均衡化 中,已经解释过什么是直方图均衡化。通过直方图均衡化后,两张图片确实是不同的,可以从下图看出。


image.png

直方图均值化.png


我们来看看如何使用直方图比较。

final Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.test_hist);
        image0.setImageBitmap(bitmap);
        CV4JImage cv4jImage = new CV4JImage(bitmap);
        ImageProcessor imageProcessor = cv4jImage.convert2Gray().getProcessor();
        int[][] source = null;
        int[][] target = null;
        CalcHistogram calcHistogram = new CalcHistogram();
        int bins = 180;
        source = new int[imageProcessor.getChannels()][bins];
        calcHistogram.calcHSVHist(imageProcessor,bins,source,true);
        if (imageProcessor instanceof ByteProcessor) {
            EqualHist equalHist = new EqualHist();
            equalHist.equalize((ByteProcessor) imageProcessor);
            image1.setImageBitmap(cv4jImage.getProcessor().getImage().toBitmap());
            target = new int[imageProcessor.getChannels()][bins];
            calcHistogram.calcHSVHist(imageProcessor,bins,target,true);
        }
        CompareHist compareHist = new CompareHist();
        StringBuilder sb = new StringBuilder();
        sb.append("巴氏距离:").append(compareHist.bhattacharyya(source[0],target[0])).append("\r\n")
                .append("协方差:").append(compareHist.covariance(source[0],target[0])).append("\r\n")
                .append("相关性因子:").append(compareHist.ncc(source[0],target[0]));
        result.setText(sb.toString());


其中,CompareHist 这个类是用于直方图比较的类。


然后,再来比较两张完全一致的图片,可以看到他们的相关性因子是1.0,表示两者完全一致。


image.png

两张相同的图比较.png


最后,来比对两张完全不同的图片,可以看到它们的相关性因子是0.037,表面二者几乎没有什么相似之处。


image.png

两张完全不同的图比较.png


直方图比较是识别图像相似度的算法之一,也是最简单的算法。当然,还有很多其他的算法啦。


直方图反向投影



所谓反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征。


image.png

反向投影的算法.png


其中,b(xi)表示在位置xi上像素对应的直方图第b(xi)个bin,直方图共m个bin,qu表示第u个bin的值。


下图是皇马的拉莫斯在2017年欧冠决赛时的图片。直方图反向投影可以根据球员球衣中的某一块区域,来查找图片中拉莫斯所穿的球衣。


image.png

直方图反向投影.png


上图是不是很酷炫?来看看是怎样使用反向投影的,需要先计算出样本的直方图,然后使用模型去寻找原图中存在的该特征。反向投影的结果包含了:以每个输入图像像素点为起点的直方图对比结果。在这里是一个单通道的浮点型图像。

Resources res = getResources();
        Bitmap bitmap1 = BitmapFactory.decodeResource(res, R.drawable.test_project_target);
        targetImage.setImageBitmap(bitmap1);
        Bitmap bitmap2 = BitmapFactory.decodeResource(res, R.drawable.test_project_sample);
        sampleImage.setImageBitmap(bitmap2);
        CV4JImage cv4jImage = new CV4JImage(bitmap1);
        ColorProcessor colorProcessor = (ColorProcessor)cv4jImage.getProcessor();
        BackProjectHist backProjectHist = new BackProjectHist();
        int w = colorProcessor.getWidth();
        int h = colorProcessor.getHeight();
        CV4JImage resultCV4JImage = new CV4JImage(w,h);
        ByteProcessor byteProcessor = (ByteProcessor)resultCV4JImage.getProcessor();
         // sample
        CV4JImage sample = new CV4JImage(bitmap2);
        ColorProcessor sampleProcessor = (ColorProcessor)sample.getProcessor();
        CalcHistogram calcHistogram = new CalcHistogram();
        int bins = 32;
        int[][] hist = new int[sampleProcessor.getChannels()][bins];
        calcHistogram.calcHSVHist(sampleProcessor,bins,hist,true);
        byte[][] source = new byte[][]{colorProcessor.getRed(),colorProcessor.getGreen(),colorProcessor.getBlue()};
        byte[][] target = new byte[3][w*h];
        Tools.rgb2hsv(source,target);
        ByteProcessor hsvByteProcessor = new ByteProcessor(target[0],w,h);
        backProjectHist.backProjection(hsvByteProcessor,byteProcessor,hist[0],new int[]{0,180});
        result.setImageBitmap(byteProcessor.getImage().toBitmap());


其中,BackProjectHist 这个类是用于直方图反向投影的类。


总结



直方图比较和直方图反向投影的算法都已经包含在cv4j中。


cv4jgloomyfish和我一起开发的图像处理库,纯java实现,目前还处于早期的版本。这次我们填完直方图的坑以后,终于把它发布到jcenter上了。


单独下载cv4j

compile 'com.cv4j:cv4j:0.1.0'


也可以下载rxcv4j,它是使用 RxJava2.x 进行的封装,如果下载该模块的话无需再下载cv4j。

compile 'com.cv4j:rxcv4j:0.1.0'


目前已经实现的功能:


image.png

cv4j.png


下周我们开始做模板匹配的算法。

相关文章
|
算法 搜索推荐 计算机视觉
图片相似度计算及检索调研
图片相似度计算和相似图片搜索,是图片识别领域两个常见的应用场景。例如搜索相似商品,和相似的图片,在百度、淘宝中都有应用。在某些业务中,也存在对图片相似度的计算和判断。因此,在这里简单介绍一下相关算法。
2014 0
|
数据采集 Python
Python爬虫:实现爬取、下载网站数据的几种方法
Python爬虫:实现爬取、下载网站数据的几种方法
1284 1
|
5月前
|
机器学习/深度学习 算法 安全
深度长文I 深度合成服务类-算法备案该怎么做?
本文详解“深度合成服务类”算法及其备案要求,涵盖定义、类型、备案流程等内容,助你全面理解合规要点。
|
前端开发 API vr&ar
Android开发之OpenGL绘制三维图形的流程
即将连载的系列文章将探索Android上的OpenGL开发,这是一种用于创建3D图形和动画的技术。OpenGL是跨平台的图形库,Android已集成其API。文章以2D绘图为例,解释了OpenGL的3个核心元素:GLSurfaceView(对应View)、GLSurfaceView.Renderer(类似Canvas)和GL10(类似Paint)。通过将这些结合,Android能实现3D图形渲染。文章介绍了Renderer接口的三个方法,分别对应2D绘图的构造、测量布局和绘制过程。示例代码展示了如何在布局中添加GLSurfaceView并注册渲染器。
560 1
Android开发之OpenGL绘制三维图形的流程
|
边缘计算 人工智能 监控
边缘计算与AI结合的场景案例研究
【8月更文第17天】随着物联网(IoT)设备数量的爆炸性增长,对实时数据处理的需求也随之增加。传统的云计算模型在处理这些数据时可能会遇到延迟问题,尤其是在需要即时响应的应用中。边缘计算作为一种新兴的技术趋势,旨在通过将计算资源更靠近数据源来解决这个问题。本文将探讨如何将人工智能(AI)技术与边缘计算结合,以实现高效的实时数据分析和决策制定。
1317 1
|
存储 SQL 分布式计算
当NameNode宕机时的应急响应与恢复策略
【8月更文挑战第31天】
544 0
|
Ubuntu Linux iOS开发
|
机器学习/深度学习
图像预处理之图像去重
图像预处理之图像去重
1765 0
|
机器学习/深度学习 人工智能 开发者
关于阿里云的图像搜索的创建和使用
关于阿里云的图像搜索的创建和使用
关于阿里云的图像搜索的创建和使用
|
安全 网络协议 Java
【紧急】Log4j又发新版2.17.0,只有彻底搞懂漏洞原因,才能以不变应万变,小白也能看懂
经过一周时间的Log4j2 RCE事件的发酵,事情也变也越来越复杂和有趣,就连 Log4j 官方紧急发布了 2.15.0 版本之后没有过多久,又发声明说 2.15.0 版本也没有完全解决问题,然后进而继续发布了 2.16.0 版本。大家都以为2.16.0是最终终结版本了,没想到才过多久又爆雷,Log4j 2.17.0横空出世。
1328 0