Как сделать картинку из картинки профиля?

Я хочу создать картинки из профильных картинок, как я прикрепил здесь:

3 ответа

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

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

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

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

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

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

Вот проект Python, который обеспечивает эффект фото-мозаики, который вы ищете: http://john2x.com/projects/photomosaic/

а также

на GitHUB

Я только что написал процедуру, чтобы сделать это сегодня в 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.

Другие вопросы по тегам