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

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

图像比较

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


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

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

直方图均值化.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,表示两者完全一致。


两张相同的图比较.png

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


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

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

直方图反向投影

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


反向投影的算法.png

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

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

直方图反向投影.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'

目前已经实现的功能:


cv4j.png

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

如果您想看该系列先前的文章可以访问下面的文集:
http://www.jianshu.com/nb/10401400

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容