30-06-17, 11:33 AM
(آخر تعديل لهذه المشاركة : 30-06-17, 11:45 AM {2} بواسطة silverlight.)
مقدمة:
هذا الموضوع سوف يوضح كيفية المقارنة بين صورتين و الحصول علي صورة ثالثة توضح الفارق بين الصورتين
عامل السرعة في المقارنة بين الصور أمر هام جدا و أغلب الموضوعات علي النت لم تضع في اعتبارها سرعة تنفيذ الكود
أيضا أغلب الموضوعات علي النت عتمدت علي استخدام Bitmap.GetPixel وتستخدمها لكي تقارن بين الألوان في الصورتين و هذا بالطبع يؤدي الي بطء في الاداء و غالبا لا يعطي نتائج مرضية للمبرمج
لضمان عامل السرعة في تنفيذ الكود سوف استخدم Bitmap.LockBits و Marshal Class للحصول علي مصفوفة Byte الحاصة بألوان الصورة
يجب الوضع في الاعتبار لو ان الصور المستخدمة في المقارنة ابعادها مختلفة فهنا تصبح المقارنة بلا جدوي
قد يتساءل البعض منكم و ما فائدة مثل هذا الموضوع
وإجابة هذا السؤال تتلخص في التالي
الفكرة المستخدمة هنا مفيدة جدا في مقارنة التغييرات في الصور و هي تستخدم غالبا في كاميرات المراقبة و أشياء أخري من هذا القبيل
وهناك شركات كثيرة عملها مبني علي الفكرة التي سوف نناقشها هنا لذلك قليلا ما تجد أحد يرد علي اسئلة مشابهة لأن الأمر و ببساطة شديدة عبارة عن بيزنس
وغالبا لن تجد أحد من المبرمجين يكشف أسرار عمله لمبرمج أخر
عموما كيفية الاستفادة من الكود متروك لمخيلة القارئ و غالبا ستجدون له استخدامات كثيرة
الفكرة:
المراحل التالية توضح خطوات العمل
المرحلة الأولي:
يكون لديك صورتان متشابهتان لكن بينهما فارق بسيط
و هنا انا حصلت علي الصور التي سأستخدمها في المقارنة من موضوع مشابه و لكنه مكتوب بلغة Ruby علي ما أتذكر
وحتي الموضوع الذي أخذت منه الصور يعتمد في المقارنة بين الصور علي فكرة مقارنة الألوان الموجودة في الصور باستخدام Bitmap.GetPixel
المرحلة الثانية:
بعد الحصول علي الصور نقوم بالحصول علي مصفوفة الألوان الخاصة بكل صورة
وبمجرد أن تفعل هذا فأنت تقريبا تكون إنتهيت من نصف العمل تقريبا
المرحلة الثالثة:
بعد الحصول علي مصفوفة الألوان الخاصة بكل صورة نقوم بتعريف متغير عبارة عن مصفوفة ثالثة تكون السعة الخاصة بها مساوية لأي من المصفوفتان الخاصة بالصور
هذه المصفوفة ستعمل بمثابة مصفوفة الألوان للصورة التي تبين الفارق بين الصورتان و لنطلق عليها مصفوفة الفروقات
المرحلة الرابعة:
بعد ذلك نقوم بعمل حلقة تكرارية و نقارن بين الألوان أو بين ARGB الخاصة بكل بكسل في مصفوفات الصور
فإن كانت الألوان مماثلة نقوم بملئ المصفوفة الثالثة وهي مصفوفة الفروقات بلون بديل وليكن اللون Magenta مثلا
و ان كانت الألوان في مصفوفات الصور مختلفة نقوم بإضافة اللون المختلف الي المصفوفة الثالثة وهي مصفوفة الفروقات
أعلم جيدا ان المرحلة هذه ربما لا تكون غير واضحة للبعض منكم لكني أثق تماما انه عند تنفبذها برمجيا ستتضح لكم
عند الانتهاء من هذه المرحلة تكون فعليا انتهيت بنسبة 90 في المائة من العمل
المرحلة الخامسة و الأخيرة:
ناخذ مصفوفة الفروقات و نحولها الي صورة
الكود:
الكود التالي يوضح الفكرة مع شرح تفصيلي
حاول تعكس السطران التاليان من الكود
بحيث تجعلهما هكذا و شاهد ما سيحدث
أتمني إن الكود يكون مفيدا للبعض منكم
تقبلوا تحياتي
هذا الموضوع سوف يوضح كيفية المقارنة بين صورتين و الحصول علي صورة ثالثة توضح الفارق بين الصورتين
عامل السرعة في المقارنة بين الصور أمر هام جدا و أغلب الموضوعات علي النت لم تضع في اعتبارها سرعة تنفيذ الكود
أيضا أغلب الموضوعات علي النت عتمدت علي استخدام Bitmap.GetPixel وتستخدمها لكي تقارن بين الألوان في الصورتين و هذا بالطبع يؤدي الي بطء في الاداء و غالبا لا يعطي نتائج مرضية للمبرمج
لضمان عامل السرعة في تنفيذ الكود سوف استخدم Bitmap.LockBits و Marshal Class للحصول علي مصفوفة Byte الحاصة بألوان الصورة
يجب الوضع في الاعتبار لو ان الصور المستخدمة في المقارنة ابعادها مختلفة فهنا تصبح المقارنة بلا جدوي
قد يتساءل البعض منكم و ما فائدة مثل هذا الموضوع
وإجابة هذا السؤال تتلخص في التالي
الفكرة المستخدمة هنا مفيدة جدا في مقارنة التغييرات في الصور و هي تستخدم غالبا في كاميرات المراقبة و أشياء أخري من هذا القبيل
وهناك شركات كثيرة عملها مبني علي الفكرة التي سوف نناقشها هنا لذلك قليلا ما تجد أحد يرد علي اسئلة مشابهة لأن الأمر و ببساطة شديدة عبارة عن بيزنس
وغالبا لن تجد أحد من المبرمجين يكشف أسرار عمله لمبرمج أخر
عموما كيفية الاستفادة من الكود متروك لمخيلة القارئ و غالبا ستجدون له استخدامات كثيرة
الفكرة:
المراحل التالية توضح خطوات العمل
المرحلة الأولي:
يكون لديك صورتان متشابهتان لكن بينهما فارق بسيط
و هنا انا حصلت علي الصور التي سأستخدمها في المقارنة من موضوع مشابه و لكنه مكتوب بلغة Ruby علي ما أتذكر
وحتي الموضوع الذي أخذت منه الصور يعتمد في المقارنة بين الصور علي فكرة مقارنة الألوان الموجودة في الصور باستخدام Bitmap.GetPixel
المرحلة الثانية:
بعد الحصول علي الصور نقوم بالحصول علي مصفوفة الألوان الخاصة بكل صورة
وبمجرد أن تفعل هذا فأنت تقريبا تكون إنتهيت من نصف العمل تقريبا
المرحلة الثالثة:
بعد الحصول علي مصفوفة الألوان الخاصة بكل صورة نقوم بتعريف متغير عبارة عن مصفوفة ثالثة تكون السعة الخاصة بها مساوية لأي من المصفوفتان الخاصة بالصور
هذه المصفوفة ستعمل بمثابة مصفوفة الألوان للصورة التي تبين الفارق بين الصورتان و لنطلق عليها مصفوفة الفروقات
المرحلة الرابعة:
بعد ذلك نقوم بعمل حلقة تكرارية و نقارن بين الألوان أو بين ARGB الخاصة بكل بكسل في مصفوفات الصور
فإن كانت الألوان مماثلة نقوم بملئ المصفوفة الثالثة وهي مصفوفة الفروقات بلون بديل وليكن اللون Magenta مثلا
و ان كانت الألوان في مصفوفات الصور مختلفة نقوم بإضافة اللون المختلف الي المصفوفة الثالثة وهي مصفوفة الفروقات
أعلم جيدا ان المرحلة هذه ربما لا تكون غير واضحة للبعض منكم لكني أثق تماما انه عند تنفبذها برمجيا ستتضح لكم
عند الانتهاء من هذه المرحلة تكون فعليا انتهيت بنسبة 90 في المائة من العمل
المرحلة الخامسة و الأخيرة:
ناخذ مصفوفة الفروقات و نحولها الي صورة
الكود:
الكود التالي يوضح الفكرة مع شرح تفصيلي
PHP كود :
' المرحلة الأولي
' تعريف الصورتان المراد المقارنة بينهما و الحصول منهما علي صورة توضح الفارق بين الصورتان
Dim sourceBitmap As Bitmap = PictureBox2.Image
Dim destBitmap As Bitmap = PictureBox1.Image
' المرحلة الثانية
' الحصول علي مصفوفة البايت الخاصة بكل صورة أعلاه
' الحصول علي مصفوفة الأوان الخاصة بالصورة الأولي و هي عبارة عن مصفوفة بايت
Dim sourceBitmapData As Imaging.BitmapData = sourceBitmap.LockBits(New Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
Dim sourceBytes As Byte() = New Byte(sourceBitmapData.Stride * sourceBitmapData.Height - 1) {}
Runtime.InteropServices.Marshal.Copy(sourceBitmapData.Scan0, SourceBytes, 0, SourceBytes.Length)
sourceBitmap.UnlockBits(sourceBitmapData)
' الحصول علي مصفوفة الأوان الخاصة بالصورة الثانية و هي أيضا عبارة عن مصفوفة بايت
Dim destBitmapData As Imaging.BitmapData = destBitmap.LockBits(New Rectangle(0, 0, destBitmap.Width, destBitmap.Height), Imaging.ImageLockMode.ReadOnly, Imaging.PixelFormat.Format32bppArgb)
Dim destBytes As Byte() = New Byte(destBitmapData.Stride * destBitmapData.Height - 1) {}
Runtime.InteropServices.Marshal.Copy(destBitmapData.Scan0, destBytes, 0, destBytes.Length)
destBitmap.UnlockBits(destBitmapData)
' المرحلة الثالثة
' تعريف متغير يعبر عن مصفوفة الفروقات في الألوان
' وهذا المتغير عبارة عن مصفوفة بايت و السعة الخاصة بهذه المصفوفة تكون بنفس سعة اي من مصفوفات الصور أعلاه
Dim diffBytes As Byte() = New Byte(sourceBytes.Length - 1) {}
' المرحلة الرابعة
' بناء الحلقة التكرارية التي نقارن فيها بين الألوان في الصور
' ملحوظة هامة
' الألوان في الصور يتم تخزينها في صورة
' RGBA: RED Green Blue Alpha
Dim i As Integer = 0
While i < sourceBytes.Length - 1
' نحصل علي اللون من الصورة الأولي و نقارنه باللون في الصورة الثانية
' يجب أن لا ننسي أن الألوان في الصور علي هيئة
' RGBA: RED Green Blue Alpha
If (sourceBytes(i) = destBytes(i)) AndAlso (sourceBytes(i + 1) = destBytes(i + 1)) AndAlso (sourceBytes(i + 2) = destBytes(i + 2)) AndAlso (sourceBytes(i + 3) = destBytes(i + 3)) Then
' تعريف لون بديل سنستخدمه لنملأ به مصفوفة الفروقات في حالة تساوي الأوان في الصورتان
Dim clr As Color = Color.Magenta
' في حالة تساوي الوان البكسل في الصورتان نعبئ مصفوفة الفروقات بأي لون نحدده
' وهنا أنا اخترت اللون الماجنتا كلون بديل
diffBytes(i) = CByte(clr.R)
diffBytes(i + 1) = CByte(clr.G)
diffBytes(i + 2) = CByte(clr.B)
diffBytes(i + 3) = CByte(clr.A)
Else
' في حالة اختلاف الالون بين الصورتان
' نقوم بتعبئة مصفوفة الفروقات باللون الموجود في الصورة الأصلية
diffBytes(i) = sourceBytes(i)
diffBytes(i + 1) = sourceBytes(i + 1)
diffBytes(i + 2) = sourceBytes(i + 2)
diffBytes(i + 3) = sourceBytes(i + 3)
End If
i += 4
End While
' المرحلة الخامسة و الأخيرة
' تحويل مصفوفة الفروقات الي صورة
' وهي تكون صورة نبنيها بنفس ابعاد اي من الصورتان التي نقارن بينهما
Dim diffBitmp As New Bitmap(sourceBitmap.Width, sourceBitmap.Height)
Dim data As Imaging.BitmapData = diffBitmp.LockBits(New Rectangle(0, 0, diffBitmp.Width, diffBitmp.Height), Imaging.ImageLockMode.WriteOnly, Imaging.PixelFormat.Format32bppArgb)
' نكتب مصفوفة الأوان باستخدام المارشال كلاس
Runtime.InteropServices.Marshal.Copy(diffBytes, 0, data.Scan0, diffBytes.Length)
diffBitmp.UnlockBits(data)
' أخيرا نقوم بعرض صورة الفروقات في بكتشر بوكس
Me.PictureBox3.Image = diffBitmp
حاول تعكس السطران التاليان من الكود
PHP كود :
Dim sourceBitmap As Bitmap = PictureBox2.Image
Dim destBitmap As Bitmap = PictureBox1.Image
PHP كود :
Dim sourceBitmap As Bitmap = PictureBox1.Image
Dim destBitmap As Bitmap = PictureBox2.Image
أتمني إن الكود يكون مفيدا للبعض منكم
تقبلوا تحياتي