|
Dev - Sort these by name
|
Perceptual Hashing
Posted on September 26, 2011 at 18:35
As the title says.
But there are some wrong-doings here. 1. It doesn't really hash, that is, you don't get any kind of alphanumeric key... you get a 64-character code (comprised of 1s and 0s. :3). 2. It's low quality, and would need some modification for more serious work, but this is Game Maker, after all. Anyway, lets go back in time, to last night... I came onto IRC, remembering someone talk of something they were working on, for comparing images, and I needed something like that for a project I'm working on, so I asked about, and Ling answered by telling me a bit about Perceptual Hashing, which creates similar hashes for similar images. I looked more into it, and began porting the basic theory. Now that I've done so (with a basic Hamming Distance-like thing as well), I've decided to release the code. It's two small scripts, pretty much fully commented. Licensed under CC-BY-SA. :3 Please excuse my bad coding habits and overall bad coding. It works, at least. phash(); Returns a 64-character string. Code /*************************************************** Perceptual Hash in Game Maker Script written by Nick Simmons using the basic structure from [ http://www.hackerfactor.com/blog/index.php?/archives/432-Looks-Like-It.html ]. This code may be freely distributed and edited under the Creative Commons BY-SA liscense. Usage: phash(image); ***************************************************/ var temp_image work_surface work_surface2 average; average = 0; main_pixel[0,0] = 0; output = ""; temp_image = argument0; work_surface = surface_create(8,8); // Create a small surface to draw/read from. surface_set_target(work_surface); // Set surface one as the draw target. draw_sprite_stretched(temp_image,0,0,0,8,8); // Draw the image, stretched down to size. // Here's the fun part (part one), use the colors to convert to grayscale. for (j=0; j<8; j+=1;) { // All the way down the image. for (i=0; i<8; i+=1;) { // All the way across. _a = surface_getpixel(work_surface,i,j); // Get the color. _b[0] = color_get_red(_a); // Separate the color out. _b[1] = color_get_green(_a); // ^ _b[2] = color_get_blue(_a); // ^ _c = (_b[0]+_b[1]+_b[2])/765; // Add them all together, and average it out to make it 'grayscale'. main_pixel[i,j] = _c; // Store that for now. } } // Fun part (part two), average the grayscale. for (j=0; j<8; j+=1;) { // All the way down the image. for (i=0; i<8; i+=1;) { // All the way across. average += main_pixel[i,j]; // Add the value to the overall average. } } average = average/64; // Divide that by the amount of pixels (8x8 = 64). // Fun part (part three), convert to one-bit using the average. for (j=0; j<8; j+=1;) { // All the way down the image. for (i=0; i<8; i+=1;) { // All the way across. if main_pixel[i,j] > average { // Make the image 'one bit'. main_pixel[i,j] = 1; // ^ } else { // ^ main_pixel[i,j] = 0; // ^ } } } // More can be done here, but for now just make it a 64-character string. for (j=0; j<8; j+=1;) { // All the way down the image. for (i=0; i<8; i+=1;) { // All the way across. output = output + string(main_pixel[i,j]); } } // Then make it a 32-character string, from that. //output = string_copy(output,0,32) + "#" + string_copy(output,32,32); // Note: I have this here just because I personally used/use it this way, since the # // is the same for all hashes, it doesn't throw it off by enough to be noticible. // If you really have an issue with that, just leave it uncommented. surface_reset_target(); // Fix drawing. surface_free(work_surface); // Delete the surface. return output; And... hdistance(); Returns the percent of similarity in two strings. Code /*************************************************** (Psuedo) Hamming Distance in Game Maker Script written by Nick Simmons. This code may be freely distributed and edited under the Creative Commons BY-SA liscense. Usage: hdistance(string1, string2); Warning: This script was intended for use with phash(); other uses may require modification. Also, in this case, the script currently gives a percentage. (Or a -1 in case of failure.) Requirements: - Must be strings. - Must be the same length. ***************************************************/ var input_a input_b threshold string_a string_b length output; input_a = string(argument0); input_b = string(argument1); string_a[0] = ""; string_b[0] = ""; output = 0; length = string_length(input_a); // Get the length. if length != string_length(input_b) {return -1; break;} // If the lengths do not match, stop now. for (i=0; i<length; i+=1;) { // For the entire length of both strings. string_a[i] = string_copy(input_a,i,1); // Copy them into an array. string_b[i] = string_copy(input_b,i,1); // ^ } for (i=0; i<length; i+=1;) { // For the entire length of both strings. if string_a[i] = string_b[i] {output += 1;}; // Check them against eachother, and add 1 to the output if they match. } output = output / length; // Divide by the length to get a percentage. return output; Enjoy, perhaps. And here we have... a game I made. :D It was for a health project (oh irony) on OCD. I made use of the above thing in the game. Techno-Jumper - Platformer 5 levels. SFX made with SFXR. Music made with FL Studio. DOWNLOAD o.o
+0
Dev - Er, any ideas how to make this work?
Related Posts Dev - Warning Dev - After editing rating, make rating display change Dev - When editing, update "edited" column Dev - Restore deleted comments Dev - Display deleted comments if mod (hidden, then with dropdown) Dev - After deletion or during edit, make rating dropdown appear again Dev - Stricter rating rules. Prevent user from rating again Dev - Pages Dev - Reporting
Well it was written simply and such so I probably did things wrong, but it performs pretty fast, considering the use of get pixel, but Game Maker is a bit iffy about scaling in that it's giving different results sometimes...
And I could certainly fix the greyscale, but I'm just lazy... XD As far as pHash goes, no. I don't know much C and do not have any environment to work with so yeah... o.o |





Furthermore, I became interested in perceptual hashing a few weeks back as well and found pHash. Try to implement THAT in GM :3 :3