كيف يمكنني تقليل الصورة النقطية إلى مجموعة معروفة من ألوان RGB

StackOverflow https://stackoverflow.com/questions/622573

  •  05-07-2019
  •  | 
  •  

سؤال

بالنسبة لمشروع هواية، سأقوم بإنشاء برنامج عندما يتم إعطاؤه صورة نقطية، فإنه سينشئ نمطًا متقاطعًا كملف PDF.سأستخدم Cocoa/Objective C على جهاز Mac.

عادةً ما تكون الصورة النقطية المصدر عبارة عن صورة بحجم 24 بت في الثانية، ولكن من بين ملايين الألوان المتاحة، لا يوجد سوى عدد قليل منها كخيوط متقاطعة.المواضيع تأتي في أنواع مختلفة.DMC هو الأكثر توفرًا على نطاق واسع، ونطاقه بالكامل تقريبًا متاح كقيم RGB من مواقع الويب المختلفة. هنا واحد, ، على سبيل المثال.

DMC#  Name               R   G   B
----- ------------------ --- --- ---
blanc White              255 255 255
208   Lavender - vy dk   148  91 128
209   Lavender - dk      206 148 186
210   Lavender - md      236 207 225
211   Lavender - lt      243 218 228
      ...etc...

مشكلتي الأولى، كما أراها، هي من نقطة بداية RGB من بكسل في الصورة باختيار أقرب لون متاح من مجموعة DMC.ما هي أفضل طريقة للعثور على أقرب لون DMC رياضيًا، والتأكد من ملاءمته للون أيضًا؟

على الرغم من أنني سأستخدم Cocoa، فلا تتردد في استخدام الكود الزائف (أو حتى Java!) في أي كود تنشره.

هل كانت مفيدة؟

المحلول

استخدم ال مختبر مساحة اللون والعثور على اللون مع الأقرب المسافة الإقليدية.سيؤدي القيام بذلك في مساحة ألوان RGB إلى نتائج غير بديهية.(أو استخدم HSL مساحة اللون.)

لذلك، قم فقط بالتكرار فوق كل بكسل وابحث عن اللون بأقرب مسافة ضمن مساحة اللون التي تختارها.لاحظ أنه يجب حساب المسافة بشكل دائري لبعض مساحات الألوان (على سبيل المثال.أولئك الذين يعملون مسحة).

(تدور معظم عمليات تكميم الألوان حول الاختيار الفعلي للوحة الألوان، ولكن تم الاهتمام بذلك بالفعل في حالتك، لذا لا يمكنك استخدام تقنيات التكميم الأكثر شيوعًا.)

أيضا، تحقق من هذا السؤال.

للعثور على لون HSB في الكاكاو، يبدو أنه يمكنك استخدام تم الإعلان عن طريقة getHue في NSColor.h.

ومع ذلك، إذا قمت فقط بتحويل صورة إلى تصميم متقاطع باستخدام هذه التقنية، فسيكون من الصعب جدًا خياطتها فعليًا. سيكون مليئًا بحقول الألوان أحادية البكسل، وهو ما يتعارض مع غرض الخياطة المتقاطعة.

نصائح أخرى

وهذا ما يسمى لون تكميم ، وهناك العديد من خوارزميات المتاحة.

واحدة أساسية جدا هو مجرد علاج ألوان RGB كنقاط في الفضاء، واستخدام المسافة الإقليدية سهل القديمة بين الألوان لمعرفة كيفية "قريبة" هم. وهذا له عيوب، لأن العين البشرية لها حساسية مختلفة في أماكن مختلفة في هذا المجال، وبالتالي فإن هذه المسافة لا تتوافق بشكل جيد لكيفية إدراك البشر الألوان. يمكنك استخدام مخططات الترجيح المختلفة لتحسين هذا الوضع.

وإينتيريستينج ...:)

وأنت لا تعرف إلا أقرب الألوان، سوف تحتاج أيضا إلى تقليل عدد الألوان المستخدمة. كنت لا تريد في نهاية المطاف مع نمط خياطة يستخدم مئات من مختلف الألوان ...

ولقد وضعت بعض التعليمات البرمجية التي تفعل ذلك على المستوى الأساسي. (عذرا أنه في C #، وآمل أنه يمكن أن يكون مفيدا إلى حد ما على أي حال.)

وهناك بعض التغيير والتبديل المزيد الذي يتعين القيام به قبل الأسلوب يعمل بشكل جيد، بطبيعة الحال. الأوزان طريقة GetDistance أهمية هوى، والتشبع والسطوع ضد بعضها البعض، والعثور على أفضل توازن بين تلك هي بالطبع مهمة من أجل العثور على اللون الذي يبدو الأقرب.

وهناك أيضا الكثير الذي يمكن القيام به مع طريقة للحد من اللوحة. في المثال أنا فقط اختار الألوان الأكثر استخداما، ولكن ربما كنت ترغب في الوزن في كيفية حد سواء الألوان في لوحة. ويمكن أن يتم ذلك عن طريق اختيار اللون الأكثر استخداما، والحد من عدد للألوان المتبقية في القائمة اعتمادا على مسافة للون اختار، ومن ثم اللجوء القائمة.

والطبقة الأعرج الذي يحمل اللون DMC، يمكن حساب المسافة إلى لون آخر، والعثور على أقرب لون في قائمة الألوان:

public class Hsl {

    public string DmcNumber { get; private set; }
    public Color Color { get; private set; }
    public float Hue { get; private set; }
    public float Saturation { get; private set; }
    public float Brightness { get; private set; }
    public int Count { get; set; }

    public Hsl(Color c) {
        DmcNumber = "unknown";
        Color = c;
        Hue = c.GetHue();
        Saturation = c.GetSaturation();
        Brightness = c.GetBrightness();
        Count = 0;
    }

    public Hsl(string dmc, int r, int g, int b)
        : this(Color.FromArgb(r, g, b))
    {
        DmcNumber = dmc;
    }

    private static float AngleDifference(float a1, float a2) {
        float a = Math.Abs(a1 - a2);
        if (a > 180f) {
            a = 360f - a;
        }
        return a / 180f;
    }

    public float GetDistance(Hsl other) {
        return
            AngleDifference(Hue, other.Hue) * 3.0f +
            Math.Abs(Saturation - other.Saturation) +
            Math.Abs(Brightness - other.Brightness) * 4.0f;
    }

    public Hsl GetNearest(IEnumerable<Hsl> dmcColors) {
        Hsl nearest = null;
        float nearestDistance = float.MaxValue;
        foreach (Hsl dmc in dmcColors) {
            float distance = GetDistance(dmc);
            if (distance < nearestDistance) {
                nearestDistance = distance;
                nearest = dmc;
            }
        }
        return nearest;
    }

}

وهذا الرمز يضع ل(المقلصة أصلا) قائمة الألوان DMC، تحميل صورة، بحساب الألوان، ويقلل من لوحة وتحويل الصورة. هل بالطبع تحتاج أيضا لحفظ المعلومات من انخفاض لوحة في مكان ما.

Hsl[] dmcColors = {
    new Hsl("blanc", 255, 255, 255),
    new Hsl("310", 0, 0, 0),
    new Hsl("317", 167, 139, 136),
    new Hsl("318", 197, 198, 190),
    new Hsl("322", 81, 109, 135),
    new Hsl("336", 36, 73, 103),
    new Hsl("413", 109, 95, 95),
    new Hsl("414", 167, 139, 136),
    new Hsl("415", 221, 221, 218),
    new Hsl("451", 179, 151, 143),
    new Hsl("452", 210, 185, 175),
    new Hsl("453", 235, 207, 185),
    new Hsl("503", 195, 206, 183),
    new Hsl("504", 206, 221, 193),
    new Hsl("535", 85, 85, 89)
};

Bitmap image = (Bitmap)Image.FromFile(@"d:\temp\pattern.jpg");

// count colors used
List<Hsl> usage = new List<Hsl>();
for (int y = 0; y < image.Height; y++) {
    for (int x = 0; x < image.Width; x++) {
        Hsl color = new Hsl(image.GetPixel(x, y));
        Hsl nearest = color.GetNearest(dmcColors);
        int index = usage.FindIndex(h => h.Color.Equals(nearest.Color));
        if (index != -1) {
            usage[index].Count++;
        } else {
            nearest.Count = 1;
            usage.Add(nearest);
        }
    }
}

// reduce number of colors by picking the most used
Hsl[] reduced = usage.OrderBy(c => -c.Count).Take(5).ToArray();

// convert image
for (int y = 0; y < image.Height; y++) {
    for (int x = 0; x < image.Width; x++) {
        Hsl color = new Hsl(image.GetPixel(x, y));
        Hsl nearest = color.GetNearest(reduced);
        image.SetPixel(x, y, nearest.Color);
    }
}

image.Save(@"d:\temp\pattern.png", System.Drawing.Imaging.ImageFormat.Png);

والحصول على مصدر للتطبيق ppmquant من netpbm مجموعة من المرافق

وأشار

وآخرون إلى تقنيات مختلفة لتكميم اللون. فمن الممكن لاستخدام تقنيات مثل حقل ماركوف العشوائي في محاولة لمعاقبة النظام لتحويل الألوان موضوع في مواقع بكسل المجاورة. هناك بعض متعددة تسمية المكتبات العامة MRF هناك بما في ذلك Boykov في .

لاستخدام واحد من هؤلاء، وعناصر البيانات ستكون الألوان المدخلات، فإن التسميات تكون مجموعة من الألوان موضوع، يمكن أن شروط البيانات يكون شيئا مثل المسافة الإقليدية في الفضاء LAB اقترحه bzlm، وسوف شروط حي معاقبة لتحويل الألوان موضوع.

وتبعا لأهمية صحة عمليات اللون الخاص بك، تذكر أن تأخذ لون الفضاء الصورة بعين الاعتبار. بينما كنت قد درست هذا إلى حد ما، وذلك بسبب هوايتي التصوير الفوتوغرافي، وأنا ما زلت مشوشة قليلا عن كل شيء.

ولكن، وكما ذكر سابقا، استخدم LAB قدر الإمكان، وذلك لأن (AFAIK) انها مساحة اللون الملحد، في حين أن جميع الطرق الأخرى (RGB / HSL / CMYK) لا تعني شيئا (نظريا) من دون لون الفضاء محددة.

وRGB، على سبيل المثال، هو مجرد ثلاث قيم النسبة المئوية (0-255 => 0-100٪، مع عمق اللون 8 بت). لذلك، إذا كان لديك RGB-الثلاثي من (0،255،0)، فإنه يترجم إلى "الأخضر فقط، وأكبر قدر من ذلك قدر الإمكان". لذا، فإن السؤال هو "كيف الأحمر هو أحمر؟". هذا هو السؤال الذي لون إجابات الفضاء - إس آر جي بي 100٪ والاخضر ليست خضراء كما AdobeRGB 100٪ والاخضر. انها ليست حتى في نفس هوى !

عذرا إذا ذهب هذا إلى جانب offtopic من الأشياء

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top