三个粗略的总结图像主颜色的算法(C#源代码)

     
前段日子有对象咨询了下分析图像主颜色的算法,小编对这一块也从未怎么深远的切磋,参考了一些小代码,然后本身写了二个一点也不细略的小工具,现共享给大家。

      界面截图如下:

      PHP 1

     
算法的规律很简单,就是总括出图像中各个颜色的分布意况,然后取前N个颜色作为主成分。

     
当然,实际上若是直白对图像的各通道2伍18个色阶实行总计,获得的结果或许是不曾意义的,所以一般都亟待先把2伍18个色阶线性的隐射到更少的色阶范围。

      主要的代码如下:

    static unsafe class Statistics
    {

      
 //’*****************************************************************************************
PHP,      //’** 开发日期 : 二〇一三-6-21
      //’** 作 者 : laviewpbt
      //’** 联系情势: 33184777
      //’** 修改日期 : 二〇一一-6-21
      //’** 版 本 : Version 1.1.1
      //’** 转发请不要删除上述新闻
      //’****************************************************************************************

        [StructLayout(LayoutKind.Sequential)]
        public struct MajorColor : IComparable<MajorColor>
        {
            internal int Color;
            internal int Amount;
            public MajorColor(int Color, int Amount)
            {
                this.Color = Color;
                this.Amount = Amount;
            }
            public int CompareTo(MajorColor obj)
            {
                return this.Amount.CompareTo(obj.Amount);
            }
        }

        // http://www.coolphptools.com/color_extract
        // http://www.wookmark.com/image/268753/30-inspiring-examples-of-levitation-photography-inspirationfeed-com
        public static List<MajorColor> PrincipalColorAnalysis(Bitmap Bmp, int PCAAmount, int Delta = 24)
        {
            List<MajorColor> MC = new List<MajorColor>();

            int X, Y, Width, Height, Stride, Index, TotalColorAmount = 0;
            int HalfDelta;
            byte* Pointer, Scan0;
            BitmapData BmpData = Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            Height = Bmp.Height; Width = Bmp.Width; Stride = BmpData.Stride; Scan0 = (byte*)BmpData.Scan0;

            int[] Table = new int[256 * 256 * 256];
            int[] NonZero = new int[Width * Height];
            int[] Map = new int[256];

            if (Delta > 2)
                HalfDelta = Delta / 2 - 1;
            else
                HalfDelta = 0;

            for (Y = 0; Y < 256; Y++)
            {
                Map[Y] = ((Y + HalfDelta) / Delta) * Delta;
                if (Map[Y] > 255) Map[Y] = 255;
            }
            for (Y = 0; Y < Height; Y++)
            {
                Pointer = Scan0 + Stride * Y;
                for (X = 0; X < Width; X++)
                {
                    Index = (Map[*Pointer] << 16) + (Map[*(Pointer + 1)] << 8) + Map[*(Pointer + 2)];
                    if (Table[Index] == 0)                  //      还没有出现过该颜色
                    {
                        NonZero[TotalColorAmount] = Index;  //      记录下有颜色的位置,同时也记录下了该颜色
                        TotalColorAmount++;                 //      颜色总数+1
                    }
                    Table[Index]++;                         //      对应的颜色数加1
                    Pointer += 3;                          //      移动到下一个像素
                }
            }
            MajorColor[] Result = new MajorColor[TotalColorAmount];
            for (Y = 0; Y < TotalColorAmount; Y++)
            {
                Result[Y].Amount = Table[NonZero[Y]];
                Result[Y].Color = NonZero[Y];
            }   
            Array.Sort(Result);                             // 系统自带的这个排序算法比一般自己写的都要快
            Array.Reverse(Result);  

            for (Y = 0; Y < PCAAmount; Y++)
                MC.Add(new MajorColor(Result[Y].Color, Result[Y].Amount));
            Bmp.UnlockBits(BmpData);
            GC.Collect();                                   // 立即释放掉分配的64MB的内存
            return MC;
        }
    }

   
 总计颜色这一块,其实我一向在探寻一种即不用占非常大内存,速度又快的算法,可是一贯从未想到好办法。
上面包车型地铁代码中是分配了64MB的内部存款和储蓄器来索引计数的,固然对于非常小的图像也急需如此大的内存占用量,可是小编透过比较发现,比用Dictionary之类的依据字典的总结划办公室法如故要快很多的。

   
 关于排序,作者直接觉得本人能写出比系统更快的算法,可是最终小编依旧选取了以上代码中的简便方法。在对Amount实行排序的还要,Color的值也随后随动了。

   
 在那种占用相比大内部存款和储蓄器的代码中,小编觉得应当及时调用GC.Collect()释放掉内部存款和储蓄器。

   
 关于Delta的取值,就好像不太好显著,那些只好说试验明确吧,一般取16-3第22中学间比较客观。

   
 四个参考链接处也有局地比较好的算法的,然而当中的代码是PHP的,改写成C#的相应说依然有自然的难度的,有趣味的心上人能够本野山参考着学习下吧。

   
 从个人的接头来看,我以为那种颜色主成分分析 还足以应用
类似于彩色转索引时
找最佳索引表时用的八叉树算法;也足以用FCM或许KMEANS之类的聚类算法来兑现。待时间足够时自个儿回来实际验证下。

     源代码下载地址:
http://files.cnblogs.com/Imageshop/ColorStatistics.rar

 

***************************笔者:
laviewpbt   时间: 二零一二.4.07    联系QQ:  33184777
 转发请保留本行音讯*************************

相关文章