الدرس السادس

Lesson_6 slides

: تغيير فضاءات الالوان

: الهدف

سنتعلم هنا كيف نحول الصور من فضاء لوني لاخر

بالاضافة لذلك سننشئ تطبيقاً لاشتقاق جسم ملون بفيديو

وسنتعلم التوابع التالية

cv2.cvtColor() , cv2.inRange()

: تغيير الفضاء اللوني

هناك اكثر من 150 طريقة لتغيير الفضاءات اللونية ب

OpenCV

ولكننا سننظر فقط الى اثنين هما الاكثر استخداماً وللتغير اللوني سنستخدم التابع التالي:

cv2.cvtColor(input_image, flag)

حيث قيمة العلم تدل على نوع التغيير , مثلا من

$$ BGR ==> GRAY $$

نستخدم:

cv2.COLOR_BGR2GRAY() , cv2.COLOR_BGR2HSV()

والثاني طبعاً للتحويل من

$$ BGR ==> HSV $$

: ولمعرفة كل الاعلام الاخرى بامكانك تشغيل الكود التالي

In [1]:
import cv2
flags = [i for i in dir(cv2) if i.startswith('COLOR_')]
for x in flags:
    print x
COLOR_BAYER_BG2BGR
COLOR_BAYER_BG2BGR_VNG
COLOR_BAYER_BG2GRAY
COLOR_BAYER_BG2RGB
COLOR_BAYER_BG2RGB_VNG
COLOR_BAYER_GB2BGR
COLOR_BAYER_GB2BGR_VNG
COLOR_BAYER_GB2GRAY
COLOR_BAYER_GB2RGB
COLOR_BAYER_GB2RGB_VNG
COLOR_BAYER_GR2BGR
COLOR_BAYER_GR2BGR_VNG
COLOR_BAYER_GR2GRAY
COLOR_BAYER_GR2RGB
COLOR_BAYER_GR2RGB_VNG
COLOR_BAYER_RG2BGR
COLOR_BAYER_RG2BGR_VNG
COLOR_BAYER_RG2GRAY
COLOR_BAYER_RG2RGB
COLOR_BAYER_RG2RGB_VNG
COLOR_BGR2BGR555
COLOR_BGR2BGR565
COLOR_BGR2BGRA
COLOR_BGR2GRAY
COLOR_BGR2HLS
COLOR_BGR2HLS_FULL
COLOR_BGR2HSV
COLOR_BGR2HSV_FULL
COLOR_BGR2LAB
COLOR_BGR2LUV
COLOR_BGR2RGB
COLOR_BGR2RGBA
COLOR_BGR2XYZ
COLOR_BGR2YCR_CB
COLOR_BGR2YUV
COLOR_BGR2YUV_I420
COLOR_BGR2YUV_IYUV
COLOR_BGR2YUV_YV12
COLOR_BGR5552BGR
COLOR_BGR5552BGRA
COLOR_BGR5552GRAY
COLOR_BGR5552RGB
COLOR_BGR5552RGBA
COLOR_BGR5652BGR
COLOR_BGR5652BGRA
COLOR_BGR5652GRAY
COLOR_BGR5652RGB
COLOR_BGR5652RGBA
COLOR_BGRA2BGR
COLOR_BGRA2BGR555
COLOR_BGRA2BGR565
COLOR_BGRA2GRAY
COLOR_BGRA2RGB
COLOR_BGRA2RGBA
COLOR_BGRA2YUV_I420
COLOR_BGRA2YUV_IYUV
COLOR_BGRA2YUV_YV12
COLOR_COLORCVT_MAX
COLOR_GRAY2BGR
COLOR_GRAY2BGR555
COLOR_GRAY2BGR565
COLOR_GRAY2BGRA
COLOR_GRAY2RGB
COLOR_GRAY2RGBA
COLOR_HLS2BGR
COLOR_HLS2BGR_FULL
COLOR_HLS2RGB
COLOR_HLS2RGB_FULL
COLOR_HSV2BGR
COLOR_HSV2BGR_FULL
COLOR_HSV2RGB
COLOR_HSV2RGB_FULL
COLOR_LAB2BGR
COLOR_LAB2LBGR
COLOR_LAB2LRGB
COLOR_LAB2RGB
COLOR_LBGR2LAB
COLOR_LBGR2LUV
COLOR_LRGB2LAB
COLOR_LRGB2LUV
COLOR_LUV2BGR
COLOR_LUV2LBGR
COLOR_LUV2LRGB
COLOR_LUV2RGB
COLOR_M_RGBA2RGBA
COLOR_RGB2BGR
COLOR_RGB2BGR555
COLOR_RGB2BGR565
COLOR_RGB2BGRA
COLOR_RGB2GRAY
COLOR_RGB2HLS
COLOR_RGB2HLS_FULL
COLOR_RGB2HSV
COLOR_RGB2HSV_FULL
COLOR_RGB2LAB
COLOR_RGB2LUV
COLOR_RGB2RGBA
COLOR_RGB2XYZ
COLOR_RGB2YCR_CB
COLOR_RGB2YUV
COLOR_RGB2YUV_I420
COLOR_RGB2YUV_IYUV
COLOR_RGB2YUV_YV12
COLOR_RGBA2BGR
COLOR_RGBA2BGR555
COLOR_RGBA2BGR565
COLOR_RGBA2BGRA
COLOR_RGBA2GRAY
COLOR_RGBA2M_RGBA
COLOR_RGBA2RGB
COLOR_RGBA2YUV_I420
COLOR_RGBA2YUV_IYUV
COLOR_RGBA2YUV_YV12
COLOR_XYZ2BGR
COLOR_XYZ2RGB
COLOR_YCR_CB2BGR
COLOR_YCR_CB2RGB
COLOR_YUV2BGR
COLOR_YUV2BGRA_I420
COLOR_YUV2BGRA_IYUV
COLOR_YUV2BGRA_NV12
COLOR_YUV2BGRA_NV21
COLOR_YUV2BGRA_UYNV
COLOR_YUV2BGRA_UYVY
COLOR_YUV2BGRA_Y422
COLOR_YUV2BGRA_YUNV
COLOR_YUV2BGRA_YUY2
COLOR_YUV2BGRA_YUYV
COLOR_YUV2BGRA_YV12
COLOR_YUV2BGRA_YVYU
COLOR_YUV2BGR_I420
COLOR_YUV2BGR_IYUV
COLOR_YUV2BGR_NV12
COLOR_YUV2BGR_NV21
COLOR_YUV2BGR_UYNV
COLOR_YUV2BGR_UYVY
COLOR_YUV2BGR_Y422
COLOR_YUV2BGR_YUNV
COLOR_YUV2BGR_YUY2
COLOR_YUV2BGR_YUYV
COLOR_YUV2BGR_YV12
COLOR_YUV2BGR_YVYU
COLOR_YUV2GRAY_420
COLOR_YUV2GRAY_I420
COLOR_YUV2GRAY_IYUV
COLOR_YUV2GRAY_NV12
COLOR_YUV2GRAY_NV21
COLOR_YUV2GRAY_UYNV
COLOR_YUV2GRAY_UYVY
COLOR_YUV2GRAY_Y422
COLOR_YUV2GRAY_YUNV
COLOR_YUV2GRAY_YUY2
COLOR_YUV2GRAY_YUYV
COLOR_YUV2GRAY_YV12
COLOR_YUV2GRAY_YVYU
COLOR_YUV2RGB
COLOR_YUV2RGBA_I420
COLOR_YUV2RGBA_IYUV
COLOR_YUV2RGBA_NV12
COLOR_YUV2RGBA_NV21
COLOR_YUV2RGBA_UYNV
COLOR_YUV2RGBA_UYVY
COLOR_YUV2RGBA_Y422
COLOR_YUV2RGBA_YUNV
COLOR_YUV2RGBA_YUY2
COLOR_YUV2RGBA_YUYV
COLOR_YUV2RGBA_YV12
COLOR_YUV2RGBA_YVYU
COLOR_YUV2RGB_I420
COLOR_YUV2RGB_IYUV
COLOR_YUV2RGB_NV12
COLOR_YUV2RGB_NV21
COLOR_YUV2RGB_UYNV
COLOR_YUV2RGB_UYVY
COLOR_YUV2RGB_Y422
COLOR_YUV2RGB_YUNV
COLOR_YUV2RGB_YUY2
COLOR_YUV2RGB_YUYV
COLOR_YUV2RGB_YV12
COLOR_YUV2RGB_YVYU
COLOR_YUV420P2BGR
COLOR_YUV420P2BGRA
COLOR_YUV420P2GRAY
COLOR_YUV420P2RGB
COLOR_YUV420P2RGBA
COLOR_YUV420SP2BGR
COLOR_YUV420SP2BGRA
COLOR_YUV420SP2GRAY
COLOR_YUV420SP2RGB
COLOR_YUV420SP2RGBA

: ملاحظة

من اجل الفضاء

HSV

مجال السطوع هو : [0,179]مجال الاشباع :[0,255]ومجال القيمة هو [0,255].القيم قد تختلف من برنامج لاخر . لذلك يجب مراعاة التحويل المناسب عند الانتقال اليها.

تعقب الاجسام

نعلم الان كيفية التحويل اللوني , ويمكننا استخدام هذا لاشتقاق جسم ملون , بالفضاء

HSV

يمكن تمثيل الالوان بسهولة اكبر مما بالفضاء

BGR

:وبتطبيقنا سنحاول اشتقاق جسم ملون ازرق والتالي هو الطريقة

خذ كل اطار من الفيديو

HSV حول من فضاء لاخر

خذ قيمة العتبة للصورة المحولة من اجل قيمة اللون المطلوبة ( الازرق) هنا

اشتق الجسم الملون الان ويمكن استخدام النتيجة الان لما نريده

:التالي هو البرنامج المفصل بالتعليقات

In [1]:
%matplotlib inline
In [4]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

cap = cv2.VideoCapture(0)

while (1):
    
    # Take each frame
    _, frame = cap.read()
    
    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    
    # define range of blue color in HSV
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])
    
    # Threshold the HSV image to get only blue colors
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    
    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame,frame, mask= mask)
    
    cv2.imshow('frame' ,frame)
    cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5)
    if k == 27:
        break
        
cv2.destroyAllWindows()

الصور ادناه تظهر اكتشاف الجسم الازرق , ولكن بسبب الاظهار في

matplotlib

يبدو احمر

In [15]:
plt.imshow(frame)
plt.show()
plt.imshow(mask)
plt.show()
plt.imshow(res)
plt.show()

لاحظ انه هناك بعض الضجيج في الصورة , سنرى بفصول لاحق كيف نزيلهم

: ملاحظة

هذه ابسط الطرق لتعقب الاجسام , ومتى احترفت توابع الاطارات بامكانك القيام بالعديد من الاشياء مثل ايجاد مركز الجسم , واستخدامه لتعقب الاجسام , ورسم البيانات فقط من خلال تحريك يدك امام كاميرا , والعديد من الاشياء الممتعة الاخرى

:كيف يمكنك تحديد القيم اللونية اللازم تعقبها

هذا سؤال شائع , في

stackoverflow.com

وهذا بغاية السهولة وبامكانك استخدام نفس التابع ,

cv2.cvtColor()

بدلا من تمرير صورة , يمكنك تمرير ال

BGR

التي ترغب بها , مثلا , لايجاد القيمة الموافقة للاخضر , جرب التالي بطرفية بايثون

In [16]:
green = np.uint8([[[0,255,0 ]]])
hsv_green = cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
print hsv_green
[[[ 60 255 255]]]

والان يمكنك اخذ

[H-10 , 100 ,100] و [H+10,255,255]

كحد ادنى وحد اعلى بالترتيب .

وبجانب هذه الطريقة , يمكنك استخدام اي ادوات تحرير صور , او محولات على الانترنت لايجاد هذه القيم ولكن لاتنسى تعديل المجالات

: تمرين غير محلول

جرب ايجاد طريقة لاشتقاق اكثر من جسم ملون بنفس الوقت , مثلا الاجسام الحمراء والزرقاء والخضراء

: تحويل العتبة للصور

:الهدف

في هذا القسم سنتعلم , التعتيب البسيط , التعتيب المتكيف ,والتعتيب وفق اوتسو

Otsu

وسنتعلم هذه التوابع

cv2.threshold , cv2.adaptiveThreshold

: التعتيب البسيط

هنا القضية بسيطة , اذا فاقت قيمة البكسل قيمة محددة , فيسند له 1 (ربما ابيض)والا يسند له 0 (ربما اسود)والتابع المستخدم هو

cv2.threshold

واول متغير له هو الصورة المصدر التي يجب ان تكون رمادية (مستوي واحد)والمتغير الثاني هو العتبة التي سنصنف البكسلات من خلالها , المتغير الثالث هو القيمة العظمى للبكسل الاكبر من العتبة كناتج والمكتبة

Opencv

:تعطي عدة خيارات للتعتيب وهذه تتحدد بالمتغير الثالث

  • cv2.THRESH_BINARY
  • cv2.THRESH_BINARY_INV
  • cv2.THRESH_TRUNC
  • cv2.THRESH_TOZERO
  • cv2.THRESH_TOZERO_INV

والتوثيق يشرح بالتفصيل وضع كل واحدة منها , وهناك خرجان , اولهما هو المرتجع الذي سيشرح لاحقا والاخر هو الصورة المعتبة الثنائية والبرنامج كما يلي

In [17]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('gradient.bmp',0)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)

titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in xrange(6):
    plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
    
plt.show()

: ملاحظة

لاظهار اكثر من صورة استخدمنا تابع

plt.subplot()

لمزيدمن الشرح يمكنك مراجعة التعليمات الخاصة بها.

: التعتيب المتكيف

في الفصل السابق استخدمنا قيمة شاملة كقيمة للعتبة , ولكن قد لايكون هذا جيدا حيث تملك الصور شروط اضاءة مختلفة باماكن مختلفة

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

ولديه ثلاث مداخيل خاصة ومتغير خرج وحيد

الطريقة المتكيفة

وهذه تقرر كيف تحسب قيمة العتبة

cv2.ADAPTIVE_THRESH_MEAN_C

قيمة التعتيب هي المتوسط لمساحة الجوار

cv2.ADAPTIVE_THRESH_GAUSSIAN_C

قيمة التعتيب هي المتوسط الموزون لمساحة الجوار , والاوزان هي النافذة الغاوسية

مساحة الوحدة

وهي تقرر مساحة الجوار المرغوب

C

وهذا ثابت يطرح من المتوسط او المتوسط الموزون المحسوب

البرنامج التالي يقارن التعتيب الشامل والمتكيف لاجل صورة متغيرة الاضاءة

In [18]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('Rene_Decart.jpg',0)
img = cv2.medianBlur(img,5)

ret,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
th2 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,\
            cv2.THRESH_BINARY,11,2)
th3 = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
            cv2.THRESH_BINARY,11,2)

titles = ['Original Image', 'Global Thresholding (v = 127)',
            'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]

for i in xrange(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

من الواضح انه بالتعتيب المتكيف , النتائج تكون افضل والضجيج اقل.

التحويل الثنائي لاوتسو

كما اوضحنا بالقسم السابق ان هناك متغيرا اخر لعملية التعتيب , فما عمله ؟؟

ما كنا نفعله بحالة التعتيب البسيط اننا نحدد العتبة ثم عن طريق التجربة والخطأ نحدد القيم المثالية , لها , ولكن اذا كان لدينا صورة

bimodal

(ببساطة صورة للهستوغرام خاصتها ذروتان) لهذه الصورة , سنأخذ قيمة عتبة وسطياً بين الذروتين , وهذا ما يفعله تحويل اوتسو .

وبعبارة بسيطة فانه يحسب قيمة العتبة من اجل الصور ثنائية الحالة , اما لباقي الصور فلن يكون التحويل الثنائي دقيقاً

ولتطبيق هذا نستخدم

cv2.THRESH_OTSU

لقيمة العتبة , مرر صفراً ببساطة , وعندها توجد الخوارزمية القيمة المثالية , وتعيده بالخرج الثاني , واذا لم يتم استخدام اوتسو فسيكون هذا الخرج نفسه , المحدد بالدخل

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

In [3]:
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('noisy.bmp',0)

# global thresholding
ret1,th1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)

# Otsu's thresholding
ret2,th2 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(img,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

# plot all the images and their histograms
images = [img, 0, th1,
    img, 0, th2,
    blur, 0, th3]
titles = ['Original Noisy Image','Histogram','Global Thresholding (v=127)',
        'Original Noisy Image','Histogram',"Otsu's Thresholding",
        'Gaussian filtered Image','Histogram',"Otsu's Thresholding"]

for i in xrange(3):
    plt.subplot(3,3,i*3+1),plt.imshow(images[i*3],'gray')
    plt.title(titles[i*3]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+2),plt.hist(images[i*3].ravel(),256)
    plt.title(titles[i*3+1]), plt.xticks([]), plt.yticks([])
    plt.subplot(3,3,i*3+3),plt.imshow(images[i*3+2],'gray')
    plt.title(titles[i*3+2]), plt.xticks([]), plt.yticks([])
plt.show()

:تمارين

هناك بعض طرق الامثلة المتوفرة , لتحويل اوتسو الثنائي , ابحث عنها وطبقها..

Otsu’s binarization optimizations

In [ ]:
 

ليست هناك تعليقات:

إرسال تعليق