مشروع عطلة نهاية الأسبوع: لغة الإشارة والتعرف على الإيماءات الثابتة باستخدام scikit-Learn

دعونا نبني خط أنابيب للتعلم الآلي يمكنه قراءة أبجدية لغة الإشارة فقط من خلال النظر إلى صورة أولية ليد الشخص.

هذه المشكلة لها جزأين:

  1. بناء أداة التعرف على الإيماءات الثابتة ، وهي عبارة عن مصنف متعدد الفئات يتنبأ بإيماءات لغة الإشارة الثابتة.
  2. تحديد موقع اليد في الصورة الأولية وتغذية هذا القسم من الصورة إلى أداة التعرف على الإيماءات الثابتة (المصنف متعدد الفئات).

يمكنك الحصول على رمز المثال الخاص بي ومجموعة البيانات الخاصة بي لهذا المشروع هنا.

أولاً ، بعض المعلومات الأساسية.

يعد التعرف على الإيماءات مشكلة مفتوحة في مجال رؤية الآلة ، وهو مجال من مجالات علوم الكمبيوتر يمكّن الأنظمة من محاكاة الرؤية البشرية. التعرف على الإيماءات له العديد من التطبيقات في تحسين التفاعل بين الإنسان والحاسوب ، أحدها في مجال ترجمة لغة الإشارة ، حيث يتم ترجمة تسلسل فيديو لإيماءات اليد الرمزية إلى لغة طبيعية.

تم تطوير مجموعة من الأساليب المتقدمة لنفسه. هنا ، سننظر في كيفية إجراء التعرف على الإيماءات الثابتة باستخدام مكتبات الصور scikit Learn و scikit.

الجزء 1: إنشاء أداة التعرف على الإيماءات الثابتة

بالنسبة لهذا الجزء ، نستخدم مجموعة بيانات تشتمل على صور أولية وملف csv مقابل مع إحداثيات تشير إلى المربع المحيط لليد في كل صورة. (استخدم ملف Dataset.zip للحصول على مجموعة البيانات النموذجية. استخراج وفقًا للإرشادات الموجودة في الملف التمهيدي)

يتم تنظيم مجموعة البيانات هذه حسب المستخدم وتكون بنية الدليل لمجموعة البيانات كما يلي. تشير أسماء الصور إلى الأبجدية التي تمثلها الصورة.

dataset |----user_1 |---A0.jpg |---A1.jpg |---A2.jpg |---... |---Y9.jpg |----user_2 |---A0.jpg |---A1.jpg |---A2.jpg |---... |---Y9.jpg |---- ... |---- ...

أداة التعرف على الإيماءات الثابتة هي في الأساس مصنِّف متعدد الفئات يتم تدريبه على إدخال الصور التي تمثل 24 إيماءات لغة الإشارة الثابتة (AY ، باستثناء J).

يعد إنشاء أداة التعرف على الإيماءات الثابتة باستخدام الصور الأولية وملف csv أمرًا بسيطًا إلى حد ما.

لاستخدام المصنفات متعددة الفئات من مكتبة scikit Learn ، سنحتاج أولاً إلى إنشاء مجموعة البيانات - أي ، يجب تحويل كل صورة إلى متجه ميزة (X) وستحتوي كل صورة على ملصق يتوافق مع أبجدية لغة الإشارة التي تشير إليها (Y).

المفتاح الآن هو استخدام استراتيجية مناسبة لتوجيه الصورة واستخراج معلومات ذات مغزى لتغذية المصنف. لن يعمل استخدام قيم البكسل الأولية ببساطة إذا خططنا لاستخدام مصنفات بسيطة متعددة الفئات (على عكس استخدام شبكات Convolution).

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

الشفرة:

نستخدم الباندا في وظيفة get_data () لتحميل ملف CSV. وظيفتان-المحاصيل ()و convertToGrayToHog ()تُستخدم للحصول على متجه الخنازير المطلوب وإلحاقه بقائمة المتجهات التي نبنيها ، من أجل تدريب المصنف متعدد الفئات.

# returns hog vector of a particular image vector def convertToGrayToHOG(imgVector): rgbImage = rgb2gray(imgVector) return hog(rgbImage) # returns cropped image def crop(img, x1, x2, y1, y2, scale): crp=img[y1:y2,x1:x2] crp=resize(crp,((scale, scale))) return crp #loads data for multiclass classification def get_data(user_list, img_dict, data_directory): X = [] Y = [] for user in user_list: user_images = glob.glob(data_directory+user+'/*.jpg') boundingbox_df = pd.read_csv(data_directory + user + '/' + user + '_loc.csv') for rows in boundingbox_df.iterrows(): cropped_img = crop( img_dict[rows[1]['image']], rows[1]['top_left_x'], rows[1]['bottom_right_x'], rows[1]['top_left_y'], rows[1]['bottom_right_y'], 128 ) hogvector = convertToGrayToHOG(cropped_img) X.append(hogvector.tolist()) Y.append(rows[1]['image'].split('/')[1][0]) return X, Y

الخطوة التالية هي ترميز تسميات الإخراج (قيم ص) إلى قيم عددية. نقوم بذلك باستخدام برنامج تشفير بطاقة sklearn.

في الكود الخاص بنا ، قمنا بهذا على النحو التالي:

Y_mul = self.label_encoder.fit_transform(Y_mul)

حيث يتم إنشاء كائن label_encoder على النحو التالي داخل مُنشئ فئة أداة التعرف على الإيماءات:

self.label_encoder = LabelEncoder().fit(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y'])

بمجرد الانتهاء من ذلك ، يمكن تدريب النموذج باستخدام أي خوارزمية تصنيف متعددة الفئات من اختيارك من مربع أدوات scikit Learn. لقد قمنا بتدريب فريقنا باستخدام تصنيف المتجهات الداعمة ، باستخدام نواة خطية.

لا يتضمن تدريب نموذج باستخدام sklearn أكثر من سطرين من التعليمات البرمجية. إليك كيف تفعل ذلك:

svcmodel = SVC(kernel='linear', C=0.9, probability=True) self.signDetector = svcmodel.fit(X_mul, Y_mul) 

يمكن ضبط المعلمات الفائقة (أي C = 0.9 في هذه الحالة) باستخدام بحث الشبكة. اقرأ اكثر عن هذه هنا.

في هذه الحالة ، لا نعرف الكثير عن البيانات على هذا النحو (أي ، ناقلات الخنازير). لذلك ، سيكون من الجيد محاولة استخدام خوارزميات مثل xgboost (Extreme Gradient Boosting) أو Random Forest Classifiers ومعرفة كيفية أداء هذه الخوارزميات.

الجزء 2: بناء المترجم

يتطلب هذا الجزء جهدًا أكبر قليلاً مقارنةً بالجزء الأول.

بشكل عام ، سوف نستخدم الخطوات التالية لإكمال هذه المهمة.

  1. قم ببناء مجموعة بيانات تشتمل على صور للأيدي والأجزاء غير اليدوية ، باستخدام مجموعة البيانات المحددة وقيم الصندوق المحيط لكل صورة.
  2. تدريب مصنف ثنائي لاكتشاف الصور اليدوية / غير اليدوية باستخدام مجموعة البيانات أعلاه.
  3. (اختياري) استخدم Hard Negative Mining لتحسين المصنف.
  4. استخدم نهج النافذة المنزلقة بمقاييس مختلفة ، على صورة الاستعلام لعزل منطقة الاهتمام.

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

بناء مجموعة البيانات اليدوية / غير اليدوية:

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

""" This function randomly generates bounding boxes Returns hog vector of those cropped bounding boxes along with label Label : 1 if hand ,0 otherwise """ def buildhandnothand_lis(frame,imgset): poslis =[] neglis =[] for nameimg in frame.image: tupl = frame[frame['image']==nameimg].values[0] x_tl = tupl[1] y_tl = tupl[2] side = tupl[5] conf = 0 dic = [0, 0] arg1 = [x_tl,y_tl,conf,side,side] poslis.append( convertToGrayToHOG(crop(imgset[nameimg], x_tl,x_tl+side,y_tl,y_tl+side))) while dic[0] <= 1 or dic[1] < 1: x = random.randint(0,320-side) y = random.randint(0,240-side) crp = crop(imgset[nameimg],x,x+side,y,y+side) hogv = convertToGrayToHOG(crp) arg2 = [x,y, conf, side, side] z = overlapping_area(arg1,arg2) if dic[0] <= 1 and z <= 0.5: neglis.append(hogv) dic[0] += 1 if dic[0]== 1: break label_1 = [1 for i in range(0,len(poslis)) ] label_0 = [0 for i in range(0,len(neglis))] label_1.extend(label_0) poslis.extend(neglis) return poslis,label_1

تدريب مصنف ثنائي:

بمجرد أن تصبح مجموعة البيانات جاهزة ، يمكن تدريب المصنف تمامًا كما رأينا سابقًا في الجزء 1.

عادة ، في هذه الحالة ، يتم استخدام تقنية تسمى التعدين السلبي الصلب لتقليل عدد الاكتشافات الإيجابية الكاذبة وتحسين المصنف. تكرار واحد أو تكررتان للتعدين السلبي الصلب باستخدام مصنف Random Forest كافٍ لضمان وصول المصنف إلى دقة تصنيف مقبولة ، والتي في هذه الحالة أعلى من 80٪.

ألقِ نظرة على الكود هنا للحصول على نموذج لتطبيق نفس الشيء.

كشف الأيدي في صور الاختبار:

Now, to actually use the above classifier, we scale the test image by various factors and then use a sliding window approach on all of them to pick the window which captures the region of interest perfectly. This is done by selecting the region corresponding to the max of the confidence scores allotted by the binary (hand/not-hand) classifier across all scales.

The test images need to be scaled because, we run a set sized window (in our case, it is 128x128) across all images to pick the region of interest and it is possible that the region of interest does not fit perfectly into this window size.

Sample implementation and overall detection across all scales.

Putting it all together

After both parts are complete, all that’s left to do is to call them in succession to get the final output when provided with a test image.

That is, given a test image, we first get the various detected regions across different scales of the image and pick the best one among them. This region is then cropped out, rescaled (to 128x128) and its corresponding hog vector is fed to the multi-class classifier (i.e., the gesture recognizer). The gesture recognizer then predicts the gesture denoted by the hand in the image.

Key points

To summarize, this project involves the following steps. The links refer to the relevant code in the github repository.

  1. Building the hand/not-hand dataset.
  2. Converting all the images i.e., cropped sections with the gestures and the hand, not-hand images, to its vectorized form.
  3. Building a binary classifier for detecting the section with the hand and building a multi-class classifier for identifying the gesture using these data sets.
  4. استخدام المصنفات أعلاه واحدة تلو الأخرى لأداء المهمة المطلوبة.

عملت أنا وسوكس في هذا المشروع كجزء من دورة التعلم الآلي التي أخذناها في الكلية. صيحة كبيرة لها على كل مساهماتها!

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

في صحتك!