iOS实现感知哈希算法

感知哈希算法(以下简称PHA)是哈希算法的一类,主要用来做相似图片的搜索工作。
PHA是一类比较哈希方法的统称。图片所包含的特征被用来生成一组指纹(不过它不是唯一的),而这些指纹是可以进行比较的。
下面是简单的步骤,来说明对图像进行PHA的运算过程:
第一步,缩小尺寸。
最快速的去除高频和细节,只保留结构明暗的方法就是缩小尺寸。
将图片缩小到8x8的尺寸,总共64个像素。摒弃不同尺寸、比例带来的图片差异。
[objc]  view plain  copy
  1. //1.缩小图片8*8  
  2. - (UIImage *)scaleToSize:(UIImage *)img size:(CGSize)size{  
  3.     UIGraphicsBeginImageContext(size);  
  4.     [img drawInRect:CGRectMake(0,0, size.width, size.height)];  
  5.     UIImage* scaledImage =UIGraphicsGetImageFromCurrentImageContext();  
  6.     UIGraphicsEndImageContext();  
  7.     return scaledImage;  
  8. }  


第二步,简化色彩。
将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
[objc]  view plain  copy
  1. //2.将图片转换成灰度图片  
  2. -(UIImage*)getGrayImage:(UIImage*)sourceImage  
  3. {  
  4.     int width = sourceImage.size.width;  
  5.     int height = sourceImage.size.height;  
  6.       
  7.     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();  
  8.     CGContextRef context = CGBitmapContextCreate (nil,width,height,8,0,colorSpace,kCGImageAlphaNone);  
  9.     CGColorSpaceRelease(colorSpace);  
  10.     if (context == NULL) {  
  11.         return nil;  
  12.     }  
  13.     CGContextDrawImage(context,CGRectMake(00, width, height), sourceImage.CGImage);  
  14.     UIImage *grayImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];  
  15.     CGContextRelease(context);  
  16.     return grayImage;  
  17. }  



第三步,计算平均值,比较像素的灰度。
计算所有64个像素的灰度平均值,将每个像素的灰度,与平均值进行比较,大于或等于平均值,记为1;小于平均值,记为0。
[objc]  view plain  copy
  1. //3.计算出图片平均灰度,然后每一点灰度与平均灰度比较,大于平均值是1,小于平均值是0  
  2. -(NSString *)pHashValueWithImage:(UIImage *)image{  
  3.     NSMutableString * pHashString = [NSMutableString string];  
  4.     CGImageRef imageRef = [image CGImage];  
  5.     unsigned long width = CGImageGetWidth(imageRef);  
  6.     unsigned long height = CGImageGetHeight(imageRef);  
  7.     CGDataProviderRef provider = CGImageGetDataProvider(imageRef);  
  8.     NSData* data = (id)CFBridgingRelease(CGDataProviderCopyData(provider));  
  9. //    NSLog(@"data = %@",data);  
  10.     const charchar * heightData = (char*)data.bytes;  
  11.     int sum = 0;  
  12.       
  13.     for (int i = 0; i < width * height; i++)  
  14.     {  
  15.         printf("%d ",heightData[i]);  
  16.         if (heightData[i] != 0)  
  17.         {  
  18.             sum += heightData[i];  
  19.         }  
  20.     }  
  21.     int avr = sum / (width * height);  
  22.     NSLog(@"%d",avr);  
  23.     for (int i = 0; i < width * height; i++)  
  24.     {  
  25.         if (heightData[i] >= avr) {  
  26.             [pHashString appendString:@"1"];  
  27.         }  
  28.         else {  
  29.             [pHashString appendString:@"0"];  
  30.         }  
  31.     }  
  32.     NSLog(@"pHashString = %@,pHashStringLength = %lu",pHashString,(unsigned long)pHashString.length);  
  33.     return pHashString;  
  34. }  
  35.    


第四步,计算哈希值。
得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。在理论上,这等同于计算Hammingdistance)。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
[objc]  view plain  copy
  1. //4.得到两个hashValue不同点数  
  2. -(NSInteger)getDifferentValueCountWithString:(NSString *)str1 andString:(NSString *)str2{  
  3.     NSInteger diff = 0;  
  4.     const charchar * s1 = [str1 UTF8String];  
  5.     const charchar * s2 = [str2 UTF8String];  
  6.     for (int i = 0 ; i < str1.length ;i++){  
  7.         if(s1[i] != s2[i]){  
  8.             diff++;  
  9.         }  
  10.     }  
  11.     return diff;  
  12. }  
  13.    

例子:
[objc]  view plain  copy
  1. UIImage * mImage1 = [self getGrayImage:[self scaleToSize:_image1 size:CGSizeMake(88)]];  
  2. UIImage * mImage2 = [self getGrayImage:[self scaleToSize:_image2 size:CGSizeMake(88)]];  
  3. NSInteger diff = [self getDifferentValueCountWithString:[self pHashValueWithImage:mImage1] andString:[self pHashValueWithImage:mImage2]];  
  4. p;  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值