منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب
درس -- تعلم إضافة الضبابية للصور - بواسطة فلتر ال Blur - مع مثال توضيحي - نسخة قابلة للطباعة

+- منتدى فيجوال بيسك لكل العرب | منتدى المبرمجين العرب (http://vb4arb.com/vb)
+-- قسم : قسم لغة الفيجوال بيسك VB.NET (http://vb4arb.com/vb/forumdisplay.php?fid=182)
+--- قسم : قسم مقالات VB.NET (http://vb4arb.com/vb/forumdisplay.php?fid=184)
+--- الموضوع : درس -- تعلم إضافة الضبابية للصور - بواسطة فلتر ال Blur - مع مثال توضيحي (/showthread.php?tid=5015)



درس -- تعلم إضافة الضبابية للصور - بواسطة فلتر ال Blur - مع مثال توضيحي - RaggiTech - 03-10-12

كاتب الموضوع : المبرمج الطموح vb6


<< بسم الله الرحمن الرحيم >>

السلام عليكم إخواني هذا أول درس لي بالدوت نت أتمنى أن يكون مفهوما و واضحا

أما بعد , كل من يعمل على ال PhotoShop يعرف فلتر ال Blur أو ما يعرف بالضبابية و من الفلاتر المهمة في مجال تصميم الصور و تعديلها

اليوم بإذن الله سوف نتعلم سويا كيف يمكن عمل هذا الفلتر باستخدام Visual Basic . Net
نبدأ باسم الله الرحمن الرحيم درسنا :

- إن فكرة الفلتر بسيطة جدا فهي تعتمد على أخذ المتوسط الحسابي لكل لون في كل Pixel مع ثمانٍ من مجاوراتها و إعادة قيمته لل Pixel مرة أخرى .

لنستفهم أنا و إياكم عن كيفية تنفيذ الفلتر Filter :

- نبدأ مشروع Windows Forms Application و نضع على الفورم الأداوت التالية باسمائها الافتراضية :

1 - ProgressBar للإستدلال على تقدم عملية الفلترة .
2 - Button للبدء بالفلترة .
3 - PictureBox تحوي على الصورة المراد تنفيذ الفلتر عليها .


- بما أننا سوف نتعامل مع ال Pixels لذلك لابد من أن يدور ذهننا للدالتين GetPixel و SetPixel و هما أساس هذا الكود .

- في الكود سنلاحظ جملة تكرار For لأخذ كل إحداثي في الصورة على المحورين X , Y و من ثم ننسبهما إلى إحداثيات الدالة GetPixel و إلحاقها بالوسيط R أو G أو B و أخذ نسبة كل من الألوان ( أحمر , أخضر , أزرق ) من كل Pixel و مع جمعها ( + ) مع نسبة اللون نفسه من ال Pixels المجاورة لهذه ال Pixel مقسمة على العدد الكلي ( 9 )

( أعلم أن هذه الخطوة تدوخ لكن تابع الدرس لأن هذه الفكرة مشروحة في الكود بالتفصيل )

- من ثم ننسب القيم الثلاثة المعدلة إلى ثلاث متغيرات Red , Green , Blue و بعدها نستخدم الدالة SetPixel لإرجاع القيم الجديدة لنسب الألوان إلى تلك ال Pixel .

- و من ثم تتكرر العملية لتشمل كل Pixels الصورة بلا استثناء .

الآن سأعطيكم الكود مشروحاً سطرا بسطر لتثبيت الفكرة أكثر :

كود :
[SIZE=3]' هذا حدث الضغط على الزر
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
[/SIZE]
[SIZE=3]' إرجاع القيمة الصفرية لشريط التقدم
ProgressBar1.Value = 0[/SIZE]

[SIZE=3]'تعريف متغير جديد على أنه صورة مع إعطائه الصورة الموجودة في مربع الصورة
Dim AHED As New Bitmap(PictureBox1.Image)[/SIZE]

[SIZE=3]'ننسب صورة مربع الصورة إلى المتغير حيث لا يشعر المستخدم بهذا الخطوة
'لكن الفائدة منها أنه عندما يتم تعديل بقية الكود يرى المستخدم التغيير أمامه
PictureBox1.Image = AHED[/SIZE]

[SIZE=3]'تعريف متغيرات لنسب الألوان
Dim Red, Green, Blue As Integer[/SIZE]

[SIZE=3]'تعريف متغيرات للإحداثيات
Dim I, J As Integer[/SIZE]

[SIZE=3]'نجعل القيمة العظمى لريط التقدم مساوية ارتفاع الصورة الموجودة في مربع الصورة
ProgressBar1.Maximum = Val(PictureBox1.Image.Height)[/SIZE]

[SIZE=3]'عبارة لاختصار الكود نظرا للاستخدام الكبير للمتغير فيصبح ليس بحاجة لكتابة المتغير
'و إنما مباشرة النقطة فيعرف الجهاز أن الخاصية بعد النقطة عائدة لمتغير الصورة
With AHED[/SIZE]

[SIZE=3]'جعل قيمة الإحداثي الصادي من الواحد إلى قبل نهاية الصورة بنقطتين لأنه يمثل طرف هذه الصورة
'لاحظ أنه في الكود لم نكتب اسم المتغير بل مباشرة استدعينا خاصيته و ذلك بفضل العبارة السابقة
For I = 1 To .Height - 2[/SIZE]

[SIZE=3]'أما هذا فللإحداثي السيني
For J = 1 To .Width - 2[/SIZE]

[SIZE=3]'نجعل قيمة متغير اللون الأحمر مساوية قيم اللون الأحمر ل 8 نقاط حول النقطة المدروسة
'و تقسيمها على 9 عدد النقاط للمتوسط الحسابي
Red = CInt((CInt(.GetPixel(J - 1, I - 1).R) + CInt(.GetPixel(J - 1, I).R) + CInt(.GetPixel(J - 1, I + 1).R) + _
(CInt(.GetPixel(J, I - 1).R)) + CInt(.GetPixel(J, I).R) + CInt(.GetPixel(J, I + 1).R) + _
CInt(.GetPixel(J + 1, I - 1).R) + CInt(.GetPixel(J + 1, I).R) + CInt(.GetPixel(J + 1, I + 1).R)) / 9)[/SIZE]

[SIZE=3]'هذا كود المتوسط الحسابي للون الأخضر
Green = CInt((CInt(.GetPixel(J - 1, I - 1).G) + CInt(.GetPixel(J - 1, I).G) + CInt(.GetPixel(J - 1, I + 1).G) + _
(CInt(.GetPixel(J, I - 1).G)) + CInt(.GetPixel(J, I).G) + CInt(.GetPixel(J, I + 1).G) + _
CInt(.GetPixel(J + 1, I - 1).G) + CInt(.GetPixel(J + 1, I).G) + CInt(.GetPixel(J + 1, I + 1).G)) / 9)[/SIZE]

[SIZE=3]'أما هذا فللون الأزرق
Blue = CInt((CInt(.GetPixel(J - 1, I - 1).B) + CInt(.GetPixel(J - 1, I).B) + CInt(.GetPixel(J - 1, I + 1).B) + _
(CInt(.GetPixel(J, I - 1).B)) + CInt(.GetPixel(J, I).B) + CInt(.GetPixel(J, I + 1).B) + _
CInt(.GetPixel(J + 1, I - 1).B) + CInt(.GetPixel(J + 1, I).B) + CInt(.GetPixel(J + 1, I + 1).B)) / 9)[/SIZE]

[SIZE=3]'إرجاع قيم الألوان مرة أخرى للنقطة بعد التعديل
AHED.SetPixel(J, I, Color.FromArgb(Red, Green, Blue))[/SIZE]

[SIZE=3]'إنتهاء عبارة التكرار الخاصة بالمتغير السيني
Next[/SIZE]

[SIZE=3]'تحديث الصورة
PictureBox1.Refresh()[/SIZE]

[SIZE=3]'زيادة خطوة في شريط التقدم
ProgressBar1.Value = ProgressBar1.Value + 1[/SIZE]

[SIZE=3]'إنتهاء عبارة التكرار الخاصة بالمتغير الصادي
Next[/SIZE]

[SIZE=3]'إنتهاء عبارة الاختصار
End With[/SIZE]

[SIZE=3]'تحديث الصورة
PictureBox1.Refresh()[/SIZE]

[SIZE=3]'إنتهاء الحدث
End Sub[/SIZE]

ملاحظات :

- سنلاحظ أن تنفيذ الكود بطيء ذلك بسبب حلقتي التكرار و العمليات الحسابية في كل منهما لكن لجعل العملية أسرع يمكننا أن نننقل السطر PictureBox1.Image = AHED
إلى نهاية الكود قبل جملة End Sub و بذلك لن يشاهد المستخدم التغيير إلا بعد إنتهاء العملية لأن الصورة تبقى محفوظة في الذاكرة لحين الانتهاء من أداء الفلتر .


- لقد قمت بإرفاق مثال للتوضيح أكثر .

<< Blur Project For vb4arab.com.zip >>

- الموضوع و المثال و الشرح من كتابتي بالكامل أتمنى أن يعجبكم .

تحياتي للجميع .
المبرمج الطموح vb6