2011-03-29 116 views
8

Hy。我需要做的是创建一个程序(使用C或C++),该程序将24位/像素位图和图像聚集作为输入,我必须创建一个马赛克图像,类似于使用输入图像给出的图像库(创建一个类似于输入的马赛克照片)。照片马赛克算法。如何根据基本图像和瓷砖列表创建马赛克照片?

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

+1

我敢肯定它的详细描述在专利中:http://v3.espacenet.com/publicationDetails/biblio?CC=US&NR=6137498&KC=&FT=E – 2011-03-29 20:34:54

回答

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 
} 

My full sourcecode is available在github

+0

Hy,我已经完成了我的代码实现它做了一些事情,但它远没有你做的(图片明智)。我做了什么,得到了opencv库,并在C++上工作。我做了一个包含图像(litle tiles)和RGB的平均值的数组, (每个chanel单独)。我得到了一个图像和矩形区域,我做了RGB通道的平均值,(sum =(avgR + avgG_avgB)/ 3),其中avgR =(ImgAvgR-tileAvgR)等。并找到了向量中的最小值,并用瓷砖替换矩形选择.....但不看起来wright。你能帮助我吗? – Alexx 2011-04-02 20:29:43

+1

您应该做的第一件事是确定您的平均颜色计算是否正确。要这样做,而不是用最接近的彩色图像替换子图像,只需将其替换为相同颜色的实心样本即可。如果这样做,那么我们可以从那里去。 – I82Much 2011-04-02 22:40:38

+0

有没有办法将每幅图片至少包含一次?例如,如果我有400张照片的集合,它们中的每一个都将至少包含一次镶嵌。 – Jaka 2013-04-11 07:18:06

3

比方说,你的基本形象是100×100像素,和你有一堆10x10瓦片。

您想要将基本图像与400个小图块拼接起来,因此每个图块都包含基本图像中的5x5像素。

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

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

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

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

+0

Hy,我已经完成了它的代码实现,但它远离你所做的事情(图片明智)。我做了什么,得到了opencv库并开始工作C++。我创建了一个包含图像(litle tiles)和RGB平均值(分别为每个chanel)的数组。我得到了一幅图像,并从中为矩形区域创建了RGB通道的平均值(sum = (avgR + avgG_avgB)/ 3)其中avgR =(ImgAvgR-tileAvgR)等。并找到了矢量中的最小值,并用瓦片替换了选中的矩形..... – Alexx 2011-04-02 20:30:10

+0

我听说用色相比rgb更好,你的意见是什么? – Sycren 2012-04-26 08:52:44