【问题标题】:How to make a picture out of profile pictures?如何从个人资料图片中制作图片?
【发布时间】:2013-12-09 03:13:10
【问题描述】:

我想创建由个人资料图片组成的图片,就像我在此处附上的那样:

【问题讨论】:

    标签: image-processing twitter information-visualization


    【解决方案1】:
    1. 计算每个配置文件图像的平均 RGB 值。

    2. 在 Photoshop(或几乎任何其他图形编辑软件)中,创建一个包含每种颜色的自定义调色板

    3. 加载您要渲染的照片,然后按比例缩小,使像素的宽度和高度与您希望在每个维度中拥有的个人资料图像的数量相对应。

    4. 使用您在步骤 1 中创建的调色板将图像的位深度减少到 8 位或更少。确保在执行此操作时选择了“抖动”选项。

    5. 编写一个脚本来读取下采样图像并创建一个更大的图像,其中下采样图像的每个像素都被转换为单个轮廓图像。

    可能的改进:如果有超过 256 张个人资料图片,您最终可能会得到比单个颜色表所能容纳的更多颜色。将相似的颜色分组在一起,并在渲染大图像时从这些组中随机选择图像。您甚至可以根据明暗分布与原始图像相应部分的分布匹配程度来选择图像。

    【讨论】:

      【解决方案2】:

      这里有一个python项目,可以实现你想要的照片马赛克效果:http://john2x.com/projects/photomosaic/

      GitHUB

      【讨论】:

        【解决方案3】:

        我今天刚刚用 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 图像处理库。

        【讨论】:

          猜你喜欢
          • 2017-09-30
          • 1970-01-01
          • 1970-01-01
          • 2014-09-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多