照片拼接算法。如何根据基本图像和瓷砖列表创建马赛克照片?

时间:2011-03-29 20:27:34

标签: c++ algorithm visual-c++ image-processing photo

Hy。我要做的是创建一个程序(使用C或C ++),将24位/像素位图作为输入并收集图像,我必须创建一个马赛克图像,类似于输入图像使用给定的图像库(创建类似于输入的马赛克照片)。

到目前为止,我可以访问输入的图像像素和颜色,但我有点卡住了。我的问题是我应该从哪里开始?我需要一个可以做这种事情的基本算法。我真的找不到任何东西(也许我看错了)。还有人可以告诉我一个随机照片下载器,以便我可以下载项目的小图像?有人能帮我吗?请告诉我从哪里开始和使用什么。

3 个答案:

答案 0 :(得分:16)

我在Scala中完成了这个。 Dr Dobbs article对我非常有用。

示例图片:

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上的

My full sourcecode is available

答案 1 :(得分:3)

假设您的基本图像是100x100像素,并且您有一堆10x10的图块。

您希望使用400个小图块拼接基本图像,因此每个图块在基本图像中包含5x5像素。

对于基本图像中的每个5x5部分,确定这些像素的平均RGB值。

对于每个图块,确定平均RGB值。

将每个5x5零件的平均RGB值与瓷砖中最接近的匹配相匹配。

然后创建马赛克。但是,您需要将平铺缩小到5x5以保持图像大小不变。

答案 2 :(得分:1)

  1. 降低输入图像的分辨率
  2. 对于列表中的每个图像,计算每个通道的平均值(3 个数字 - RGB)
  3. 对于输入图像中值为 (r,g,b) 的每个像素执行以下操作: 从列表中随机抽取 30 个(只是一个效果很好的数字)图像。 对于样本中的每个这样的随机图像,计算 rgb 值之间的距离 (*) 并选择距离最小的图像。

(*) (r1,g1,b1)(r2,g2,b2) 之间的距离可以是例如: (r1-r2)**2+(g1-g2)**2+(b1-b2)**2

就是这样。它工作得很好。 该算法有两个超参数。

  • 输入图像的新分辨率
  • 我们为输入图像中的每个像素采样的图像数量。 你可以和他们一起玩。