http://bbs.125.la/thread-13628690-1-1.html
这个也是从别的地方看来的算法。
经验:第五步,计算哈希值
扯淡的,就是用获得的010101这样的字符串互相比较。
下面一步一步来:
第一步,缩小尺寸。将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
-(UIImage * ) OriginImage:(UIImage **)image scaleToSize:(CGSize)size
{
UIGraphicsBeginImageContext(size); //size 为CGSize类型,即你所需要的图片尺寸
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage; //返回的就是已经改变的图片
}
第二步,简化色彩。将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
-(UIImage*)getGrayImage:(UIImage*)sourceImage
{
int width = sourceImage.size.width;
int height = sourceImage.size.height;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate (nil,width,height,8,0,colorSpace,kCGImageAlphaNone);
CGColorSpaceRelease(colorSpace);
if (context == NULL) {
return nil;
}
CGContextDrawImage(context,CGRectMake(0, 0, width, height), sourceImage.CGImage);
UIImage *grayImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)];
CGContextRelease(context);
return grayImage;
}
第三步,计算平均值。计算所有64个像素的灰度平均值。
以下代码来自github
-(unsigned char*) grayscalePixels:(UIImage *) image
{
// The amount of bits per pixel, in this case we are doing grayscale so 1 byte = 8 bits
#define BITS_PER_PIXEL 8
// The amount of bits per component, in this it is the same as the bitsPerPixel because only 1 byte represents a pixel
#define BITS_PER_COMPONENT (BITS_PER_PIXEL)
// The amount of bytes per pixel, not really sure why it asks for this as well but it's basically the bitsPerPixel divided by the bits per component (making 1 in this case)
#define BYTES_PER_PIXEL (BITS_PER_PIXEL/BITS_PER_COMPONENT)
// Define the colour space (in this case it's gray)
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceGray();
// Find out the number of bytes per row (it's just the width times the number of bytes per pixel)
size_t bytesPerRow = image.size.width * BYTES_PER_PIXEL;
// Allocate the appropriate amount of memory to hold the bitmap context
unsigned char* bitmapData = (unsigned char*) malloc(bytesPerRow*image.size.height);
// Create the bitmap context, we set the alpha to none here to tell the bitmap we don't care about alpha values
CGContextRef context = CGBitmapContextCreate(bitmapData,image.size.width,image.size.height,BITS_PER_COMPONENT,bytesPerRow,colourSpace,kCGImageAlphaNone);
// We are done with the colour space now so no point in keeping it around
CGColorSpaceRelease(colourSpace);
// Create a CGRect to define the amount of pixels we want
CGRect rect = CGRectMake(0.0,0.0,image.size.width,image.size.height);
// Draw the bitmap context using the rectangle we just created as a bounds and the Core Graphics Image as the image source
CGContextDrawImage(context,rect,image.CGImage);
// Obtain the pixel data from the bitmap context
unsigned char* pixelData = (unsigned char*)CGBitmapContextGetData(context);
// Release the bitmap context because we are done using it
CGContextRelease(context);
return pixelData;
#undef BITS_PER_PIXEL
#undef BITS_PER_COMPONENT
}
返回就是0101字符串了
-(NSString *) myHash:(UIImage *) img
{
unsigned char* pixelData = [self grayscalePixels:img];
int total = 0;
int ave = 0;
for (int i = 0; i < img.size.height; i++) {
for (int j = 0; j < img.size.width; j++) {
total += (int)pixelData[(i*((int)img.size.width))+j];
}
}
ave = total/64;
NSMutableString *result = [[NSMutableString alloc] init];
for (int i = 0; i < img.size.height; i++) {
for (int j = 0; j < img.size.width; j++) {
int a = (int)pixelData[(i*((int)img.size.width))+j];
if(a >= ave)
{
[result appendString:@"1"];
}
else
{
[result appendString:@"0"];
}
}
}
return result;
}
第五步,计算哈希值。将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。在理论上,这等同于计算"汉明距离"
(Hamming distance)。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
这里在文章开头说过了,这里不是计算哈希值。上面得到的01010字符串就是这个图片的指纹了。比较就行了。
以下是两个图片的对比
0111111011110011111100111110000111000001100000011110001101111010
1111111111110001111000011110000111000001100000011110000111111011
然后算一下不一样的,排序。结束~~!