Алгоритм фото-мозаики. Как создать мозаичное фото с учетом основного изображения и списка плиток? - PullRequest
8 голосов
/ 30 марта 2011

Hy. Что мне нужно сделать, это создать программу (с использованием C или C ++), которая принимает в качестве входных данных растровое изображение 24 бит / пиксель и сбор изображений, и мне нужно создать мозаичное изображение, аналогичное входному изображению используя предоставленную библиотеку изображений (для создания мозаичной фотографии, аналогичной входной).

Пока что я могу получить доступ к пикселям изображения на входе и цветам из него, но я застрял. Мой вопрос: с чего мне начать? Мне нужен базовый алгоритм, который мог бы сделать такую ​​вещь. И я не могу найти что-либо (возможно, я смотрю неправильно) А также может кто-нибудь сказать мне случайный загрузчик фотографий, чтобы я мог загрузить небольшие изображения для проекта? Кто-нибудь может мне помочь? Скажите, пожалуйста, с чего начать и что использовать.

Ответы [ 2 ]

16 голосов
/ 30 марта 2011

Я сделал это в Scala.Статья доктора Доббса была чрезвычайно полезна для меня.

Пример изображения:

Sample photomosaic

Вот мой основной алгоритм:

def createMosaic(targetImage:BufferedImage,
  index:PhotoIndexer.PhotoIndex,
  opacity:Float,
  targetWidth:Int,
  targetHeight:Int,
  numRows:Int,
  numColumns:Int, callback:PhotoMosaicCallback): ImageGrid = {

      var indexCopy = index

      // Map from the buffered image to that image's average color
      var colorMap:Map[BufferedImage,Color] =
      index.values.map(data => (data.thumbnail, data.avgColor)).toMap

      // We look at rectangular regions of the target image, calculate their average
      // colors, and then pick images that match those colors.
      val sampleWidth = targetImage.getWidth / numColumns
      val sampleHeight = targetImage.getHeight / numRows

      // Used to report the progress of the process
      var counter = 1
      val numSubImages = numRows * numColumns

      val imageGrid:ImageGrid = Array.fill(numRows, numColumns)(Nil)

      // for each patch in the image
      for (row <- 0 until numRows) {
        for (column <- 0 until numColumns) {
          val x = column * sampleWidth
          val y = row * sampleHeight
          // This is the small rectangular region of the target image that we're
          // currently considering
          val subImage = targetImage.getData(new Rectangle(x,y,sampleWidth,sampleHeight))
          val avgImageColor = calculateColorFromRaster(subImage)

          val nearest:Seq[BufferedImage] = getNearestColorImages(avgImageColor, colorMap)

          // nearest is in sorted order; pick one of them and draw it to correct place in
          // image
          imageGrid(row)(column) = nearest

          callback.photosCalculated(row, column, nearest)

          val percent = 100.0 * counter / numSubImages
          // TODO: for GUI version, use a display bar
          if (counter % 100 == 0) {
            println(percent + " completed (" + counter + " of" + numSubImages + ")")
          }
          counter+=1
        }
      }
      imageGrid
}

Мой полный исходный код доступен на github

3 голосов
/ 30 марта 2011

Допустим, ваше базовое изображение имеет размер 100x100 пикселей, и у вас есть куча плиток 10x10.

Вы хотите создать мозаичное базовое изображение с 400 маленькими плитками, поэтому каждая плитка содержит 5x5 пикселей в базовойimage.

Для каждой части 5x5 в основном изображении определите средние значения RGB для этих пикселей.

Для каждой плитки определите средние значения RGB.

Совпадениесредние значения RGB каждой части 5x5 к ближайшему совпадению из плиток.

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

...