照片马赛克算法。如何在给定基本图像和瓷砖列表的情况下创建马赛克照片?

发布于 2024-10-29 00:05:54 字数 253 浏览 6 评论 0原文

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

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

Hy.What I have to do is to create a program (using C or C++), that takes as input a 24bits/pixel bitmap and a gathering of images and I have to create a mosaic image , similar to the input image using the library of images given(To create a mosaic Photo similar to the input).

So far I can access the input's image pixels and the colors from it but I'm kind of stuck. My question is Where should I start? I need a basic algorithm that could do such a thing. And I can't really find any(maybe I'm looking wrong). And also can someone tell me a random photo downloader, so that i can download small images for the project? Can someone help me? Please, tell me where to start and what to use.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

此生挚爱伱 2024-11-05 00:05:54

我已经在 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 上找到

I've done this in Scala. The Dr Dobbs article was extremely useful to me.

Sample image:

Sample photomosaic

Here's my basic algorithm:

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
}

My full sourcecode is available on github

再浓的妆也掩不了殇 2024-11-05 00:05:54

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

您想要用 400 个小图块对基本图像进行马赛克,因此每个图块在基本图像中包含 5x5 像素。

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

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

将每个 5x5 部分的平均 RGB 值与图块中最接近的匹配项进行匹配。

然后创建你的马赛克。不过,您需要将图块缩小到 5x5 以保持图像大小相同。

Let's say your basic image is 100x100 pixels, and you have a bunch of 10x10 tiles.

You want to mosaic the basic image with 400 of the little tiles, so each tile comprises 5x5 pixels in the basic image.

For each 5x5 part in the basic image, determine the average RGB values for those pixels.

For each tile, determine the average RGB values.

Match up the average RGB values of each 5x5 part to the closest match from the tiles.

Then create your mosaic. You'll need to scale the tiles down to 5x5 to keep the image size the same, though.

甜宝宝 2024-11-05 00:05:54
  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

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

  • 输入图像的新分辨率
  • 我们对输入图像中每个像素采样的图像数量。
    你可以和他们两个一起玩。
  1. Decrease the resolution of the input image
  2. For every image in the list compute the average value of every channel (3 numbers - RGB)
  3. For every pixel in the input image with values (r,g,b) do the following:
    Randomly sample 30 (just a number that works well) images from the list.
    For every such random image in the sample, compute the distance (*) between the rgb values and choose the image with smallest distance.

(*) The distance between (r1,g1,b1) and (r2,g2,b2) can be for example:
(r1-r2)**2+(g1-g2)**2+(b1-b2)**2.

That's it. It works pretty well.
There are two hyperparameters for the algorithm.

  • The new resolution of the input image
  • The number of images we sample for every pixel in the input image.
    You can play with both of them.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文