2013-11-24 4 views

ответ

3
  1. Вычислить среднее значение RGB каждого изображения профиля.

  2. в Photoshop (или любой другой графики программное обеспечение для редактирования), создать пользовательскую палитру, содержащую каждый из этих цветов

  3. нагрузки фотографию, которую вы хотите сделать, и масштабировать его вниз так, чтобы ширина и высота в пикселях соответствуют количеству изображений профиля, которые вы хотите иметь в каждом измерении.

  4. Уменьшите глубину цвета изображения до 8 бит или менее, используя палитру, созданную на шаге 1. Убедитесь, что при выполнении этого параметра выбрана опция «сглаживание».

  5. Напишите сценарий для чтения в изображении с пониженной дискретизацией и создайте более крупное изображение, в котором каждый пиксель изображения с понижающей дискретизацией преобразуется в одно изображение профиля.

Возможные улучшения: Если имеется более 256 изображения профиля, вы, вероятно, в конечном итоге с большим количеством цветов, чем могут быть размещены в одной цветовой таблице. Сгруппируйте аналогичные цвета вместе в группах и произвольно выберите изображения из этих групп при рендеринге большого изображения. Вы даже можете выбирать изображения в зависимости от того, насколько хорошо распределение света и тени соответствует распределению в соответствующем разделе исходного изображения.

0

Я просто написал процедуру, чтобы сделать это сегодня в C#. Я увидел фотомозаику, и мне вдруг пришло в голову, как вы это сделаете, поэтому я бросил это вместе как своего рода доказательство концепции. Работала над моей второй попыткой. Любопытное взорвал мой ум:

public void BuildMosaic(string srcFolder, string picFileSrc, string mosaicFile, uint mosaicSizeMultiplier, Size numTiles) 
{ 
    // The file we're going to create a mosaic of 
    Image srcPic = Image.FromFile(picFileSrc); 
    int mosaicWidth = srcPic.Width * (int)mosaicSizeMultiplier; 
    int mosaicHeight = srcPic.Height * (int)mosaicSizeMultiplier; 
    int thumbWidth = mosaicWidth/numTiles.Width; 
    int thumbHeight = mosaicHeight/numTiles.Height; 

    List<ImageInfo> imageInfos = new List<ImageInfo>(); 
    foreach (string filename in Directory.GetFiles(srcFolder)) 
    { 
     string ext = Path.GetExtension(filename).ToUpper(); 
     if (ext == ".JPG" || ext == ".PNG" || ext == ".GIF" || ext == ".JPEG") 
     { 
      imageInfos.Add(ImageInfo.FromImage(filename, new Size(thumbWidth, thumbHeight))); 
     } 
    } 

    int segmentWidth = srcPic.Width/numTiles.Width; 
    int segmentHeight = srcPic.Height/numTiles.Height; 

    Image mosaic = new Bitmap(mosaicWidth, mosaicHeight); 
    Bitmap segBmp = new Bitmap(segmentWidth, segmentHeight); 
    for (int tileX = 0; tileX < numTiles.Width; tileX++) 
    for(int tileY = 0; tileY < numTiles.Height; tileY++) 
    { 
     // Create a bitmap from the original image that we'll try to match a tile to. 
     using (Graphics g = Graphics.FromImage(segBmp)) 
     { 
      g.DrawImage(srcPic, new Rectangle(0, 0, segmentWidth, segmentHeight), new Rectangle(tileX * segmentWidth, tileY * segmentHeight, segmentWidth, segmentHeight), GraphicsUnit.Pixel); 
     } 
     ImageInfo segInfo = ImageInfo.FromImage(segBmp); 

     // Find the matching tile and paint it onto our mosaic 
     ImageInfo match = segInfo.FindMatch(imageInfos.ToArray()); 
     using (Graphics g = Graphics.FromImage(mosaic)) 
     { 
      g.DrawImage(match.Thumbnail, tileX * thumbWidth, tileY * thumbHeight); 
     } 
    } 
    segBmp.Dispose(); 
    mosaic.Save(mosaicFile, ImageFormat.Jpeg); 
    mosaic.Dispose(); 
} 

и класс ImageInfo:

public class ImageInfo 
{ 
    private ImageInfo() 
    { 
    } 

    public string Filename { get; private set; } 
    public int Blue { get; private set; } 
    public int Green { get; private set; } 
    public int Red { get; private set; } 
    public System.Drawing.Image Thumbnail { get; private set; } 

    // Calculate color distance 
    private float CalcDistance(ImageInfo otherImage) 
    { 
     int blueDiff = Math.Abs(Blue - otherImage.Blue); 
     int greenDiff = Math.Abs(Green - otherImage.Green); 
     int redDiff = Math.Abs(Red - otherImage.Red); 
     return (float) Math.Sqrt(blueDiff * blueDiff + greenDiff * greenDiff + redDiff * redDiff); 
    } 

    // Find the image with the closes matching color average 
    internal ImageInfo FindMatch(ImageInfo[] list) 
    { 
     ImageMatch closest = null; 
     foreach (ImageInfo ii in list) 
     { 
      if (closest == null) 
      { 
       closest = new ImageMatch() 
       { 
        Distance = CalcDistance(ii), 
        Info = ii 
       }; 
       continue; 
      } 
      float dist = CalcDistance(ii); 
      if (dist < closest.Distance) 
      { 
       closest = new ImageMatch() 
       { 
        Distance = CalcDistance(ii), 
        Info = ii 
       }; 
      } 
     } 
     return closest.Info; 
    } 

    internal static ImageInfo FromImage(System.Drawing.Bitmap srcBmp) 
    { 
     ImageStatistics stats = new ImageStatistics(srcBmp); 
     return new ImageInfo() 
     { 
      Blue = (int)stats.Blue.Mean, 
      Green = (int)stats.Green.Mean, 
      Red = (int)stats.Red.Mean 
     }; 
    } 

    internal static ImageInfo FromImage(string filename, System.Drawing.Size thumbSize) 
    { 
     using(System.Drawing.Bitmap bmp = System.Drawing.Bitmap.FromFile(filename) as System.Drawing.Bitmap) 
     { 
      ImageStatistics stats = new ImageStatistics(bmp); 
      return new ImageInfo() 
      { 
       Filename = filename, 
       Blue = (int)stats.Blue.Mean, 
       Green = (int)stats.Green.Mean, 
       Red = (int)stats.Red.Mean, 
       Thumbnail = new System.Drawing.Bitmap(bmp, thumbSize) 
      }; 
     } 
    } 

    internal class ImageMatch 
    { 
     public float Distance { get; set; } 
     public ImageInfo Info { get; set; } 
    } 
} 

Первый параметр представляет каталог со всеми "мозаичных" изображения. Они могут быть любого размера. Второй параметр - это изображение, которое вы собираетесь превратить в мозаику. Третий параметр - это выходной файл мозаики. Четвертый - множитель. Он принимает изображение в параметре 2 и умножает высоту и ширину на это значение, и это размер вашего файла мозаики. Последний параметр - это количество элементов X и y, которые составляют мозаику.

В нем используется библиотека обработки изображений AForge.