Эффективный алгоритм поиска одинаковых квадратов 16x16 пикселей на большом изображении - C # - PullRequest
2 голосов
/ 24 февраля 2011

Я пишу программное обеспечение на Visual Studio 2010 с помощью C #.то, что делает это программное обеспечение, находит те же квадраты на изображении после выбранного квадрата.каждый квадрат состоит из 16x16 пикселей.Мой текущий алгоритм начинается с первого пикселя и сканирует все изображение попиксельно, сравнивая, чтобы определить одинаковые квадраты пикселей с выбранным.это занимает действительно много времени.Можете ли вы предложить мне лучший способ?

также каждый квадрат заказан.поэтому они начинаются как 0 - 16 - 32 - 48

квадрат не может начинаться с 5 или 65 и т. д.

спасибо

Ответы [ 2 ]

6 голосов
/ 24 февраля 2011

Вы можете кэшировать контрольную сумму каждой области изображения. Тогда вам нужно будет проверить только те из них, которые соответствуют контрольной сумме на равенство.

Предположим, что каждое изображение размером 16x16 rgb. Вы можете сделать это (и да, у него будет целочисленное переполнение.)

Все это в псевдокоде - ожидается, что вы сможете перевести это на C #.

Добавьте int к классу изображения поля или создайте оболочку изображения с int в качестве контрольной суммы

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

Теперь, когда вы идете на поиск, вы можете пойти так:

/**
 * 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;
}
1 голос
/ 24 февраля 2011

Один из известных мне алгоритмов сравнения двух изображений - это алгоритм среднеквадратичного значения. Я использовал это в нескольких программах, и это всегда было довольно быстро. Это просто суммирует различия, делает некоторые математические вычисления, и разница будет в том, «насколько близко» эти два изображения друг к другу.

Но, если доступ медленный для сравнения каждого пикселя, то доступ все равно будет медленным (хотя и немного быстрее), добавляя их все (или проверяя суммирование).

Другой вариант - добавить короткое замыкание. Если какой-либо пиксель вообще не совпадает, можно утверждать, что вся картинка не совпадает.

Мне было бы любопытно, почему это идет медленно. Изображение должно быть невероятно большим, чтобы его не считали. Вы используете Bitmap.GetPixel ()?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...