Я хочу создать фотографии, сделанные из рисунков профиля, как тот, который я прилагается здесь:Как сделать снимок из профайла?
ответ
Вычислить среднее значение RGB каждого изображения профиля.
в Photoshop (или любой другой графики программное обеспечение для редактирования), создать пользовательскую палитру, содержащую каждый из этих цветов
нагрузки фотографию, которую вы хотите сделать, и масштабировать его вниз так, чтобы ширина и высота в пикселях соответствуют количеству изображений профиля, которые вы хотите иметь в каждом измерении.
Уменьшите глубину цвета изображения до 8 бит или менее, используя палитру, созданную на шаге 1. Убедитесь, что при выполнении этого параметра выбрана опция «сглаживание».
Напишите сценарий для чтения в изображении с пониженной дискретизацией и создайте более крупное изображение, в котором каждый пиксель изображения с понижающей дискретизацией преобразуется в одно изображение профиля.
Возможные улучшения: Если имеется более 256 изображения профиля, вы, вероятно, в конечном итоге с большим количеством цветов, чем могут быть размещены в одной цветовой таблице. Сгруппируйте аналогичные цвета вместе в группах и произвольно выберите изображения из этих групп при рендеринге большого изображения. Вы даже можете выбирать изображения в зависимости от того, насколько хорошо распределение света и тени соответствует распределению в соответствующем разделе исходного изображения.
Вот питон проект, который достигает фото эффект мозаики ваш ищет: 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.