link2x101

Last Login:
May 20, 2013
Warn:

Rank:
Member
Member Points:
27



User Profile
Follow

Hits: 25,289
Joined August 31, 2006
Games (6)

Desert Strike v1.0
September 05, 2006
Constructor
September 02, 2012
Zonline - SPECIAL BETA-Edition
April 12, 2007
ZombieNight
December 01, 2007
This is a game.
June 29, 2010
Just run!
July 02, 2010
Examples (6)
Favorite Users
Dev - Sort these by name
Favorite Games


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


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
Pretty simple algorithm I see, but I'd like to see some test results... how well does this algorithm perform? I quickly glanced over your source material and noticed you are converting the source color to gray scale sort of wrong. Usually converting an RGB color to a gray one is done by 0.3*R+0.59*G+0.11*B. I am not sure what kind of effect this has on the algorithm, but you should try it out!

Furthermore, I became interested in perceptual hashing a few weeks back as well and found pHash. Try to implement THAT in GM :3 :3
Posted by sirxemic September 26, 2011 19:36 - 1.7 years ago
| [#1]

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
Posted by link2x101 September 26, 2011 20:40 - 1.7 years ago
| [#2]

Not sure of a use? lol
Posted by Alert Games September 26, 2011 23:09 - 1.7 years ago
| [#3]

Well I have one, so I made it. XD Anyway, I guess it is a bit out of place, for making games, but here it is anyway. O.o
Posted by link2x101 September 26, 2011 23:13 - 1.7 years ago
| [#4]

Updated.
Posted by link2x101 September 30, 2011 0:48 - 1.6 years ago
| [#5]

WHY MUST MY BLOGS ALWAYS DIE!? </raeg>
Posted by link2x101 September 30, 2011 18:38 - 1.6 years ago
| [#6]

Blogs are made to die.
Posted by Josea September 30, 2011 22:35 - 1.6 years ago
| [#7]

Recent Activity
 
Active Users (0)