http://bbs.125.la/thread-13628690-1-1.html
這個(gè)也是從別的地方看來的算法月帝。
經(jīng)驗(yàn):第五步搅荞,計(jì)算哈希值
扯淡的,就是用獲得的010101這樣的字符串互相比較框咙。
下面一步一步來:
第一步咕痛,縮小尺寸。將圖片縮小到8x8的尺寸喇嘱,總共64個(gè)像素茉贡。這一步的作用是去除圖片的細(xì)節(jié),只保留結(jié)構(gòu)者铜、明暗等基本信息腔丧,摒棄不同尺寸、比例帶來的圖片差異作烟。
-(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; //返回的就是已經(jīng)改變的圖片
}
第二步,簡(jiǎn)化色彩拿撩。將縮小后的圖片衣厘,轉(zhuǎn)為64級(jí)灰度。也就是說压恒,所有像素點(diǎn)總共只有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;
}
第三步,計(jì)算平均值探赫。計(jì)算所有64個(gè)像素的灰度平均值型宙。
以下代碼來自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;
}
第五步,計(jì)算哈希值伦吠。將上一步的比較結(jié)果妆兑,組合在一起,就構(gòu)成了一個(gè)64位的整數(shù)毛仪,這就是這張圖片的指紋箭跳。組合的次序并不重要,只要保證所有圖片都采用同樣次序就行了潭千。得到指紋以后谱姓,就可以對(duì)比不同的圖片,看看64位中有多少位是不一樣的刨晴。在理論上屉来,這等同于計(jì)算"漢明距離"
(Hamming distance)路翻。如果不相同的數(shù)據(jù)位不超過5,就說明兩張圖片很相似茄靠;如果大于10茂契,就說明這是兩張不同的圖片。
這里在文章開頭說過了慨绳,這里不是計(jì)算哈希值掉冶。上面得到的01010字符串就是這個(gè)圖片的指紋了。比較就行了脐雪。
以下是兩個(gè)圖片的對(duì)比
0111111011110011111100111110000111000001100000011110001101111010
1111111111110001111000011110000111000001100000011110000111111011
然后算一下不一樣的厌小,排序。結(jié)束~~战秋!