مطابقة السمات + تحويلات لايجاد الاجسام:¶
الهدف:¶
- سندمج بهذا الفصل مطابقة السمات مع ايجاد التحويلات , عبر calib3d لايجاد أجسام معروفة بصور مختلطة المشهد.
الاساسيات:¶
ما قمنا به بالدرس السابق , كان استخدام صورة والبحث عنها باخرى , وجدنا بعض السمات فيها ثم , أخذنا صورة تدريب وأوجدنا السمات بها ايضاً ثم طابقنا المجموعتين من السمات , من خلال حساب المسافة الاقرب لكل منها .
باختصار أوجدنا اماكن بعض الاجزاء للجسم في صورة أخرى . وهذه المعلومات تكفي لايجاد الجسم المطابق تماماً .
ولهذا يمكننا استخدام التابع التالي : cv2.findHomography() . واذا مررنا مجموعة من النقاط من كلا الصورتين , فسنجد التحويلات الاسقاطية لهذا الجسم . ومن ثم يمكننا استخدام cv2.perspectivTransform() لايجاد الجسم , ونحتاج على الاقل أربعة نقاط متطابقة لايجاد التحويل .
ولقد راينا سابقاً إمكانية حدوث أخطاء أثناء المطابقة تؤثر على النتيجة .
ولحل هذه المشكلة نستخدم خوارزمية RANSAC أو LEAST_MEDIAN (ونحدد ذلك عبر الاعلام ). ولذلك فالمطابقات الجيدة التي تعطي تقديرات جيدة تدعى inliers والمتبقية تدعى outliers , والتابع cv2.findHomography() يعطي قناعاً يصنف السمات لاحد المجموعتين السابقتين .
البرنامج :¶
أولا نبحث عن سمات SIFT أو ORB أو FAST , بالصورتين ونطابق الموصفات ثم نعزل المطابقات الغير دقيقة وفق اختبار النسبة
import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
img1 = cv2.imread('images/query.png',0) # queryImage
img2 = cv2.imread('images/train.jpg',0) # trainImage
# Initiate ORB detector
orb = cv2.ORB_create()
# find the keypoints and descriptors with ORB
kp1, des1 = orb.detectAndCompute(img1,None)
kp2, des2 = orb.detectAndCompute(img2,None)
# create BFMatcher object
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# Match descriptors.
matches = bf.match(des1,des2)
# Sort them in the order of their distance.
matches = sorted(matches, key = lambda x:x.distance)
# Take the Best
good = matches[:40]
والان نضع شرطأ انه يجب ايجاد عشرة مطابقات على الاقل لايجاد الجسم . والا ستظهر رسالة تقول أن عدد النقاط غير كافي .
أما اذا أوجدنا مطابقات كافية , سنشتق الخصائص للنقاط المتطابقة بكلا الصورتين , ومن ثم نمررها لايجاد التحويل الاسقاطي . وبعد حصولنا على المصفوفة 3x3 , نستخدمها لتحويل زوايا الصورة المستفسر عنها للمكان المرتبط بالصورة , المستفسر فيها , ومن ثم نرسم .
MIN_MATCH_COUNT = 10
if len(good)>MIN_MATCH_COUNT:
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
matchesMask = mask.ravel().tolist()
h,w = img1.shape
pts = np.float32([ [0,0],[0,h-1],[w-1,h-1],[w-1,0] ]).reshape(-1,1,2)
dst = cv2.perspectiveTransform(pts,M)
img2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA)
else:
print "Not enough matches are found - %d/%d" % (len(good),MIN_MATCH_COUNT)
matchesMask = None
أخيرأً نرسم النقاط الصحيحة (إذا وجدنا الجسم) أو النقاط المتطابقة (إذا فشلت العملية ) .
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
cv2.imwrite('figure_4.png',img3)
from IPython.display import Image
Image('images/figure_4.png')
ليست هناك تعليقات:
إرسال تعليق