2011-03-29 14 views
8

Hy.Lo que tengo que hacer es crear un programa (usando C o C++), que toma como entrada un mapa de bits de 24bits/pixel y una recolección de imágenes y tengo que crear una imagen de mosaico, similar a la imagen de entrada usando la biblioteca de imágenes dada (Para crear una foto de mosaico similar a la entrada).Foto Algoritmo de mosaico. ¿Cómo crear una foto de mosaico dada la imagen básica y una lista de mosaicos?

Hasta ahora puedo acceder a los píxeles de la imagen de entrada y los colores de ella, pero estoy atascado. Mi pregunta es ¿Por dónde debería empezar? Necesito un algoritmo básico que pueda hacer tal cosa. Y realmente no puedo encontrar ninguno (tal vez me veo mal). ¿Y también alguien puede decirme un descargador de fotos al azar, para que pueda descargar imágenes pequeñas para el proyecto? ¿Alguien me puede ayudar? Por favor, dime por dónde empezar y qué usar.

+1

Estoy seguro de que está descrito en gran detalle en la patente: http://v3.espacenet.com/publicationDetails/biblio?CC=US&NR=6137498&KC=&FT=E –

Respuesta

16

He hecho esto en Scala. El Dr Dobbs article fue extremadamente útil para mí.

imagen de la muestra:

Sample photomosaic

Aquí es mi algoritmo básico:

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 en github

+0

Hy, he hecho mi implementación del código hace algo, pero está muy lejos de lo que hiciste (sabio de la imagen). Lo que hice es, obtuve la biblioteca de opencv y trabajé en C++. Hice una matriz que contenía una imagen (pequeños azulejos) y los valores promedio para RGB, (cada canal por separado). Obtuve una imagen y para un área rectangular de ella hice los valores promedio para los canales RGB, (suma = (avgR + avgG_avgB)/3) donde avgR = (ImgAvgR-tileAvgR) etc. y encontró el mínimo en el vector, y reemplaza el rectángulo seleccionado con el azulejo ..... pero no se ve bien. ¿me puedes ayudar? – Alexx

+1

Lo primero que debe hacer es determinar si su cálculo de color promedio es correcto. Para hacer esto, en lugar de reemplazar la subimagen con la imagen de color más cercana, simplemente reemplácela con una muestra sólida del mismo color. Si eso funciona, entonces podemos ir desde allí. – I82Much

+0

¿Hay alguna forma de incluir cada imagen al menos una vez? por ejemplo, si tengo una colección de 400 imágenes, cada una de ellas se incluirá en el mosaico al menos una vez. – Jaka

3

digamos que su imagen básica es de 100x100 píxeles, y usted tiene un montón de 10x10 azulejos.

Quiere mosaizar la imagen básica con 400 de las pequeñas fichas, por lo que cada ficha contiene 5x5 píxeles en la imagen básica.

Para cada parte de 5x5 en la imagen básica, determine los valores promedio de RGB para esos píxeles.

Para cada mosaico, determine los valores promedio de RGB.

Haga coincidir los valores promedio de RGB de cada parte de 5x5 con la coincidencia más cercana de los mosaicos.

A continuación, cree su mosaico. Sin embargo, tendrá que escalar las fichas hasta 5x5 para mantener el mismo tamaño de imagen.

+0

Hy, he hecho mi implementación del código, hace algo, pero está muy lejos de lo que hiciste (imagen sabia) .Lo que hice fue, obtuve la librería opencv y trabajé en C++. Hice una matriz que contenía una imagen (pequeños mosaicos) y los valores promedio para RGB, (cada canal por separado). Obtuve una imagen y para un área rectangular de ella hice los valores promedio para los canales RGB, (suma = (avgR + avgG_avgB)/3) donde avgR = (ImgAvgR-tileAvgR) etc. y encontré el mínimo en el vector, y reemplacé el rectángulo seleccionado con el mosaico ..... – Alexx

+0

He escuchado que es mejor usar hue en lugar de rgb, ¿cuál es su opinión? – Sycren

Cuestiones relacionadas