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

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

في ذاكرة الكمبيوتر ، يتميز كل مكون لون برقم من 0 إلى 255. أي أنه يجمع بين قيم مختلفة من الأحمر والأخضر والأزرق ، نحصل على لوحة ألوان على الشاشة.
باستخدام وحدات البكسل كمثال ، نقوم بتنفيذ الخوارزمية الخاصة بنا. K- يعني خوارزمية تكرارية ، أي أنها ستعطي النتيجة الصحيحة ، بعد عدد معين من التكرار لبعض الحسابات الرياضية.
خوارزمية
- يجب أن تعرف مقدمًا عدد المجموعات التي تحتاجها لتوزيع البيانات. يعد هذا عيبًا كبيرًا لهذه الطريقة ، ولكن يتم حل هذه المشكلة من خلال التطبيقات المحسنة للخوارزمية ، ولكن هذه ، كما يقولون ، قصة مختلفة تمامًا.
- نحن بحاجة إلى اختيار المراكز الأولية لمجموعاتنا. كيف؟ نعم بشكل عشوائي. لماذا؟ بحيث يمكنك انجذاب كل بكسل إلى مركز الكتلة. المركز مثل الملك ، حيث يتم تجميع رعاياه - بكسل. إن "المسافة" من المركز إلى البكسل هي التي تحدد لمن تطيعه كل بكسل.
- نحسب المسافة من كل مركز إلى كل بكسل. تعتبر هذه المسافة هي المسافة الإقليدية بين النقاط في الفضاء ، وفي حالتنا ، المسافة بين مكونات الألوان الثلاثة:
$$ display $$ \ sqrt {(R_ {2} -R_ {1}) ^ 2 + (G_ {2} -G_ {1}) ^ 2 + (B_ {2} -B_ {1}) ^ 2} . $$ display $$
نحسب المسافة من البكسل الأول إلى كل مركز ونحدد أصغر مسافة بين هذه البكسل والمراكز. بالنسبة للمركز ، والمسافة التي هي أصغرها ، نقوم بإعادة حساب الإحداثيات كمتوسط حسابي بين كل مكون من عناصر البكسل - الملك والبكسل - للموضوع. يتغير مركزنا في الفضاء وفقًا للحسابات. - بعد إعادة سرد جميع المراكز ، نقوم بتوزيع وحدات البكسل في مجموعات ، ومقارنة المسافة من كل بكسل إلى المراكز. يتم وضع البكسل في كتلة ، يكون مركزها أقرب منه إلى المراكز الأخرى.
- يبدأ كل شيء مرة أخرى ، طالما بقيت البكسل في نفس العناقيد. غالبًا ما لا يحدث هذا ، نظرًا لأن كمية كبيرة من البيانات ستتحرك المراكز في نصف قطر صغير ، وستقفز وحدات البكسل على طول حواف المجموعات إلى مجموعة أو أخرى. للقيام بذلك ، حدد الحد الأقصى لعدد التكرارات.
التنفيذ
سأقوم بتنفيذ هذا المشروع في C ++. الملف الأول هو "k_means.h" ، حيث قمت بتعريف أنواع البيانات الرئيسية والثوابت والفئة الرئيسية للعمل - "K_means".
لتمييز كل بكسل ، قم بإنشاء هيكل يتكون من ثلاثة مكونات بكسل ، اخترت النوع المزدوج لها لإجراء حسابات أكثر دقة ، كما حددت بعض الثوابت ليعمل البرنامج:
const int KK = 10;
K_ يعني الصف نفسه:
class K_means { private: std::vector<rgb> pixcel; int q_klaster; int k_pixcel; std::vector<rgb> centr; void identify_centers(); inline double compute(rgb k1, rgb k2) { return sqrt(pow((k1.r - k2.r),2) + pow((k1.g - k2.g), 2) + pow((k1.b - k2.b), 2)); } inline double compute_s(double a, double b) { return (a + b) / 2; }; public: K_means() : q_klaster(0), k_pixcel(0) {}; K_means(int n, rgb *mas, int n_klaster); K_means(int n_klaster, std::istream & os); void clustering(std::ostream & os); void print()const; ~K_means(); friend std::ostream & operator<<(std::ostream & os, const K_means & k); };
لنستعرض مكونات الفصل:
vectorpixcel - ناقل للبكسل ؛
q_klaster - عدد العناقيد ؛
k_pixcel - عدد البكسل ؛
Vectorcentr - متجه لمراكز التجميع ، يتم تحديد عدد العناصر فيه بواسطة q_klaster ؛
Ident_centers () - طريقة لاختيار المراكز الأولية عشوائيًا بين وحدات بكسل الإدخال ؛
compute () و compute_s () طريقتان مدمجتان لحساب المسافة بين البكسل ومراكز إعادة الحساب ، على التوالي ؛
ثلاثة مُنشئات: الأول بشكل افتراضي ، والثاني هو لتهيئة وحدات البكسل من مصفوفة ، والثالث لتهيئة وحدات البكسل من ملف نصي (في التطبيق الخاص بي ، يتم تعبئة الملف عن طريق الخطأ بالبيانات في البداية ، ثم تتم قراءة وحدات البكسل من هذا الملف لكي يعمل البرنامج ، لماذا لا مباشرة إلى المتجه - مطلوب فقط في حالتي) ؛
التجمع (std :: ostream & os) - طريقة التجميع ؛
طريقة وحمل بيان المخرجات الزائد لنشر النتائج.
تنفيذ الأسلوب:
void K_means::identify_centers() { srand((unsigned)time(NULL)); rgb temp; rgb *mas = new rgb[q_klaster]; for (int i = 0; i < q_klaster; i++) { temp = pixcel[0 + rand() % k_pixcel]; for (int j = i; j < q_klaster; j++) { if (temp.r != mas[j].r && temp.g != mas[j].g && temp.b != mas[j].b) { mas[j] = temp; } else { i--; break; } } } for (int i = 0; i < q_klaster; i++) { centr.push_back(mas[i]); } delete []mas; }
هذه طريقة لاختيار مراكز التجميع الأولية وإضافتها إلى ناقل المركز. يتم إجراء فحص لتكرار المراكز واستبدالها في هذه الحالات.
K_means::K_means(int n, rgb * mas, int n_klaster) { for (int i = 0; i < n; i++) { pixcel.push_back(*(mas + i)); } q_klaster = n_klaster; k_pixcel = n; identify_centers(); }
تطبيق منشئ لتهيئة وحدات البكسل من صفيف.
K_means::K_means(int n_klaster, std::istream & os) : q_klaster(n_klaster) { rgb temp; while (os >> temp.r && os >> temp.g && os >> temp.b) { pixcel.push_back(temp); } k_pixcel = pixcel.size(); identify_centers(); }
نقوم بتمرير كائن إدخال إلى هذا المُنشئ حتى نتمكن من إدخال البيانات من كل من الملف ووحدة التحكم.
void K_means::clustering(std::ostream & os) { os << "\n\n :" << std::endl; std::vector<int> check_1(k_pixcel, -1); std::vector<int> check_2(k_pixcel, -2); int iter = 0; while(true) { os << "\n\n---------------- №" << iter << " ----------------\n\n"; { for (int j = 0; j < k_pixcel; j++) { double *mas = new double[q_klaster]; for (int i = 0; i < q_klaster; i++) { *(mas + i) = compute(pixcel[j], centr[i]); os << " " << j << " #" << i << ": " << *(mas + i) << std::endl; } double min_dist = *mas; int m_k = 0; for (int i = 0; i < q_klaster; i++) { if (min_dist > *(mas + i)) { min_dist = *(mas + i); m_k = i; } } os << " #" << m_k << std::endl; os << " #" << m_k << ": "; centr[m_k].r = compute_s(pixcel[j].r, centr[m_k].r); centr[m_k].g = compute_s(pixcel[j].g, centr[m_k].g); centr[m_k].b = compute_s(pixcel[j].b, centr[m_k].b); os << centr[m_k].r << " " << centr[m_k].g << " " << centr[m_k].b << std::endl; delete[] mas; } int *mass = new int[k_pixcel]; os << "\n : "<< std::endl; for (int k = 0; k < k_pixcel; k++) { double *mas = new double[q_klaster]; for (int i = 0; i < q_klaster; i++) { *(mas + i) = compute(pixcel[k], centr[i]); os << " №" << k << " #" << i << ": " << *(mas + i) << std::endl; } double min_dist = *mas; int m_k = 0; for (int i = 0; i < q_klaster; i++) { if (min_dist > *(mas + i)) { min_dist = *(mas + i); m_k = i; } } mass[k] = m_k; os << " №" << k << " #" << m_k << std::endl; } os << "\n : \n"; for (int i = 0; i < k_pixcel; i++) { os << mass[i] << " "; check_1[i] = *(mass + i); } os << std::endl << std::endl; os << " : " << std::endl; int itr = KK + 1; for (int i = 0; i < q_klaster; i++) { os << " #" << i << std::endl; for (int j = 0; j < k_pixcel; j++) { if (mass[j] == i) { os << pixcel[j].r << " " << pixcel[j].g << " " << pixcel[j].b << std::endl; mass[j] = ++itr; } } } delete[] mass; os << " : \n" ; for (int i = 0; i < q_klaster; i++) { os << centr[i].r << " " << centr[i].g << " " << centr[i].b << " - #" << i << std::endl; } } iter++; if (check_1 == check_2 || iter >= max_iterations) { break; } check_2 = check_1; } os << "\n\n ." << std::endl; }
الطريقة الرئيسية للتجميع.
std::ostream & operator<<(std::ostream & os, const K_means & k) { os << " : " << std::endl; for (int i = 0; i < k.k_pixcel; i++) { os << k.pixcel[i].r << " " << k.pixcel[i].g << " " << k.pixcel[i].b << " - №" << i << std::endl; } os << std::endl << " : " << std::endl; for (int i = 0; i < k.q_klaster; i++) { os << k.centr[i].r << " " << k.centr[i].g << " " << k.centr[i].b << " - #" << i << std::endl; } os << "\n : " << k.q_klaster << std::endl; os << " : " << k.k_pixcel << std::endl; return os; }
إخراج البيانات الأولية.
مثال الإخراج
مثال الإخراجوحدات البكسل الأولية:
255140 50 - رقم 0
100 70 1 - رقم 1
15020200 - رقم 2
251 141 51 - رقم 3
104 69 3 - رقم 4
153 22 210 - رقم 5
252 138 54 - رقم 6
101 74 4 - رقم 7
مراكز التجمعات العشوائية الأولية:
15020200 - # 0
104 69 3 - # 1
100 70 1 - # 2
عدد العناقيد: 3
عدد البكسل: 8
بداية الكتلة:
رقم التكرار 0
المسافة من بكسل 0 إلى المركز رقم 0: 218.918
المسافة من بكسل 0 إلى المركز رقم 1: 173.352
المسافة من بكسل 0 إلى المركز رقم 2: 176.992
الحد الأدنى لمسافة المركز # 1
إعادة حساب المركز # 1: 179.5 104.5 26.5
المسافة من بكسل 1 إلى المركز رقم 0: 211.189
المسافة من البكسل 1 إلى المركز رقم 1: 90.3369
المسافة من بكسل 1 إلى المركز رقم 2: 0
الحد الأدنى لمسافة المركز 2
إعادة حساب المركز # 2: 100 70 1
المسافة من بكسل 2 إلى المركز # 0: 0
المسافة من بكسل 2 إلى المركز رقم 1: 195.225
المسافة من بكسل 2 إلى المركز رقم 2: 211.189
الحد الأدنى لمسافة المركز # 0
عد المركز # 0: 150 20200
المسافة من البكسل 3 إلى المركز رقم 0: 216.894
المسافة من البكسل 3 إلى المركز رقم 1: 83.933
المسافة من بكسل 3 إلى المركز رقم 2: 174.19
الحد الأدنى لمسافة المركز # 1
عد المركز # 1: 215.25 122.75 38.75
المسافة من بكسل 4 إلى المركز رقم 0: 208.149
المسافة من بكسل 4 إلى المركز رقم 1: 128.622
المسافة من بيكسل 4 إلى المركز رقم 2: 4.58258
الحد الأدنى لمسافة المركز 2
عد المركز # 2: 102 69.5 2
المسافة من بكسل 5 إلى المركز رقم 0: 10.6301
المسافة من بكسل 5 إلى المركز رقم 1: 208.212
المسافة من بكسل 5 إلى المركز رقم 2: 219.366
الحد الأدنى لمسافة المركز # 0
إعادة حساب المركز # 0: 151.5 21205
المسافة من بكسل 6 إلى المركز رقم 0: 215.848
المسافة من بكسل 6 إلى المركز رقم 1: 42.6109
المسافة من بكسل 6 إلى المركز رقم 2: 172.905
الحد الأدنى لمسافة المركز # 1
إعادة حساب المركز # 1: 233.625 130.375 46.375
المسافة من بيكسل 7 إلى المركز رقم 0: 213.916
المسافة من بكسل 7 إلى المركز رقم 1: 150.21
المسافة من بيكسل 7 إلى المركز رقم 2: 5.02494
الحد الأدنى لمسافة المركز 2
إعادة حساب المركز # 2: 101.5 71.75 3
لنصنف وحدات البكسل:
المسافة من البكسل رقم 0 إلى المركز # 0: 221.129
المسافة من البكسل رقم 0 للمركز # 1: 23.7207
المسافة من البكسل رقم 0 للمركز رقم 2: 174.44
Pixel # 0 الأقرب إلى المركز رقم 1
المسافة من البكسل رقم 1 للمركز # 0: 216.031
المسافة من البكسل رقم 1 للمركز رقم 1: 153.492
المسافة من البكسل رقم 1 للمركز رقم 2: 3.05164
Pixel # 1 الأقرب إلى المركز رقم 2
المسافة من البكسل رقم 2 للمركز # 0: 5.31507
المسافة من البكسل رقم 2 للمركز رقم 1: 206.825
المسافة من البكسل رقم 2 للمركز رقم 2: 209.378
Pixel # 2 الأقرب إلى المركز رقم 0
المسافة من البكسل رقم 3 للمركز # 0: 219.126
المسافة من البكسل رقم 3 للمركز رقم 1: 20.8847
المسافة من البكسل رقم 3 للمركز رقم 2: 171.609
Pixel # 3 الأقرب إلى المركز رقم 1
المسافة من البكسل رقم 4 للمركز # 0: 212.989
المسافة من البكسل رقم 4 للمركز رقم 1: 149.836
المسافة من البكسل رقم 4 للمركز رقم 2: 3.71652
Pixel # 4 الأقرب إلى المركز رقم 2
المسافة من البكسل رقم 5 للمركز # 0: 5.31507
المسافة من البكسل رقم 5 للمركز # 1: 212.176
المسافة من البكسل رقم 5 للمركز رقم 2: 219.035
Pixel # 5 الأقرب إلى المركز رقم 0
المسافة من البكسل رقم 6 للمركز # 0: 215.848
المسافة من البكسل رقم 6 إلى المركز رقم 1: 21.3054
المسافة من البكسل رقم 6 للمركز # 2: 172.164
Pixel # 6 الأقرب إلى المركز رقم 1
المسافة من البكسل رقم 7 إلى المركز # 0: 213.916
المسافة من البكسل رقم 7 إلى المركز رقم 1: 150.21
المسافة من البكسل رقم 7 للمركز رقم 2: 2.51247
Pixel # 7 الأقرب إلى المركز رقم 2
مجموعة من وحدات البكسل والمراكز المطابقة:
1 2 0 1 2 0 1 2
نتيجة التجميع:
المجموعة رقم 0
150 20200
153 22 210
المجموعة رقم 1
255140 50
251 141 51
252 138 54
المجموعة رقم 2
100 70 1
104 69 3
101 74 4
المراكز الجديدة:
151.5 21 205 - # 0
233.625 130.375 46.375 - # 1
101.5 71.75 3 - # 2
التكرار رقم 1
المسافة من البكسل 0 إلى المركز # 0: 221.129
المسافة من بكسل 0 إلى المركز رقم 1: 23.7207
المسافة من بكسل 0 إلى المركز رقم 2: 174.44
الحد الأدنى لمسافة المركز # 1
عد المركز # 1: 244.313 135.188 48.1875
المسافة من البكسل 1 إلى المركز رقم 0: 216.031
المسافة من بكسل 1 إلى المركز رقم 1: 165.234
المسافة من بكسل 1 إلى المركز رقم 2: 3.05164
الحد الأدنى لمسافة المركز 2
إعادة حساب المركز # 2: 100.75 70.875 2
المسافة من بكسل 2 إلى المركز رقم 0: 5.31507
المسافة من بكسل 2 إلى المركز رقم 1: 212.627
المسافة من بكسل 2 إلى المركز رقم 2: 210.28
الحد الأدنى لمسافة المركز # 0
إعادة حساب المركز # 0: 150.75 20.5 202.5
المسافة من بكسل 3 إلى المركز رقم 0: 217.997
المسافة من البكسل 3 إلى المركز رقم 1: 9.29613
المسافة من بكسل 3 إلى المركز رقم 2: 172.898
الحد الأدنى لمسافة المركز # 1
عد المركز # 1: 247.656 138.094 49.5938
المسافة من بيكسل 4 إلى المركز رقم 0: 210.566
المسافة من البكسل 4 إلى المركز رقم 1: 166.078
المسافة من بيكسل 4 إلى المركز رقم 2: 3.88306
الحد الأدنى لمسافة المركز 2
عد المركز # 2: 102.375 69.9375 2.5
المسافة من بكسل 5 إلى المركز رقم 0: 7.97261
المسافة من بكسل 5 إلى المركز رقم 1: 219.471
المسافة من بكسل 5 إلى المركز رقم 2: 218.9
الحد الأدنى لمسافة المركز # 0
عد المركز # 0: 151.875 21.25 206.25
المسافة من بكسل 6 إلى المركز رقم 0: 216.415
المسافة من بكسل 6 إلى المركز رقم 1: 6.18805
المسافة من بكسل 6 إلى المركز رقم 2: 172.257
الحد الأدنى لمسافة المركز # 1
إعادة حساب المركز # 1: 249.828 138.047 51.7969
المسافة من بكسل 7 إلى المركز رقم 0: 215.118
المسافة من بيكسل 7 إلى المركز رقم 1: 168.927
المسافة من بكسل 7 إلى المركز رقم 2: 4.54363
الحد الأدنى لمسافة المركز 2
إعادة حساب المركز # 2: 101.688 71.9688 3.25
لنصنف وحدات البكسل:
المسافة من البكسل رقم 0 إلى المركز # 0: 221.699
المسافة من البكسل رقم 0 للمركز رقم 1: 5.81307
المسافة من البكسل رقم 0 للمركز رقم 2: 174.122
Pixel # 0 الأقرب إلى المركز رقم 1
المسافة من البكسل رقم 1 للمركز # 0: 217.244
المسافة من البكسل رقم 1 للمركز رقم 1: 172.218
المسافة من البكسل رقم 1 للمركز رقم 2: 3.43309
Pixel # 1 الأقرب إلى المركز رقم 2
المسافة من البكسل رقم 2 للمركز # 0: 6.64384
المسافة من البكسل رقم 2 للمركز رقم 1: 214.161
المسافة من البكسل رقم 2 للمركز رقم 2: 209.154
Pixel # 2 الأقرب إلى المركز رقم 0
المسافة من البكسل رقم 3 للمركز # 0: 219.701
المسافة من البكسل # 3 إلى المركز رقم 1: 3.27555
المسافة من البكسل رقم 3 للمركز رقم 2: 171.288
Pixel # 3 الأقرب إلى المركز رقم 1
المسافة من البكسل رقم 4 إلى المركز # 0: 214.202
المسافة من البكسل رقم 4 للمركز رقم 1: 168.566
المسافة من البكسل رقم 4 للمركز رقم 2: 3.77142
Pixel # 4 الأقرب إلى المركز رقم 2
المسافة من البكسل رقم 5 للمركز # 0: 3.9863
المسافة من البكسل رقم 5 للمركز # 1: 218.794
المسافة من البكسل رقم 5 للمركز رقم 2: 218.805
Pixel # 5 الأقرب إلى المركز رقم 0
المسافة من البكسل رقم 6 للمركز # 0: 216.415
المسافة من البكسل رقم 6 إلى المركز رقم 1: 3.09403
المسافة من البكسل رقم 6 إلى المركز رقم 2: 171.842
Pixel # 6 الأقرب إلى المركز رقم 1
المسافة من البكسل رقم 7 إلى المركز # 0: 215.118
المسافة من البكسل رقم 7 إلى المركز رقم 1: 168.927
المسافة من البكسل رقم 7 إلى المركز رقم 2: 2.27181
Pixel # 7 الأقرب إلى المركز رقم 2
مجموعة من وحدات البكسل والمراكز المطابقة:
1 2 0 1 2 0 1 2
نتيجة التجميع:
المجموعة رقم 0
150 20200
153 22 210
المجموعة رقم 1
255140 50
251 141 51
252 138 54
المجموعة رقم 2
100 70 1
104 69 3
101 74 4
المراكز الجديدة:
151.875 21.25 206.25 - # 0
249.828 138.047 51.7969 - # 1
101.688 71.9688 3.25 - # 2
نهاية التكتل.
تم التخطيط لهذا المثال مسبقًا ، ويتم تحديد وحدات البكسل خصيصًا للتوضيح. يكفي تكراران للبرنامج لتجميع البيانات في ثلاث مجموعات. بالنظر إلى مراكز التكررين الماضيين ، يمكنك أن ترى أنها بقيت في مكانها عمليًا.
أكثر إثارة للاهتمام هي حالات بكسل تم إنشاؤها بشكل عشوائي. بعد أن ولدت 50 نقطة يجب تقسيمها إلى 10 مجموعات ، حصلت على 5 تكرارات. بعد أن ولدت 50 نقطة يجب تقسيمها إلى 3 مجموعات ، حصلت على كل 100 تكرار كحد أقصى مسموح به. قد تلاحظ أنه كلما زاد عدد المجموعات ، كان من الأسهل على البرنامج العثور على وحدات البكسل الأكثر تشابهًا ودمجها في مجموعات أصغر ، والعكس صحيح - إذا كان هناك عدد قليل من المجموعات وهناك العديد من النقاط ، غالبًا ما تنتهي الخوارزمية فقط عندما يتم تجاوز الحد الأقصى لعدد التكرارات ، حيث تقفز بعض وحدات البكسل باستمرار من عنقود لآخر. ومع ذلك ، لا يزال الجزء الأكبر محددًا في مجموعاته بالكامل.
حسنًا ، الآن دعنا نتحقق من نتيجة التجميع. بأخذ نتيجة بعض المجموعات من مثال 50 نقطة لكل 10 مجموعات ، قمت بقيادة نتيجة هذه البيانات إلى Illustrator وهذا ما حدث:

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

وهذه هي المجموعة 8 ، ولكن في نسخة أصغر ، تكون النتيجة متشابهة:

يمكن الاطلاع على النسخة الكاملة من البرنامج على
GitHub .