cardano7
دوشنبه 02 اسفند 1389, 12:33 عصر
سلام
من می خواهم یک متغیر رنگ را به یک palette که مجموعه ای از رنگ هاست نگاشت کنم. شبیه هر رنگی که بود، اون را انتخاب کنه.
در ابتدا برنامه ای نوشتم که این کار را بکنه اما کار به اون سادگی که فکر می کردم نبود.
یک کلاس دارم برای ذخیره ی نام و مقدار رنگ ها:
public class ColorValue
{
public string name;
public Color color;
public ColorValue(string name, Color color)
{
if (name.IndexOf("Color [") >= 0)
name = name.Substring("Color [".Length, name.Length - 1 - "Color [".Length);
this.name = name;
this.color = color;
}
}
و بعد رنگ هایی را که می خواهم به مجموعه اضافه می کنم:
List<ColorValue> color_value = new List<ColorValue>();
color_value.Add(new ColorValue(Color.Black.ToString(), Color.Black));
color_value.Add(new ColorValue(Color.Blue.ToString(), Color.Blue));
color_value.Add(new ColorValue(Color.Blue.ToString(), Color.DarkBlue));
color_value.Add(new ColorValue(Color.Blue.ToString(), Color.LightBlue));
color_value.Add(new ColorValue(Color.Brown.ToString(), Color.Brown));
color_value.Add(new ColorValue(Color.Cyan.ToString(), Color.Cyan));
color_value.Add(new ColorValue(Color.Cyan.ToString(), Color.DarkCyan));
color_value.Add(new ColorValue(Color.Cyan.ToString(), Color.LightCyan));
color_value.Add(new ColorValue(Color.Gray.ToString(), Color.Gray));
color_value.Add(new ColorValue(Color.Gray.ToString(), Color.DarkGray));
color_value.Add(new ColorValue(Color.Gray.ToString(), Color.LightGray));
color_value.Add(new ColorValue(Color.Green.ToString(), Color.Green));
color_value.Add(new ColorValue(Color.Green.ToString(), Color.DarkGreen));
color_value.Add(new ColorValue(Color.Green.ToString(), Color.LightGreen));
color_value.Add(new ColorValue(Color.Orange.ToString(), Color.Orange));
color_value.Add(new ColorValue(Color.Pink.ToString(), Color.Pink));
color_value.Add(new ColorValue(Color.Purple.ToString(), Color.Purple));
color_value.Add(new ColorValue(Color.Red.ToString(), Color.Red));
color_value.Add(new ColorValue(Color.White.ToString(), Color.White));
color_value.Add(new ColorValue(Color.Yellow.ToString(), Color.Yellow));
color_value.Add(new ColorValue(Color.Yellow.ToString(), Color.Wheat));
در ابتدا برنامه را این طوری نوشتم که بیاد ببینه کدوم فاصله ی قرمز و سبز و آبی اون به رنگ های پلت نزدیک تره و اون را انتخاب کنه:
double diff = double.MaxValue;
int index = -1;
foreach (ColorValue cv in color_value)
{
double dr = (cv.color.R - color.R);
double dg = (cv.color.G - color.G);
double db = (cv.color.B - color.B);
double d = dr * dr + dg * dg + db * db;
if (d < diff)
{
index = ColorItem.IndexOf(cv.name);
diff = d;
}
}
اما این راه یک سری مشکلات داره. مثلا گاهی رنگ من آبی خیلی روشن هست و به همین دلیل با سفید اشتباه گرفته میشه. برای همین اومدم و شدت رنگ را هم دخالت دادم . یعنی اول عامل شدت را کنسل می کنم و اون را به عنوان پارامتر چهارم در کنار R , G , B به حساب میارم. و با رنگ های پالت مقایسه می کنم:
double diff = double.MaxValue;
int index = -1;
foreach (ColorValue cv in color_value)
{
double I_cv_color = Math.Sqrt(cv.color.R * cv.color.R + cv.color.G * cv.color.G + cv.color.B * cv.color.B + 1);
double I_color = Math.Sqrt(color.R * color.R + color.G * color.G + color.B * color.B + 1);
double I_Mut = Math.Sqrt(I_cv_color * I_color);
double dr = (cv.color.R * I_color - color.R * I_cv_color) / I_Mut;
double dg = (cv.color.G * I_color - color.G * I_cv_color) / I_Mut;
double db = (cv.color.B * I_color - color.B * I_cv_color) / I_Mut;
double di = I_cv_color - I_color;
double d = dr * dr + dg * dg + db * db + di * di;
if (d < diff)
{
index = ColorItem.IndexOf(cv.name);
diff = d;
}
}
با این روش نتیجه بهتر میشه اما هنوز ایراد داره مثلا خیلی رنگ ها مثل آبی و فیروزه ای را با هم قاطی می کنه.
آیا کسی روش استانداردی برای این کار سراغ داره؟ توجه داشته باشید که باید پلت دلخواه باشه و برنامه نباید برای یک پلت از پیش تعیین شده نوشته بشه. چون این بخش قراره مقدار اولیه ی یک شبکه عصبی را تعیین کنه و کوانتیزه کردن رنگ روی یک پلت از پیش مشخص این برنامه را بی معنی می کنه. هر چند این برنامه را دارم برای دل خودم می نویسم و نه استادی که بهم بخواد گیر بده.
من می خواهم یک متغیر رنگ را به یک palette که مجموعه ای از رنگ هاست نگاشت کنم. شبیه هر رنگی که بود، اون را انتخاب کنه.
در ابتدا برنامه ای نوشتم که این کار را بکنه اما کار به اون سادگی که فکر می کردم نبود.
یک کلاس دارم برای ذخیره ی نام و مقدار رنگ ها:
public class ColorValue
{
public string name;
public Color color;
public ColorValue(string name, Color color)
{
if (name.IndexOf("Color [") >= 0)
name = name.Substring("Color [".Length, name.Length - 1 - "Color [".Length);
this.name = name;
this.color = color;
}
}
و بعد رنگ هایی را که می خواهم به مجموعه اضافه می کنم:
List<ColorValue> color_value = new List<ColorValue>();
color_value.Add(new ColorValue(Color.Black.ToString(), Color.Black));
color_value.Add(new ColorValue(Color.Blue.ToString(), Color.Blue));
color_value.Add(new ColorValue(Color.Blue.ToString(), Color.DarkBlue));
color_value.Add(new ColorValue(Color.Blue.ToString(), Color.LightBlue));
color_value.Add(new ColorValue(Color.Brown.ToString(), Color.Brown));
color_value.Add(new ColorValue(Color.Cyan.ToString(), Color.Cyan));
color_value.Add(new ColorValue(Color.Cyan.ToString(), Color.DarkCyan));
color_value.Add(new ColorValue(Color.Cyan.ToString(), Color.LightCyan));
color_value.Add(new ColorValue(Color.Gray.ToString(), Color.Gray));
color_value.Add(new ColorValue(Color.Gray.ToString(), Color.DarkGray));
color_value.Add(new ColorValue(Color.Gray.ToString(), Color.LightGray));
color_value.Add(new ColorValue(Color.Green.ToString(), Color.Green));
color_value.Add(new ColorValue(Color.Green.ToString(), Color.DarkGreen));
color_value.Add(new ColorValue(Color.Green.ToString(), Color.LightGreen));
color_value.Add(new ColorValue(Color.Orange.ToString(), Color.Orange));
color_value.Add(new ColorValue(Color.Pink.ToString(), Color.Pink));
color_value.Add(new ColorValue(Color.Purple.ToString(), Color.Purple));
color_value.Add(new ColorValue(Color.Red.ToString(), Color.Red));
color_value.Add(new ColorValue(Color.White.ToString(), Color.White));
color_value.Add(new ColorValue(Color.Yellow.ToString(), Color.Yellow));
color_value.Add(new ColorValue(Color.Yellow.ToString(), Color.Wheat));
در ابتدا برنامه را این طوری نوشتم که بیاد ببینه کدوم فاصله ی قرمز و سبز و آبی اون به رنگ های پلت نزدیک تره و اون را انتخاب کنه:
double diff = double.MaxValue;
int index = -1;
foreach (ColorValue cv in color_value)
{
double dr = (cv.color.R - color.R);
double dg = (cv.color.G - color.G);
double db = (cv.color.B - color.B);
double d = dr * dr + dg * dg + db * db;
if (d < diff)
{
index = ColorItem.IndexOf(cv.name);
diff = d;
}
}
اما این راه یک سری مشکلات داره. مثلا گاهی رنگ من آبی خیلی روشن هست و به همین دلیل با سفید اشتباه گرفته میشه. برای همین اومدم و شدت رنگ را هم دخالت دادم . یعنی اول عامل شدت را کنسل می کنم و اون را به عنوان پارامتر چهارم در کنار R , G , B به حساب میارم. و با رنگ های پالت مقایسه می کنم:
double diff = double.MaxValue;
int index = -1;
foreach (ColorValue cv in color_value)
{
double I_cv_color = Math.Sqrt(cv.color.R * cv.color.R + cv.color.G * cv.color.G + cv.color.B * cv.color.B + 1);
double I_color = Math.Sqrt(color.R * color.R + color.G * color.G + color.B * color.B + 1);
double I_Mut = Math.Sqrt(I_cv_color * I_color);
double dr = (cv.color.R * I_color - color.R * I_cv_color) / I_Mut;
double dg = (cv.color.G * I_color - color.G * I_cv_color) / I_Mut;
double db = (cv.color.B * I_color - color.B * I_cv_color) / I_Mut;
double di = I_cv_color - I_color;
double d = dr * dr + dg * dg + db * db + di * di;
if (d < diff)
{
index = ColorItem.IndexOf(cv.name);
diff = d;
}
}
با این روش نتیجه بهتر میشه اما هنوز ایراد داره مثلا خیلی رنگ ها مثل آبی و فیروزه ای را با هم قاطی می کنه.
آیا کسی روش استانداردی برای این کار سراغ داره؟ توجه داشته باشید که باید پلت دلخواه باشه و برنامه نباید برای یک پلت از پیش تعیین شده نوشته بشه. چون این بخش قراره مقدار اولیه ی یک شبکه عصبی را تعیین کنه و کوانتیزه کردن رنگ روی یک پلت از پیش مشخص این برنامه را بی معنی می کنه. هر چند این برنامه را دارم برای دل خودم می نویسم و نه استادی که بهم بخواد گیر بده.