2011-03-29 119 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