ফেস রিকগনিশন (Face recognition aka: Facial recognition) বা মুখমণ্ডল শনাক্তকরণ পদ্ধতি হলো ছবিতে মানুষের মুখ শনাক্ত করার একটি প্রদ্ধতি যেখানে কম্পিউটার ভিশন এর ব্যবহার করা হয়।
FaceNet: মুখ শনাক্তকরণ (Facial recognition) মডেল
২০১৫ সালে গুগলের গবেষকরা FaceNet নামে একটি সিস্টেম উদ্ভাবন করেন যা Facial recogniton / Face recognition বা মানুষের মুখমণ্ডল শনাক্তকরণের কাজে বেশ কার্যকর প্রমাণিত হয়। আমরাও FaceNet ব্যবহার করে মুখ শনাক্তকরনের কাজ খুব সহজেই করতে পারি। সেজন্য বিশাল একটা ধন্যবাদ কিন্তু সেসব third party, open source প্রজেক্ট এর contributor দের দেয়া দরকার যাদের জন্য আমরা বিনামূল্যে FaceNet এর কোডের ইমপ্লিমেন্টেশন ও বিশাল পরিমাণ ডাটাদিয়ে প্রিট্রেইন করা মডেল অ্যাক্সেস করতে পারছি। 🙂
FaceNet মডেল দিয়ে আমরা আমাদের মুখ থেকে প্রধান যে ফিচার গুলো আছে (aka Facial features) সেগুলোকে বের করে নিতে পারি যাকে ফেস এমবেডিং (Face embeddings) ও বলা হয়। এই ফেস এমবেডিং গুলো ব্যবহার করেই আমরা একটি ছবির সাথে আরেকটি ছবির মিল/অমিল হিসেব করতে পারি। এই লিখায় দেখবো কিভাবে আমরা FaceNet ব্যবহার করে ছবির মানুষটি কে তা বের করতে পারি।
এই লিখায় আমরা যা করবো তা হলো,
- গুগল ফেস নেট নিয়ে জানবো।
- দেখবো কিভাবে একটি ছবি থেকে মুখের অংশটুকু আলাদা করা যায় (Face detection)
- দেখবো কিভাবে Face recognition এর জন্য ডাটাসেট তৈরি করতে হয়
- আলাদা করা মুখের ছবি থেকে কিভাবে তার এমবেডিং হিসাব করে মানুষের পরিচয় বের করা যায় (Face identification)
Face recognition: দরকারি python লাইব্রারি গুলো:
- মডেল লোড, এমবেড প্রেডিক্ট করার জন্য টেনসরফ্লো-কেরাস (Tensorflow-keras) version 2.3.1
- ছবি তুলা, রিসাইজ করা ও বিভিন্ন অপারেশনের জন্য এবং ছবি থেকে মুখ বের করার জন্য ওপেন সিভি (Open CV)
- গণিতের হিসাব নিকাশ করার জন্য নামপাই লাইব্রেরী (Numpy)
- যেকোনো পাইথন IDE ( Jupyter notebook হলে ভালো)
এইতো, আর তেমন কিছু লাগবে না। আমরা pip কমান্ড দিয়ে লাইব্রেরী গুলো ইন্সটল করে নিবো।
Time needed: 5 minutes
কিভাবে Tensorflow এবং opencv ইন্সটল করা লাগবে?
- pip না থাকে যদি তাহলে pip ইন্সটল করতে হবে
আপনার পিসি তে pip আছে কিনা তা দেখার জন্য পাইথন শেল এ এই কমান্ড দিন
Linux: python -m pip –version
Windows: py -m pip –version
যদি ঠিকঠাক pip ভার্সন দেখায় তাহলে ঠিক আছে, নতুবা,
https://bootstrap.pypa.io/get-pip.py এখান থেকে পাইথন ফাইল টি ডাউনলোড করে পাইথন শেলে রান করান। pip ইন্সটল হয়ে যাবে।
ps: যদি CMD বা Terminal থেকে python রান না হয় তবে আপনার পাইথন ফোল্ডার টি সিস্টেম পাথ এ যুক্ত করতে হবে। - টেন্সরফ্লো (Tensorflow) ইন্সটল করা
Tensorflow ইন্সটল করার জন্য এই কমান্ড টি আপানর Command prompt/ Terminal এ রান করানো লাগবে।
pip install tensorflow
এটা দিলেই আশা করা যায় টেন্সরফ্লো নরমালি ইন্সটল হয়ে যাবে। - কেরাস (Keras) ইন্সটল করা
টেন্সরফ্লো এর সাথেই কেরাস লাইব্রেরী যুক্ত থাকে
- OpenCv ইন্সটল করা
ওপেন সিভি ইন্সটল করার সাধারণ ভাবে pip install opencv-python কমান্ড দিলেই হবে।
Face Detection: ছবি থেকে মুখের অংশ টুকু আলাদা করা
নিচের ছবিটি দেখি, এখানে আমাদের নেতা ওবামা ভাই এবং তার স্ত্রী মিশেল ওবামা আপা আছেন।
তো এখানে আমরা দুইটি মুখের ছবি দেখছি। তো কম্পিউটারে যদি আমরা এই দুটি ছবিকে চিহ্নিত করতে চাই তবে আমাদেরকে প্রথমেই তাদের দুইজনের মুখকে আলাদা করে বের করে নিতে হবে। আমরা Python opencv ব্যবহার করে খুব সহজেই কাজটি করে ফেলটি পারি। আমরা আমাদের মুখের বিভিন্ন ফিচার ব্যবহার করবো মুখ গুলো চিহ্নিত করতে। আমরা এদের Haar features বলি। নিচের পাইথন কোড টি দেখি,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import numpy as np import cv2 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') img = cv2.imread('obama_photo.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.2, 5) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) face = img[y:y+h, x:x+w] cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() |
একটা নির্দিষ্ট ফোল্ডার করে কোডটিকে main.py নামে সেভ করুন। ফোল্ডারটিতে এই ফাইলটি ডাউনলোড করে রাখুন। এই ছবিটিও ডাউনলোড করে রাখুন, ফোল্ডারে নিচের মতো দেখা যাবে।
তারপর আমরা python shell এ code.py ফাইলটি রান করি। এর জন্য python code.py কমান্ড দিতে হবে। নিচের মতো আউটপুট পাওয়া যাবে।
কোডে face variable টি মুখগুলোকে বের করে রাখবে।
ফেস রিকগনিশন (Face recognition) এর জন্য আমরা roi_color variable টিকে একটি ফাংশনের মধ্যে পাস করে দিবো। বাকি কাজ আমাদের ফাংশনটিই করবে। এবার আমরা মুল কাজে নামতে যাচ্ছি। প্রথমেই আমাদেরকে ফেস নেট মডেলটি ডাউনলোড করে নিতে হবে। ডাউনলোড লিঙ্কটি এখানে।
Face recognition (ফেস রিকগনিশন): ছবির মুখটি কার তা বের করা।
আশা করি মডেল ফাইলটি ডাউনলোড করে নিয়েছেন সবাই। মডেলটিকে আপনার যে ফোল্ডারে main.py ফাইলটি আছে সেখানে রাখেন। এখন আমাদের মডেলটিকে আমাদের প্রোগ্রামে লোড করাতে হবে। এর জন্য আমাদেরকে tensorflow.keras.models থেকে load_model কে import করে নিতে হবে। তারপর একটি লাইনে আমাদের মডেলকে লোড করে নিতে হবে নিচের মতো করে।
1 2 3 4 5 | #Loading load_model from tensorflow.keras.models from tensorflow.keras.models import load_model #Loading the facenet model embedding_model=load_model("Facenet_model.h5") |
এখন আমাদের একটা ফাংশন বানাতে হবে যে একটা ফোল্ডার থেকে আমাদের ডাটা গুলো লোড করবে। এবং তার এনকোডিং গুলো একটা পাইথন ডিকশনারিতে ভরে রিটার্ন করবে।
ডাটা লোড করা (Loading the data)
আমরা বিষয়টাকে যতদূর সম্ভব সিম্পল রাখার চেষ্টা করবো। একটু মাথা খাটালেই আমরা একটু জটিল সিস্টেম বানাতে পারবো। আপাতত আমরা সিঙ্গেল ছবি দিয়ে কাজ চালিয়ে নিবো। নিচের কোডটা হাস্যকর মনে হতেই পারে 😉
1 2 3 4 5 6 7 8 | images = {} images['ben_afflek'] = cv2.imread('data/ben_afflek/1.jpg') images['elton_john'] = cv2.imread('data/elton_john/1.jpg') images['jerry_seinfeld'] = cv2.imread('data/jerry_seinfeld/1.jpg') images['madonna'] = cv2.imread('data/madonna/1.jpg') images['obama'] = cv2.imread('data/obama/1.png') images['michelle_obama'] = cv2.imread('data/michelle_obama/1.png') |
আমরা ডাটাকে নিয়ে একটু কাজ করে নিবো। আমরা প্রথমে কালার চ্যানেল কনভার্ট করবো (BGR2RGB)। তারপর ছবিটি (160×160) এ রিসাইজ করবো। তারপর ছবিটিকে স্টান্ডার্ডাইজ করে নিবো তারপর আবার images ডিকশনারিতে রেখেদিবো। এটুকুই। আমরা কোডটি দেখি।
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import numpy as np def prewhiten(x): if x.ndim == 4: axis = (1, 2, 3) size = x[0].size elif x.ndim == 3: axis = (0, 1, 2) size = x.size else: raise ValueError('Dimension should be 3 or 4') mean = np.mean(x, axis=axis, keepdims=True) std = np.std(x, axis=axis, keepdims=True) std_adj = np.maximum(std, 1.0 / np.sqrt(size)) y = (x - mean) / std_adj return y for name in images: img=images[name] img=cv2.resize(img,(160,160)) img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) images[name]=prewhiten(img) |
ফেস এনকোডিং প্রেডিক্ট করা (Predicting face encoding from facenet)
আমাদের এখনকার কাজ হলো আমাদের মুখের ছবিগুলোর জন্য Face encodings প্রেডিক্ট করা। এর জন্য আমরা embedding_model ভ্যারিএবল এ যে মডেলটি রেখিছি সেখানে ছবিটি ইনপুট দিবো।
ডাটাসেট ফেস এনকোডিং প্রি ক্যালকুলেট করা
আমরা আমাদের লোডেড মডেল অবজেক্টের predict() মেথড ব্যবহার করে প্রত্যেকটি স্যাম্পলের জন্য এমবেডিং ক্যালকুলেট করবো। নিচের কোডটি দেখি,
1 2 3 4 5 6 7 8 9 | def l2_normalize(x, axis=-1, epsilon=1e-10): output = x / np.sqrt(np.maximum(np.sum(np.square(x), axis=axis, keepdims=True), epsilon)) return output for name in images: img=images[name] img=np.reshape(img,(1,160,160,3)) emb=embedding_model.predict(img) images[name]=l2_normalize(emb) |
এখানে আমাদের ছবিটিকে প্রথমে images ডিকশনারি থেকে বের করে reshape করা হয়েছে। এখানে আমাদের মডেলটিকে আগে (None,160,160,3) ডাইমেনশনের ডাটা দিয়ে ট্রেইন করা হয়েছিলো। এখানে আমাদের Dimension দেখা যাচ্ছে 4 । কিন্তু আমাদের প্রতিটি ছবির ডাইমেনশন হলো 3 । যার জন্য আমরা বাড়তি একটি ডাইমেনশন যোগ করে দিয়েছি 4 ডাইমেনশন করার জন্য। পরবর্তি লাইনের মাধ্যমে আমরা সিম্পল করে predict() মেথড কলের মাধ্যমে ফেস এমবেডিংটা বের করে L2 Normalize করে images ডিকশনারিতে রেখে দিয়েছি।
ইনপুট ইমেজ থেকে মুখগুলোর ছবির এমবেডিং বের করা এবং নাম প্রেডিকশন
মনে আছে সবার উপরে আমরা face ভ্যারিয়েবলে মুখগুলো বের করে রাখছিলাম? এখন আমরা ওই ভেরিয়েবল টি কাজে লাগাবো। তার আগে আমরা একটা ফাংশন লিখি, যে একটি মুখের ছবি নিবে এবং ছবিটি কার তা প্রেডিক্ট করবে। কোডটি দেখি
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | def predict_name(img): img=cv2.resize(img,(160,160)) img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) img=np.resize(img,(1,160,160,3)) img=prewhiten(img) emb=embedding_model.predict(img) emb_norm=l2_normalize(emb) minimum_dis=9999 person=None for name in images: dis=np.linalg.norm(emb_norm-images[name]) if dis<minimum_dis: person=name minimum_dis=dis return person,minimum_dis |
লুপের আগ পর্যন্ত প্রসেস টা আমাদের পরিচিত। লুপের ভিতরে আমরা যে আগে ডাটাসেটের প্রতিটি মুখের জন্য Embeddings হিসাব করে রাখছিলাম তা images[name] এর মাধ্যমে পুনরায় বের করেছি। এখানে emb_norm টা হলো নতুন ইনপুটের জন্য L2 Normalize করা embedding। যাইহোক, এখানে আমরা np.linalg.norm দিয়ে আমরা দুটি Embedding এর মধ্যে দূরত্ব বের করেছি এবং সবচেয়ে কম দূরত্বের যে নামের ছবির জন্য তাকে বের করে ড়িটার্ন করেছি। আরেকটু বেশি বুঝার জন্য ছবিটি দেখি,
পরবর্তি কাজ খুব সহজ, সবার উপরের কোডটি আবার দেখি,
1 2 3 4 5 6 7 8 9 10 11 12 13 | img = cv2.imread('obama_photo.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.2, 5) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) face = img[y:y+h, x:x+w] name,_=predict_name(face) img = cv2.putText(img, name, (x,y),cv2.FONT_HERSHEY_SIMPLEX,1,(0, 0, 255)) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() |
এখানে predict_name ফাংশনে আমরা আমাদের মুখের ছবি পাস করছি এবং পরে ছবির উপর নামটি লিখে দিচ্ছি cv2.putText এর মাধ্যমে। শেষ।
তো প্রোগ্রামটির সম্পুর্ন কোড নিচে দেয়া আছে
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | import numpy as np import cv2 #Loading load_model from tensorflow.keras.models from tensorflow.keras.models import load_model #Loading the facenet model embedding_model=load_model("Facenet_model.h5") face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') images = {} images['ben_afflek'] = cv2.imread('data/ben_afflek/1.jpg') images['elton_john'] = cv2.imread('data/elton_john/1.jpg') images['jerry_seinfeld'] = cv2.imread('data/jerry_seinfeld/1.jpg') images['madonna'] = cv2.imread('data/madonna/1.jpg') images['obama'] = cv2.imread('data/obama/1.png') images['michelle_obama'] = cv2.imread('data/michelle_obama/1.png') import numpy as np def prewhiten(x): if x.ndim == 4: axis = (1, 2, 3) size = x[0].size elif x.ndim == 3: axis = (0, 1, 2) size = x.size else: raise ValueError('Dimension should be 3 or 4') mean = np.mean(x, axis=axis, keepdims=True) std = np.std(x, axis=axis, keepdims=True) std_adj = np.maximum(std, 1.0 / np.sqrt(size)) y = (x - mean) / std_adj return y for name in images: img=images[name] img=cv2.resize(img,(160,160)) img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) images[name]=prewhiten(img) def l2_normalize(x, axis=-1, epsilon=1e-10): output = x / np.sqrt(np.maximum(np.sum(np.square(x), axis=axis, keepdims=True), epsilon)) return output for name in images: img=images[name] img=np.reshape(img,(1,160,160,3)) emb=embedding_model.predict(img) images[name]=l2_normalize(emb) def predict_name(img): img=cv2.resize(img,(160,160)) img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB) img=np.resize(img,(1,160,160,3)) img=prewhiten(img) emb=embedding_model.predict(img) emb_norm=l2_normalize(emb) minimum_dis=9999 person=None for name in images: dis=np.linalg.norm(emb_norm-images[name]) if dis<minimum_dis: person=name minimum_dis=dis return person,minimum_dis img = cv2.imread('obama_photo.jpg') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.2, 5) for (x,y,w,h) in faces: img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) face = img[y:y+h, x:x+w] name,_=predict_name(face) img = cv2.putText(img, name, (x,y),cv2.FONT_HERSHEY_SIMPLEX,1,(0, 0, 255)) cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows() |
আমাদের এতক্ষণ ধরে এত কষ্ট করার পর আউটপুটটি দেখা উচিত, এইযে আমাদের আউটপুট। আপনারও কোডটি নিজের PC তে রান করিয়ে দেখে নিন।
এইতো, আমাদের প্রোগ্রাম ঠিকঠাক দুজন মানুষকে চিনে নিয়েছে। আমরা এই ফেস রিকগনেশন সিস্টেম ব্যবহার করে বিভিন্ন সফটওয়ার বানাতে পারি। যেমন Attendace project, similar person খুঁজে বের করা ইত্যাদি। আরও ইন্টেরেস্টিং প্রজেক্ট করা যাবে। পুরো প্রজেক্টটি আমার গিটহাবে রিপোতে পাওয়া যাবে। প্রজেক্টটি পেতে এই লিঙ্কে ভিজিট করুন। ভুল ক্রুটি ক্ষমা সুন্দর দৃষ্টিতে দেখে আমাকে জানানোর জন্য অনুরোধ করছি। ভালো লাগলে শেয়ার করতে ভুলবেন না। গিট নিয়ে জানতে এই লেখাটি পড়তে পারেন।