طريقة تكميم الصورة. الانتقال من الإشارات والتحولات المستمرة إلى الإشارات المنفصلة

27.04.2019

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

الشكل 8. وظيفة تصف التكميم
مهمة بناء المكمّم هي تحديد قيم العتبات والمستويات. إن أبسط طريقة لحل هذه المشكلة هي تقسيم النطاق الديناميكي إلى فترات زمنية متساوية. ومع ذلك، فإن هذا الحل ليس هو الأفضل. إذا تم تجميع قيم السطوع لغالبية عينات الصور، على سبيل المثال، في المنطقة "المظلمة" وكان عدد المستويات محدودًا، فمن المستحسن قياسها بشكل غير متساو. في المنطقة "المظلمة"، يجب عليك إجراء القياس الكمي بشكل أكثر تكرارًا، وفي المنطقة "المشرقة" بشكل أقل. هذا سوف يقلل من الخطأ الكمي.

في الأنظمة الحقيقية، يتم استخدام نوعين من التكميم بشكل أساسي: تصحيح غاما الخطي. وفي الحالة الأخيرة، تخضع الإشارة التناظرية لتحول غير خطي قبل التكميم س '= س 1 /  . يتم تنفيذ هذه الوظيفة في جميع كاميرات CCD المنتجة تجاريًا تقريبًا. القيمة القياسية لـ  هي 1.4.

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

يعتمد الاختيار الأمثل لعدد مستويات أخذ العينات إلى حد كبير على خصائص جهاز الاستقبال (كاميرا CCD، على سبيل المثال). نادرًا ما تحتوي كاميرات CCD للأغراض العامة على نسبة إشارة إلى ضوضاء أكبر من 46 ديسيبل. يتم إعطاء نسبة الإشارة إلى الضوضاء بالتعبير التالي:
، أين
-السعة القصوى للإشارة المفيدة،
-سعة الضوضاء rms. وبناء على ذلك، مع نسبة الإشارة إلى الضوضاء البالغة 46 ديسيبل، يكون العدد المفيد لمستويات التكميم 200، مما يشير إلى استصواب استخدام جهاز تكميم ثماني بتات.

حاشية. ملاحظة: مقدمة. خوارزمية التقسيم الموحد لمساحة اللون. خوارزمية التقسيم حسب تكرار الحدوث: فكرة الخوارزمية، طريقة تقسيم مكعب الألوان – البحث المفرز محليا. خوارزمية القطع المتوسطة. طرق التجميع لتكميم الصورة: طريقة K-means، أو طريقة اتصال الرسم البياني، أو الطريقة الهرمية، أو طريقة K-means المعممة، أو طريقة التكثيف الديناميكي. خاتمة.

12.1. مقدمة

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

هناك حاجة إلى الكمي من أجل:

  • توفير الذاكرة؛
  • تحسين خصائص تسلسل الضغط؛
  • التحضير للمعالجة اللاحقة.
  • إضافة تأثيرات.

دعونا نعلق على هذه النقاط بمزيد من التفصيل فيما يتعلق بالصور.

من الواضح أنه يتم تحقيق وفورات في الذاكرة عن طريق تقليل تكلفة تخزين قيم السمات. العديد من تنسيقات تخزين الصور، مثل PNG وGIF، بدلاً من تخزين قيم السمات، تقوم بتخزين الأرقام المرجعية في صفوف اللوحة. اللوحة عبارة عن جدول تحتوي صفوفه على قيمة سمة ثابتة. في السابق، تم استخدام آلية اللوحة لإنشاء الصور وعرضها نظرًا لأن حجم ذاكرة الفيديو في كمبيوتر سطح المكتب النموذجي حتى عام 1995 لم يتجاوز ميغابايت واحد.

يتم تحسين خصائص تسلسلات الضغط عن طريق تقليل عدد القيم الممكنة، وبالتالي زيادة التكرارات.


أرز. 12.1.

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

يمكن استخدام تكميم الصورة لإضافة تأثيرات فنية وإبراز الحواف.

تفترض هذه المحاضرة أن قيم سمات بكسلات الصورة تكمن في مساحة ألوان RGB ("المفاهيم الأساسية: تمثيل اللون في رسومات الكمبيوتر"). لسهولة العرض، يتم تقديم الرموز الزائفة للخوارزميات لصورة نصفية 8 بت (256 ظلًا) (انظر الشكل 12.1)، ويتم التحويل إلى صورة 4 بت (16 ظلًا).


أرز. 12.2.

12.2. خوارزمية التقسيم الموحد لمساحة اللون

دعونا نفكر في أبسط خوارزمية التكميم - خوارزمية للتقسيم الموحد لمساحة اللون، أيضا يسمى التكميم الخطي. دعونا نقسم مساحة اللون إلى أجزاء متساوية لكل اتجاه من الاتجاهات الرئيسية (بالنسبة لـ RGB هناك ثلاثة اتجاهات من هذا القبيل - وفقًا لعدد المكونات). على سبيل المثال، في اتجاه المحور الأزرق أو الأخضر (انظر الشكل 1.5) سنقسم المكعب إلى 8 أجزاء، وفي اتجاه المحور الأحمر - إلى 4. نقوم بإدخال مجموعة القيم التي يتم تشكيلها عند تقاطع الأقسام في الجدول. في مثالنا، حصلنا على 256 قيمة، موزعة بالتساوي عبر مكعب RGB. بعد ذلك، يأتي تحويل الصورة إلى البحث عن الرقم المقابل في الجدول بحيث تكون المسافة بين اللون الحقيقي واستبداله ضئيلة. ويمكن القيام بذلك بسرعة باستخدام التقريب.

// من بين 256 ظلًا للون الرمادي، نصنع 16 // I(بكسل) - سمة البكسل // سمة جديدة (بكسل) جديدة - الرقم المرجعي في اللوحة // اللوحة - اللوحة // عدد الظلال في الصورة الأصلية NOldColors = 256؛ // عدد العناصر في اللوحة NNewColors = 16; // 1. املأ اللوحة for(i = 0; i< NNewColors; i++) { Palette[i] = i * (NOldColors / NNewColors); } // 2. Вычиcляем новые значения атрибутов foreach(pixel in I) // для каждого пикселя { // округляем, отбрасывая дробную часть Inew(pixel) = I(pixel) / (NOldColors / NNewColors); } القائمة 12.1. خوارزمية التقسيم الموحد لمساحة اللون

نتيجة لهذه الخوارزمية ( انظر الشكل. 12.2) غالبًا ما تظهر حدود واضحة جدًا في الصورة، ويتم مسح التفاصيل، على العكس من ذلك. ومع ذلك، فإن المزايا الرئيسية لهذه الخوارزمية هي البساطة والسرعة العالية.

يجذب الانتباه

على سبيل المثال، يستخدم تنسيق GIF القديم الجيد لوحة ألوان تصل إلى 256 لونًا. إذا كنت تريد حفظ سلسلة من صورك الشخصية كرسوم متحركة بتنسيق GIF (من سيحتاج إلى ذلك)، فإن أول شيء ستحتاج إليه، أو بالأحرى البرنامج الذي ستستخدمه لهذا، هو إنشاء لوحة ألوان. يمكنك استخدام لوحة ثابتة، على سبيل المثال الألوان الآمنة للويب، وستكون خوارزمية التكميم بسيطة وسريعة للغاية، ولكن النتيجة لن تكون جيدة جدًا. يمكنك إنشاء لوحة ألوان مثالية بناءً على الألوان الموجودة في الصورة، مما سيعطي نتيجة مشابهة بصريًا للأصل.

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

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

خلفية

منذ زمن طويل، عندما كانت شركة نوكيا دافئة وهيمنت الأنابيب على سوق الهواتف الذكية، وكان أصحاب الهواتف الذكية يطلقون على أنفسهم بكل فخر اسم "أشخاص الهواتف الذكية"، في تلك العصور القديمة كتبت برامج بسيطة بلغة بايثون للسلسلة60. لقد عثرت على أحدهم ذات يوم أثناء البحث في الأرشيف. GifTool هو برنامج لإنشاء صور GIF متحركة من مجموعة من الصور. في ذلك، قمت بتنفيذ التكميم باستخدام طريقة القسم المتوسط، وخوارزمية الضغط LZW، وتم إنشاء بنية الملف بالكامل بشكل مستقل، وتم استخدام الشفافية لوحدات البكسل التي لم تتغير في الشريحة التالية لتقليل حجم الملف النهائي. أردت أن أنعش ذاكرتي وأرى كيف تعمل. فتحت الكود و... هذا الشعور عندما لا تتمكن من اكتشاف الكود الرديء الخاص بك منذ عشر سنوات مضت. لم أكن أعرف شيئًا عن PEP8 في ذلك الوقت، لذا كانت سهولة قراءة الكود أقل قليلاً من عدم وجودها (في ذلك الوقت أحببت البساطة، مثل العديد من المبرمجين المبتدئين). ذرفت بعض الدموع، وبصقت، وأعدت بناءه في PyCharm، واكتشفت كيفية تنفيذ طريقة القسم المتوسط، وسرعان ما أنشأت نصًا "قذرًا". يعمل! يتم إنشاء اللوحة، وتكون الصورة الناتجة مقبولة. ثم تساءلت عما إذا كان بإمكاني تحقيق نتائج أفضل بحيث تكون الصورة أقرب ما تكون إلى الصورة الأصلية قدر الإمكان.


لذلك - طريقة القسم المتوسط. انها بسيطة مثل الجحيم. الخطوة الأولى هي إنشاء مكعب RGB من جميع الألوان الفريدة للصورة. بعد ذلك، قم بقصها على طول الجانب الأطول. على سبيل المثال، النطاق الأحمر لدينا هو من 7 إلى 231 (الطول 231-7 = 224)، والأخضر من 32 إلى 170 (الطول 170-32 = 138)، والأزرق من 12 إلى 250 (الطول 250-12 = 238)، وهو ما يعني سنقوم "بقص" المكعب على طول الجانب الأزرق. نقوم أيضًا بقطع الأجزاء الناتجة على طول الجانب الطويل، وما إلى ذلك. حتى نحصل على 256 قطعة. لكل قطعة، احسب متوسط ​​اللون - هكذا نحصل على اللوحة.

هناك صورتان تقريبًا حول الموضوع من أجل الوضوح



ما الذي يمكن تحسينه هنا؟ أول ما يتبادر إلى الذهن هو حساب متوسط ​​اللون، ليس عن طريق جمع كل الألوان بغباء وتقسيمها على عددها [ sum(color) / count(color) ]، ولكن عن طريق الأخذ في الاعتبار عدد مرات ظهور كل لون في الصورة. أي أننا نقوم بضرب كل لون في عدد مرات ظهوره في الصورة، ثم نضيف القيم الناتجة، ونقسم الناتج على عدد مرات ظهوره في الصورة لجميع ألوان هذه القطعة [ sum(color *tal) / sum( المجموع) ]. ونتيجة لذلك، فإن الألوان التي يتم مواجهتها بشكل متكرر لها الأولوية في الحساب، ولكن الألوان النادرة تقوم أيضًا بإجراء تعديلاتها الخاصة، وبالتالي فإن لوحة الألوان أفضل والانحراف البصري للألوان أقل. للحصول على أفضل النتائج، من المستحسن أن تأخذ في الاعتبار أيضًا غاما، لكنني تركت هذا لوقت لاحق. والثاني ليس واضحًا جدًا - فالقسم المتوسط ​​​​لا يأخذ في الاعتبار خصوصيات إدراك اللون بالعين البشرية. نحن ندرك ظلال اللون الأخضر أفضل بكثير من ظلال اللون الأزرق. قررت تصحيح سوء الفهم هذا و"تسوية" المكعب - لقد ضربت أطوال الجوانب في المعاملات من . ونتيجة لذلك، كان هناك المزيد من الأقسام على الجانبين الأخضر والأحمر، وعدد أقل على الجانب الأزرق. لم أجد مثل هذا الحل في أي مكان آخر (ربما لم أبحث عنه جيدًا)، لكن النتيجة واضحة.

الآن لدينا لوحة مثالية، ليست مثالية بالطبع (أعلم أنه يمكن تحسينها بشكل أكبر)، ولكنها جيدة بما فيه الكفاية. والخطوة التالية هي فهرسة ألوان الصورة. الخيار الأبسط هو الجزء الذي يوجد فيه اللون، وكذلك الفهرس. بسرعة وسهولة. ولكن هناك واحدة ولكن، وليس حتى واحدة، لذلك سوف نعود إلى هذه الخطوة لاحقا.

هناك طريقة أخرى لتحسين جودة الصورة الناتجة - تشتت الأخطاء. هنا أيضًا كل شيء بسيط جدًا - نطرح اللون المقابل للوحة من اللون المفهرس، ونحصل على خطأ، وننثره على وحدات البكسل المجاورة وفقًا لصيغة (قالب) معينة، وهي صيغة فلويد شتاينبرغ الأكثر شهرة، والتي هو ما استخدمته. عندما يتم نشر الأخطاء، تصبح التحولات الحادة بين الألوان غير واضحة، ويبدو أن الصورة تحتوي على المزيد من الظلال (الألوان). إذا كنت مهتمًا، يمكنك أن تقرأ عن تشتت الأخطاء بالتفصيل وبشكل مثير للاهتمام. قررت أيضًا إكمال هذه الخوارزمية عن طريق ضرب الخطأ بنفس المعاملات، كما اتضح فيما بعد، كانت هذه فكرة جيدة جدًا - نظرًا لوجود عدد أقل من المقاطع العرضية في النطاق الأزرق، تم الحصول على خطأ كبير فيها، وبدون تصحيح الخطأ في المعاملات، والتشتت أحدث الكثير من "الضجيج" "

الآن يمكنك العودة إلى الفهرسة مرة أخرى. من خلال تشتيت الأخطاء، نقوم بتغيير ألوان البكسلات ونحصل على تلك غير الموجودة في مكعب RGB الخاص بنا (دعني أذكرك، فهو يتكون حصريًا من ألوان الصور). الآن لا يمكنك فقط إلقاء نظرة على الجزء الذي يوجد به اللون لتعيين فهرس. تم العثور على الحل على الفور - البحث عن اللون الأقرب في اللوحة. لقد استبدلت نفس المعاملات في هذه الصيغة. وبمقارنة نتائج اختيار لون اللوحة بناءً على فهرس المقطع الذي يتضمن اللون الأصلي ونتائج البحث عن اللون الأقرب، رأيت بوضوح أن اللون الأقرب غالبًا ما ينتهي في المقطع المجاور. إذا كان اللون المصدر أقرب إلى مركز المقطع، فإن فهرس المقطع يتوافق مع فهرس الألوان الموجود في اللوحة، ولكن كلما كان اللون المصدر أقرب إلى حواف المقطع، زاد احتمال أن يكون اللون الأقرب يكون في الجزء المجاور. بشكل عام، الطريقة الصحيحة الوحيدة للفهرسة هي البحث عن اللون الأقرب في اللوحة. لكن البحث له عيب - فهو بطيء، بطيء جدًا. إن كتابة أداة تحليل الأرقام في لغة بايثون فكرة سيئة.

حسنًا، أردت أن أشرح الأمر باختصار، لكن تبين أن الأمر عبارة عن مجموعة كاملة من الكتابة غير المفهومة. آمل أن أكتب كودًا أفضل مما أشرحه، لذا إليك رابط إلى github. تمت إعادة كتابة الكود عدة مرات، في البداية تم تحسين الخوارزمية حتى لم أكن راضيًا عن النتيجة، ثم اتضح أنها كانت تستهلك الكثير من ذاكرة الوصول العشوائي عند معالجة الصور (أولاً اختبرتها على صور صغيرة)، واضطررت إلى النقل مكعب RGB والقسم المتوسط ​​وخريطة البكسل لقاعدة البيانات (Sqlite). يعمل البرنامج النصي ببطء شديد، لكن النتيجة أفضل من التكميم باستخدام PIL/Pillow وGIMP (تسمى هذه العملية بالفهرسة).

مظاهرة مرئية:

إبداعي

نتيجة التكميم في GIMP، لوحة مثالية مكونة من 256 لونًا + طمس الألوان من Floyd-Stenberg (عادي)

نتيجة التكميم PIL/Pillow image.convert(mode = "P"، ثبات = PIL.Image.FLOYDSTEINBERG، لوحة = PIL.Image.ADAPTIVE، الألوان = 256)

نتيجة التكميم بواسطة الكود الخاص بي

ما يجب الانتباه إليه: تشتيت الأخطاء في GIMP صاخب جدًا، PIL/Pillow ينشئ لوحة ألوان ليست مثالية جدًا ولا يبدد الأخطاء عمليًا (انتقالات حادة بين الألوان).
إذا كنت لا ترى الفرق، فابحث عن أمثلة أخرى على جيثب.


ملاحظة.:هناك برنامج رائع Color Quantizer، الذي يتعامل مع هذه المهمة بشكل أفضل وأسرع، لذا فإن النص الخاص بي ليس له معنى عملي، فقد تم إنشاؤه فقط من باب الاهتمام "الرياضي".
محدث:قام بتحديث المشروع على جيثب. تمت إضافة خوارزمية تكميم Octree، وصيغ تشتيت الأخطاء الشائعة، للبحث عن أقرب لون حسب متوسط ​​القيمة الحمراء.

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

أخذ عينات من الصور

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

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

السؤال الأساسي الذي يطرح نفسه أثناء أخذ العينات: ما هو التردد الذي يجب أن نأخذ فيه عينات الإشارة حتى نتمكن من إعادة بنائها مرة أخرى من هذه العينات؟ ومن الواضح أنه إذا تم أخذ العينات في حالات نادرة جدًا، فإنها لن تحتوي على معلومات حول إشارة سريعة التغير. يتميز معدل تغير الإشارة بالتردد العلوي لطيفها. وبالتالي، فإن الحد الأدنى المسموح به من عرض الفاصل الزمني لأخذ العينات يرتبط بأعلى تردد لطيف الإشارة (يتناسب عكسيا معه).

وفي حالة أخذ العينات الموحدة، ينطبق ما يلي: نظرية كوتيلنيكوف، نُشر عام 1933 في عمل "حول قدرة الهواء والأسلاك في الاتصالات". تقول: إذا كانت الإشارة المستمرة لها طيف محدود بالتردد، فيمكن إعادة بنائها بالكامل وبشكل لا لبس فيه من عيناتها المنفصلة المأخوذة بفترة، أي. مع التردد.

تتم استعادة الإشارة باستخدام الوظيفة . أثبت Kotelnikov أن الإشارة المستمرة التي تلبي المعايير المذكورة أعلاه يمكن تمثيلها كسلسلة:

.

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

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

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

تكميم الصورة

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

أرز. 1. وظيفة تصف التكميم

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

في أنظمة معالجة الصور الرقمية، تسعى جاهدة لتقليل عدد مستويات وعتبات التكميم، حيث أن كمية المعلومات المطلوبة لتشفير الصورة تعتمد على عددها. ومع ذلك، مع وجود عدد صغير نسبيًا من المستويات في الصورة الكمية، قد تظهر ملامح زائفة. تنشأ نتيجة للتغير المفاجئ في سطوع الصورة الكمية وتكون ملحوظة بشكل خاص في المناطق المسطحة من تغيرها. تعمل الخطوط الزائفة على تدهور الجودة المرئية للصورة بشكل كبير، نظرًا لأن الرؤية البشرية حساسة بشكل خاص للخطوط. عند قياس الصور النموذجية بشكل موحد، يلزم وجود 64 مستوى على الأقل.

يجذب الانتباه

على سبيل المثال، يستخدم تنسيق GIF القديم الجيد لوحة ألوان تصل إلى 256 لونًا. إذا كنت تريد حفظ سلسلة من صورك الشخصية كرسوم متحركة بتنسيق GIF (من سيحتاج إلى ذلك)، فإن أول شيء ستحتاج إليه، أو بالأحرى البرنامج الذي ستستخدمه لهذا، هو إنشاء لوحة ألوان. يمكنك استخدام لوحة ثابتة، على سبيل المثال الألوان الآمنة للويب، وستكون خوارزمية التكميم بسيطة وسريعة للغاية، ولكن النتيجة لن تكون جيدة جدًا. يمكنك إنشاء لوحة ألوان مثالية بناءً على الألوان الموجودة في الصورة، مما سيعطي نتيجة مشابهة بصريًا للأصل.

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

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

خلفية

منذ زمن طويل، عندما كانت شركة نوكيا دافئة وهيمنت الأنابيب على سوق الهواتف الذكية، وكان أصحاب الهواتف الذكية يطلقون على أنفسهم بكل فخر اسم "أشخاص الهواتف الذكية"، في تلك العصور القديمة كتبت برامج بسيطة بلغة بايثون للسلسلة60. لقد عثرت على أحدهم ذات يوم أثناء البحث في الأرشيف. GifTool هو برنامج لإنشاء صور GIF متحركة من مجموعة من الصور. في ذلك، قمت بتنفيذ التكميم باستخدام طريقة القسم المتوسط، وخوارزمية الضغط LZW، وتم إنشاء بنية الملف بالكامل بشكل مستقل، وتم استخدام الشفافية لوحدات البكسل التي لم تتغير في الشريحة التالية لتقليل حجم الملف النهائي. أردت أن أنعش ذاكرتي وأرى كيف تعمل. فتحت الكود و... هذا الشعور عندما لا تتمكن من اكتشاف الكود الرديء الخاص بك منذ عشر سنوات مضت. لم أكن أعرف شيئًا عن PEP8 في ذلك الوقت، لذا كانت سهولة قراءة الكود أقل قليلاً من عدم وجودها (في ذلك الوقت أحببت البساطة، مثل العديد من المبرمجين المبتدئين). ذرفت بعض الدموع، وبصقت، وأعدت بناءه في PyCharm، واكتشفت كيفية تنفيذ طريقة القسم المتوسط، وسرعان ما أنشأت نصًا "قذرًا". يعمل! يتم إنشاء اللوحة، وتكون الصورة الناتجة مقبولة. ثم تساءلت عما إذا كان بإمكاني تحقيق نتائج أفضل بحيث تكون الصورة أقرب ما تكون إلى الصورة الأصلية قدر الإمكان.


لذلك - طريقة القسم المتوسط. انها بسيطة مثل الجحيم. الخطوة الأولى هي إنشاء مكعب RGB من جميع الألوان الفريدة للصورة. بعد ذلك، قم بقصها على طول الجانب الأطول. على سبيل المثال، النطاق الأحمر لدينا هو من 7 إلى 231 (الطول 231-7 = 224)، والأخضر من 32 إلى 170 (الطول 170-32 = 138)، والأزرق من 12 إلى 250 (الطول 250-12 = 238)، وهو ما يعني سنقوم "بقص" المكعب على طول الجانب الأزرق. نقوم أيضًا بقطع الأجزاء الناتجة على طول الجانب الطويل، وما إلى ذلك. حتى نحصل على 256 قطعة. لكل قطعة، احسب متوسط ​​اللون - هكذا نحصل على اللوحة.

هناك صورتان تقريبًا حول الموضوع من أجل الوضوح



ما الذي يمكن تحسينه هنا؟ أول ما يتبادر إلى الذهن هو حساب متوسط ​​اللون، ليس عن طريق جمع كل الألوان بغباء وتقسيمها على عددها [ sum(color) / count(color) ]، ولكن عن طريق الأخذ في الاعتبار عدد مرات ظهور كل لون في الصورة. أي أننا نقوم بضرب كل لون في عدد مرات ظهوره في الصورة، ثم نضيف القيم الناتجة، ونقسم الناتج على عدد مرات ظهوره في الصورة لجميع ألوان هذه القطعة [ sum(color *tal) / sum( المجموع) ]. ونتيجة لذلك، فإن الألوان التي يتم مواجهتها بشكل متكرر لها الأولوية في الحساب، ولكن الألوان النادرة تقوم أيضًا بإجراء تعديلاتها الخاصة، وبالتالي تكون لوحة الألوان أفضل والانحراف البصري للألوان أقل. للحصول على أفضل النتائج، من المستحسن أن تأخذ في الاعتبار أيضًا غاما، لكنني تركت هذا لوقت لاحق. والثاني ليس واضحًا جدًا - فالقسم المتوسط ​​​​لا يأخذ في الاعتبار خصوصيات إدراك اللون بالعين البشرية. نحن ندرك ظلال اللون الأخضر أفضل بكثير من ظلال اللون الأزرق. قررت تصحيح سوء الفهم هذا و"تسوية" المكعب - لقد ضربت أطوال الجوانب في المعاملات الواردة في هذه المقالة. ونتيجة لذلك، كان هناك المزيد من الأقسام على الجانبين الأخضر والأحمر، وعدد أقل على الجانب الأزرق. لم أجد مثل هذا الحل في أي مكان آخر (ربما لم أبحث عنه جيدًا)، لكن النتيجة واضحة.

الآن لدينا لوحة مثالية، ليست مثالية بالطبع (أعلم أنه يمكن تحسينها بشكل أكبر)، ولكنها جيدة بما فيه الكفاية. والخطوة التالية هي فهرسة ألوان الصورة. الخيار الأبسط هو الجزء الذي يوجد فيه اللون، وكذلك الفهرس. بسرعة وسهولة. ولكن هناك واحدة ولكن، وليس حتى واحدة، لذلك سوف نعود إلى هذه الخطوة لاحقا.

هناك طريقة أخرى لتحسين جودة الصورة الناتجة - تشتت الأخطاء. هنا أيضًا كل شيء بسيط جدًا - نطرح اللون المقابل للوحة من اللون المفهرس، ونحصل على خطأ، وننثره على وحدات البكسل المجاورة وفقًا لصيغة (قالب) معينة، وهي صيغة فلويد شتاينبرغ الأكثر شهرة، والتي هو ما استخدمته. عندما يتم نشر الأخطاء، تصبح التحولات الحادة بين الألوان غير واضحة، ويبدو أن الصورة تحتوي على المزيد من الظلال (الألوان). إذا كنت مهتمًا، يمكنك أن تقرأ عن تشتت الأخطاء بالتفصيل وبشكل مثير للاهتمام. قررت أيضًا إكمال هذه الخوارزمية عن طريق ضرب الخطأ بنفس المعاملات، كما اتضح فيما بعد، كانت هذه فكرة جيدة جدًا - نظرًا لوجود عدد أقل من المقاطع العرضية في النطاق الأزرق، تم الحصول على خطأ كبير فيها، وبدون تصحيح الخطأ في المعاملات، والتشتت أحدث الكثير من "الضجيج" "

الآن يمكنك العودة إلى الفهرسة مرة أخرى. من خلال تشتيت الأخطاء، نقوم بتغيير ألوان البكسلات ونحصل على تلك غير الموجودة في مكعب RGB الخاص بنا (دعني أذكرك، فهو يتكون حصريًا من ألوان الصور). الآن لا يمكنك فقط إلقاء نظرة على الجزء الذي يوجد به اللون لتعيين فهرس. تم العثور على الحل على الفور - البحث عن اللون الأقرب في اللوحة. لقد استبدلت نفس المعاملات في هذه الصيغة. وبمقارنة نتائج اختيار لون اللوحة بناءً على فهرس المقطع الذي يتضمن اللون الأصلي ونتائج البحث عن اللون الأقرب، رأيت بوضوح أن اللون الأقرب غالبًا ما ينتهي في المقطع المجاور. إذا كان اللون المصدر أقرب إلى مركز المقطع، فإن فهرس المقطع يتوافق مع فهرس الألوان الموجود في اللوحة، ولكن كلما كان اللون المصدر أقرب إلى حواف المقطع، زاد احتمال أن يكون اللون الأقرب يكون في الجزء المجاور. بشكل عام، الطريقة الصحيحة الوحيدة للفهرسة هي البحث عن اللون الأقرب في اللوحة. لكن البحث له عيب - فهو بطيء، بطيء جدًا. إن كتابة أداة تحليل الأرقام في لغة بايثون فكرة سيئة.

حسنًا، أردت أن أشرح الأمر باختصار، لكن تبين أن الأمر عبارة عن مجموعة كاملة من الكتابة غير المفهومة. آمل أن أكتب كودًا أفضل مما أشرحه، لذا إليك رابط إلى github. تمت إعادة كتابة الكود عدة مرات، في البداية تم تحسين الخوارزمية حتى لم أكن راضيًا عن النتيجة، ثم اتضح أنها كانت تستهلك الكثير من ذاكرة الوصول العشوائي عند معالجة الصور (أولاً اختبرتها على صور صغيرة)، واضطررت إلى النقل مكعب RGB والقسم المتوسط ​​وخريطة البكسل لقاعدة البيانات (Sqlite). يعمل البرنامج النصي ببطء شديد، لكن النتيجة أفضل من التكميم باستخدام PIL/Pillow وGIMP (تسمى هذه العملية بالفهرسة).

مظاهرة مرئية:

إبداعي

نتيجة التكميم في GIMP، لوحة مثالية مكونة من 256 لونًا + طمس الألوان من Floyd-Stenberg (عادي)

نتيجة التكميم PIL/Pillow image.convert(mode = "P"، ثبات = PIL.Image.FLOYDSTEINBERG، لوحة = PIL.Image.ADAPTIVE، الألوان = 256)

نتيجة التكميم بواسطة الكود الخاص بي

ما يجب الانتباه إليه: تشتيت الأخطاء في GIMP صاخب جدًا، PIL/Pillow ينشئ لوحة ألوان ليست مثالية جدًا ولا يبدد الأخطاء عمليًا (انتقالات حادة بين الألوان).
إذا كنت لا ترى الفرق، فابحث عن أمثلة أخرى على جيثب.


ملاحظة.:هناك برنامج رائع Color Quantizer، الذي يتعامل مع هذه المهمة بشكل أفضل وأسرع، لذا فإن النص الخاص بي ليس له معنى عملي، فقد تم إنشاؤه فقط من باب الاهتمام "الرياضي".
محدث:قام بتحديث المشروع على جيثب. تمت إضافة خوارزمية تكميم Octree، وصيغ تشتيت الأخطاء الشائعة، للبحث عن أقرب لون حسب متوسط ​​القيمة الحمراء.