//三平方の定理で、類似度を判定します.(YCbCr) // static int CalcColorScoreYCbCr(ColorRanking c, double Yc, double Ycb, double Ycr) // { // double r = c.Yc - Yc; // double g = c.Ycb - Ycb; // double b = c.Ycr - Ycr; // return (int)Math.Sqrt((r * r) + (g * g) + (b * b)); // } List <ColorRanking> AssingPalette(int palette, List <ColorRanking> totalRank, List <TileMapping> tileMapping) { List <ColorRanking> pal = new List <ColorRanking>(); if (totalRank.Count <= 0) {//もう未割当の色はない. return(pal); } //最も利用されている色を取り出す. ColorRanking topC = totalRank[0]; totalRank.RemoveAt(0); //この色が使われているタイルの処理. for (int i = 0; i < tileMapping.Count; i++) { int found = FindColor(tileMapping[i].Rank, topC); if (found >= 0) { //タイルの割り当て tileMapping[i].Palette = palette; //タイルの色をすべてパレットに追加. ついでに、色ランキングから消去. InsertColorRank(pal, tileMapping[i].Rank, totalRank); } } return(pal); }
//三平方の定理で、類似度を判定します. static int CalcColorScore(ColorRanking c, int r2, int g2, int b2) { // ColorRanking c2 = new ColorRanking(r2,g2,b2); // return CalcColorScoreYCbCr(c, c2.Yc, c2.Ycb, c2.Ycr); int r = c.R - r2; int g = c.G - g2; int b = c.B - b2; return((int)Math.Sqrt((r * r) + (g * g) + (b * b))); }
int FindColor(List <ColorRanking> rank, ColorRanking c) { for (int i = 0; i < rank.Count; i++) { if (rank[i].R == c.R && rank[i].G == c.G && rank[i].B == c.B) { return(i); } } return(-1); }
void VoteColor(List <ColorRanking> rank, int r, int g, int b) { for (int i = 0; i < rank.Count; i++) { if (rank[i].R == r && rank[i].G == g && rank[i].B == b) { rank[i].Count++; return; } } ColorRanking rr = new ColorRanking(r, g, b); rank.Add(rr); }
public ColorRanking Clone() { ColorRanking a = new ColorRanking(); a.R = this.R; a.G = this.G; a.B = this.B; // a.Yc = this.Yc; // a.Ycb = this.Ycb; // a.Ycr = this.Ycr; a.Count = this.Count; a.PaletteNumber = this.PaletteNumber; return(a); }
void InsertColorRank(List <ColorRanking> pal, List <ColorRanking> rank, List <ColorRanking> totalRank) { for (int i = 0; i < rank.Count; i++) { int found = FindColor(pal, rank[i]); if (found >= 0) { pal[found].Count += rank[i].Count; } else { ColorRanking c = rank[i].Clone(); pal.Add(c); } //割り当てた色は、色ランキングから消す. found = FindColor(totalRank, rank[i]); if (found >= 0) { totalRank.RemoveAt(found); } } }
void VoteColor(List <ColorRanking> rank, ColorRanking c) { VoteColor(rank, c.R, c.G, c.B); }
//色がどれだけ似ていないかを求めます. 0は同一 数値が大きなればなるほど似ていません. static int CalcColorScore(ColorRanking c, ColorRanking c2) { return(CalcColorScore(c, c2.R, c2.G, c2.B)); // return CalcColorScoreYCbCr(c, c2.Yc, c2.Ycb, c2.Ycr); }
//パレットを16色にします. static ColorRanking[] Convert16Color(List <ColorRanking> countList, bool isReserve1StPalette, int maxColor = 16) { SortColor(countList); ColorRanking[] center = new ColorRanking[maxColor]; int pal16; int first; if (isReserve1StPalette) {//最初のパレットが背景色で予約されている場合 pal16 = maxColor - 1; first = 1; center[0] = new ColorRanking(); } else { pal16 = maxColor; first = 0; } if (countList.Count < pal16) {//16色以下しかないなら、それで確定. for (int i = 0; i < countList.Count; i++) { countList[i].PaletteNumber = i + first; center[i + first] = countList[i].Clone(); } for (int i = countList.Count; i < pal16; i++) { center[i + first] = new ColorRanking(); } return(center); } //k-means法で16色にクラスタ化していきます。 for (int k = 0; k < pal16; k++) { countList[k].PaletteNumber = k + first; center[k + first] = countList[k].Clone(); } while (true) { //Assignment処理 //一番近い中心点に所属を変えていく. bool isUpdate = false; for (int i = 0; i < countList.Count; i++) { int best = 0; int min_score = Int32.MaxValue; for (int k = 0; k < pal16; k++) { int kk = k + first; int score = CalcColorScore(center[kk], countList[i]); if (score < min_score) { min_score = score; best = kk; } } if (countList[i].PaletteNumber != best) { countList[i].PaletteNumber = best; isUpdate = true; } } if (isUpdate == false) {//クラスタに変化がないので終了. break; } //Update //クラスタの中心点の移動. for (int k = 0; k < pal16; k++) { int kk = k + first; UInt64 r = 0; UInt64 g = 0; UInt64 b = 0; UInt64 count = 0; for (int i = 0; i < countList.Count; i++) { if (countList[i].PaletteNumber != kk) { continue; } count += (UInt64)countList[i].Count; r += (UInt64)(countList[i].R * countList[i].Count); g += (UInt64)(countList[i].G * countList[i].Count); b += (UInt64)(countList[i].B * countList[i].Count); } if (count == 0) { center[kk].SetRGB(0, 0, 0); } else { center[kk].SetRGB((int)(r / count), (int)(g / count), (int)(b / count)); } } } return(center); }