上周,正在忙,突然有个同学找我帮忙,说有个需求:图片相似度比较。

网上搜了一下,感觉不是很难,就写了下,这里分享给需要的小伙伴。

首先,本次采用的是OpenCV,图片哈希值:

先说一下基本思路:

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

注:实际操作时,采取了两种尺寸作对比(10*10,100*100)尺寸再大的话就会性能影响就会较大了,我实现了两种,目的是为了展示怎么设定不同尺寸。

2.      简化色彩:将缩小后的图像,转为64级灰度,即所有像素点总共只有64种颜色;

注:关于多少灰度级的问题,我并没有太在意,采取了一个合适的RGB to GRAY 算法就好,个人理解

3.      计算平均值:计算所有64个像素的灰度平均值;

4.      比较像素的灰度:将每个像素的灰度,与平均值进行比较,大于或等于平均值记为1,小于平均值记为0;

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

6.      得到指纹以后,就可以对比不同的图像

参考博客:http://blog.csdn.net/fengbingchun/article/details/42153261

类文件下载链接:http://files.cnblogs.com/files/kongkaikai/GetSimilarity.zip

GetSimilarity.h

 //
// GetSimilarity.h
// imgsimlartest
//
// Created by test on 16/3/3.
// Copyright © 2016年 com.facishare.CoreTest. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
typedef double Similarity; @interface GetSimilarity : NSObject
- (void)setImgWithImgA:(UIImage*)imgA ImgB:(UIImage*)imgB;//设置需要对比的图片
- (void)setImgAWidthImg:(UIImage*)img;
- (void)setImgBWidthImg:(UIImage*)img;
- (Similarity)getSimilarityValue; //获取相似度
+ (Similarity)getSimilarityValueWithImgA:(UIImage*)imga ImgB:(UIImage*)imgb;//类方法
@end

GetSimilarity.m

 //
// GetSimilarity.m
// imgsimlartest
//
// Created by test on 16/3/3.
// Copyright © 2016年 com.facishare.CoreTest. All rights reserved.
// #import "GetSimilarity.h"
#define ImgSizeA 10
#define ImgSizeB 100
typedef enum workday
{
SizeA,
SizeB,
}GetSimilarityType; @interface GetSimilarity()
@property (nonatomic,assign) Similarity similarity;
@property (nonatomic,strong) UIImage *imga;
@property (nonatomic,strong) UIImage *imgb;
@end @implementation GetSimilarity
- (instancetype)init
{
self = [super init];
if (self) {
self.imga = [[UIImage alloc]init];
self.imgb = [[UIImage alloc]init];
}
return self;
} - (void)setImgWithImgA:(UIImage*)imgA ImgB:(UIImage*)imgB
{
_imga = imgA;
_imgb = imgB;
} - (void)setImgAWidthImg:(UIImage*)img
{
self.imga = img;
} - (void)setImgBWidthImg:(UIImage*)img
{
self.imgb = img;
} - (Similarity)getSimilarityValue
{
self.similarity = MAX([self getSimilarityValueWithType:SizeA], [self getSimilarityValueWithType:SizeB]);
return self.similarity;
}
+ (Similarity)getSimilarityValueWithImgA:(UIImage *)imga ImgB:(UIImage *)imgb
{
GetSimilarity * getSimilarity = [[GetSimilarity alloc]init];
[getSimilarity setImgWithImgA:imga ImgB:imgb];
return [getSimilarity getSimilarityValue];
}
- (Similarity)getSimilarityValueWithType:(GetSimilarityType)type;//
{
int cursize = (type == SizeA ? ImgSizeA : ImgSizeB);
int ArrSize = cursize * cursize + ,a[ArrSize],b[ArrSize],i,j,grey,sum = ;
CGSize size = {cursize,cursize};
UIImage * imga = [self reSizeImage:self.imga toSize:size];
UIImage * imgb = [self reSizeImage:self.imgb toSize:size];//缩小图片尺寸 a[ArrSize] = ;
b[ArrSize] = ;
CGPoint point;
for (i = ; i < cursize; i++) {//计算a的灰度
for (j = ; j < cursize; j++) {
point.x = i;
point.y = j;
grey = ToGrey([self UIcolorToRGB:[self colorAtPixel:point img:imga]]);
a[cursize * i + j] = grey;
a[ArrSize] += grey;
}
}
a[ArrSize] /= (ArrSize - );//灰度平均值
for (i = ; i < cursize; i++) {//计算b的灰度
for (j = ; j < cursize; j++) {
point.x = i;
point.y = j;
grey = ToGrey([self UIcolorToRGB:[self colorAtPixel:point img:imgb]]);
b[cursize * i + j] = grey;
b[ArrSize] += grey;
}
}
b[ArrSize] /= (ArrSize - );//灰度平均值
for (i = ; i < ArrSize ; i++)//灰度分布计算
{
a[i] = (a[i] < a[ArrSize] ? : );
b[i] = (b[i] < b[ArrSize] ? : );
}
ArrSize -= ;
for (i = ; i < ArrSize ; i++)
{
sum += (a[i] == b[i] ? : );
} return sum * 1.0 / ArrSize;
} - (UIImage *)reSizeImage:(UIImage *)image toSize:(CGSize)reSize//重新设定图片尺寸
{
UIGraphicsBeginImageContext(CGSizeMake(reSize.width, reSize.height));
[image drawInRect:CGRectMake(, , reSize.width, reSize.height)];
UIImage *reSizeImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return reSizeImage;
} unsigned int ToGrey(unsigned int rgb)//RGB计算灰度
{
unsigned int blue = (rgb & 0x000000FF) >> ;
unsigned int green = (rgb & 0x0000FF00) >> ;
unsigned int red = (rgb & 0x00FF0000) >> ;
return ( red* + green * + blue * )>>;
} - (unsigned int)UIcolorToRGB:(UIColor*)color//UIColor转16进制RGB
{
unsigned int RGB,R,G,B;
RGB = R = G = B = 0x00000000;
CGFloat r,g,b,a;
[color getRed:&r green:&g blue:&b alpha:&a];
R = r * ;
G = g * ;
B = b * ;
RGB = (R << ) | (G << ) | B ;
return RGB;
} - (UIColor *)colorAtPixel:(CGPoint)point img:(UIImage*)img{//获取指定point位置的RGB
// Cancel if point is outside image coordinates
if (!CGRectContainsPoint(CGRectMake(0.0f, 0.0f, img.size.width, img.size.height), point)) { return nil; } NSInteger pointX = trunc(point.x);
NSInteger pointY = trunc(point.y);
CGImageRef cgImage = img.CGImage;
NSUInteger width = img.size.width;
NSUInteger height = img.size.height;
int bytesPerPixel = ;
int bytesPerRow = bytesPerPixel * ;
NSUInteger bitsPerComponent = ;
unsigned char pixelData[] = { , , , };
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pixelData, , , bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); CGColorSpaceRelease(colorSpace);
CGContextSetBlendMode(context, kCGBlendModeCopy); // Draw the pixel we are interested in onto the bitmap context
CGContextTranslateCTM(context, -pointX, pointY-(CGFloat)height);
CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, (CGFloat)width, (CGFloat)height), cgImage);
CGContextRelease(context);
// Convert color values [0..255] to floats [0.0..1.0] CGFloat red = (CGFloat)pixelData[] / 255.0f;
CGFloat green = (CGFloat)pixelData[] / 255.0f;
CGFloat blue = (CGFloat)pixelData[] / 255.0f;
CGFloat alpha = (CGFloat)pixelData[] / 255.0f;
return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
}
@end

iOS,OC,图片相似度比较,图片指纹的更多相关文章

  1. atitit.图片相似度与图片查找的设计 获取图片指纹

    atitit.图片相似度与图片查找的设计. 1. 两张图片相似算法 1 2. DCT(离散余弦变换(DiscreteCosineTransform))编辑 2 3.  编辑距离编辑 3 4. Java ...

  2. Android实现图片相似度

    Android实现图片相似度 最近公司有一个需求,就是希望能判断用户提交的照片是否是身份证的正面或者反面.可以通过预设一张拍摄清晰的身份证正面或者反面,来对比是否相似,那么问题就转化为如何计算两张图片 ...

  3. iOS开发系列--无限循环的图片浏览器

    --UIKit之UIScrollView 概述 UIKit框架中有大量的控件供开发者使用,在iOS开发中不仅可以直接使用这些控件还可以在这些控件的基础上进行扩展打造自己的控件.在这个系列中如果每个控件 ...

  4. opencv学习笔记(六)直方图比较图片相似度

    opencv学习笔记(六)直方图比较图片相似度 opencv提供了API来比较图片的相似程度,使我们很简单的就能对2个图片进行比较,这就是直方图的比较,直方图英文是histogram, 原理就是就是将 ...

  5. iOS开发--基于AFNetWorking3.0的图片缓存分析

    图片在APP中占有重要的角色,对图片做好缓存是重要的一项工作.[TOC] 理论 不喜欢理论的可以直接跳到下面的Demo实践部分 缓存介绍 缓存按照保存位置可以分为两类:内存缓存.硬盘缓存(FMDB.C ...

  6. python 对比图片相似度

    最近appium的使用越来越广泛了,对于测试本身而言,断言同样是很重要的,没有准确的断言那么就根本就不能称之为完整的测试了.那么目前先从最简单的截图对比来看.我这里分享下python的图片相似度的代码 ...

  7. 基于2-channel network的图片相似度判别

    一.相关理论 本篇博文主要讲解2015年CVPR的一篇关于图像相似度计算的文章:<Learning to Compare Image Patches via Convolutional Neur ...

  8. iOS WebView 加载本地资源(图片,文件等)

    https://www.cnblogs.com/dhui69/p/5596917.html iOS WebView 加载本地资源(图片,文件等) NSString *path = [[NSBundle ...

  9. 通过CSS3实现:鼠标悬停图片360度旋转效果

    效果很好玩,代码很简单: 效果: 鼠标放置在图片上:360度顺时针旋转 鼠标离开图片:图片260度逆时针旋转 只要将下面代码拷贝过去,并将图片改成你想要的就可以看到效果 <!doctype ht ...

随机推荐

  1. oracle授权另外一个用户访问自己创建的数据对象

    oracle安装好之后,有一个默认的scott用户,该用户有一个默认的emp表,怎样让新创建的用户也能够访问这个表呢? 授权xiaoming这个用户访问emp表,但是xiaoming只有select权 ...

  2. SVN状态图标不显示

    Windows最多只允许15个覆盖图标,它自己又用了几个,结果给用户用的就11个左右了,如果你安装了其他网盘,那可用的就更少了. 解决方法: 1.在运行里输入regedit进入注册表 2.依次打开HK ...

  3. DATABASE LINK 的查看、创建与删除

    1.查看dblink SELECT OWNER,OBJECT_NAME FROM DBA_OBJECTS WHERE OBJECT_TYPE='DATABASE LINK'; 或者 SELECT * ...

  4. SQL Execute语法.

    一,执行字符串: EXECUTE语句可以执行存放SQL语句的字符串变量,或直接执行SQL语句字符串. 语法:EXECUTE({@字符串变量|[N]’SQL语句字符串’}[+...n]) 例子:Decl ...

  5. TP-LINK wr703n openwrt 挂载 U盘

    1.首先设置好DNS 2.点SYSTEM 点SOFTWARE 更新软件列表 3.安装下列软件: block-mount kmod-usb-storage kmod-fs-ext4 e2fsprogs ...

  6. 使用Newtonsoft.Json序列化和反序列化对象(源码)

    Json数据格式,简单而强大. 使用Json,不得不提到Newtonsoft.Json,它帮助我们更方便的使用Json,当然,不使用它也是可以的,还有许多方法将对象序列化成Json字符串,暂且不提. ...

  7. 禁用UITextField复制粘贴等方法

    要实现此功能只需创建一个继承自UITextField的子类,重写以下方法即可. - (BOOL)canPerformAction:(SEL)action withSender:(id)sender{ ...

  8. Java程序实现导出Excel,支持IE低版本

    来博客园两年多了,最近才开通了微博,因为懒所以也一直没有写东西,今天想整理一下自己前段时间遇到的一个导出的问题. 因为项目的需求,要做一部分导出功能.开始的时候用的公司的导出,但是很奇怪有部分模块导出 ...

  9. prime,素数的判断——c语言

    输入一个数a,求他是否是素数(用函数) 程序: #include<stdio.h> int prime(int a)-----------------------------------/ ...

  10. PHP过滤常用标签的正则表达式

    $str=preg_replace("/\s+/", " ", $str); //过滤多余回车 $str=preg_replace("/<[ ] ...