简体   繁体   中英

Effective algorithm for finding 16x16 pixel same squares in a big image - C#

i am coding a software at visual studio 2010 by using C#. what does this software do is finding same squares at the image after a square selected. every square is composed by 16x16 pixel. my current algorithm starts from first pixel and scan the entire image pixel by pixel comparing to determine same pixel squares with the selected one. this takes really big time. Can you suggest me any better way ?

also every square is ordered. so they start like 0 - 16 - 32 - 48

a square can not start from 5 or 65 etc

thank you

You could cache a checksum of each image-region. Then you would only have to check ones that match the checksum for equality.

Let's assume each image is 16x16 rgb elements. You could do this (and yes, it will have integer overflow.)

All of this is in pseudo code - you're expected to be able to translate this to C#.

Add an int to the field image class, or create an image wrapper with an int as the 'checksum'

int checksum = 0
for each pixel in image {
   checksum += pixel.red + pixel.blue + pixel.green
   // you could do anything you wanted here, like
   // checksum *= 17 + pixel.red
   // checksum *= 17 + pixel.blue
   // checksum *= 17 + pixel.green
   // just make it "unique enough", like a hashcode
}
image.checksum = checksum

Now when you go to search you can go like this:

/**
 * equals method before: 
 */
boolean equals(image a, image b) {
  for x = 0..15 do /* all 16 pixels in X */
    for y = 0..15 do /* all 16 pixels in Y */
      if a.getPixel(x,y) != b.getPixel(x,y) return false;
  return true;
}

/**
 * equals method after: 
 *.
boolean equals(image a, image b) {
  /* this check lets you skip the loop in most cases */
  /* still have to verify that the image is equal pixel for pixel though */
  if a.checksum != b.checksum return false;
  for x = 0..15 do /* all 16 pixels in X */
    for y = 0..15 do /* all 16 pixels in Y */
      if a.getPixel(x,y) != b.getPixel(x,y) return false;
  return true;
}

One algorithm I know of to compare how similar two images are is the root mean square algorithm. I've used this in several programs and it's always been pretty fast. This simply sums up the differences, does some math, and the difference will be 'how close' the two images are to each other.

But, if the access is slow for comparison of each pixel, then access will still be slow (albeit slightly faster) adding them all up (or checksumming it).

Another option would be to add a short-circuit. The second any pixel at all doesn't match, you can claim the whole picture doesn't match.

I would be curious why this is going slow, though. The image would have to be incredibly large for it to not count. Are you using Bitmap.GetPixel()?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM