music box

چکیده:

در این پروژه، دو هدف دنبال شده‌است. یکی تشخیص تک‌به‌تک نت‌های موسیقی (نام نت و ارزش زمانی نت) از روی یکnote sheet(Note Reader)، و دیگری تشخیص سبک موسیقی(music genre recognition) از روی فایل صوتی (پاپ، راک،…) . و در هر بخش شبکه‌های متفاوتی آموزش داده‌شده است.که یک به یک هر دو هدف توضیح داده خواهد شد.

Note Reader:
مقدمه

اولین قدم برای نواختن یک موسیقی، تشخیص و خواندن نت‌های آن است.که نوازنده پس از خواندن تک به تک نت ها می تواند آنها را اجرا کند اما اجرای موسیقی از روی تصویر نت توسط کامپیوتر برای جامعه هنر بسیار کارامد خواهد بود  و تاثیر بسزایی در آهنگ سازی و کمک به یادگیری موسیقی و… خواهد داشت. برای این کار ما سعی کردیم  از بینایی ماشین و پردازش تصویر با کمک شبکه‌های عصبی استفاده کرده تا نتیجه دلخواه را داشته باشیم.

در این پروژه از سه روش برای تشخیص نت استفاده و نتیجه های آن بررسی شد، در ادامه هر سه روش به طور مفصل بیان خواهد شد.

آزمایش‌ها و داده‌ها

برای جدا کردن خط های یک صفحه از نت شیت از contour استفاده کردیم اما برای جدا کردن نت ها ابتدا سعی میکردیم خطوط حامل را حذف کنیم و با استفاده از contour نت ها را از یکدیگر جدا کنیم. اما مشکلی که در این بخش با آن رو به رو بودیم وجود نت های چنگ است که به یکدیگر چسبیده هستند و جدا کردن آن ها به این روش ممکن نیست زیرا اگر میخواستیم کل خطوط افقی موجود در صفحه را حذف کنیم تا بتوانیم نت ها را از هم تفکیک کنیم، چنگ بودن این نت ها را از دست میدادیم.

برای رفع این مشکل با استفاده از الگوریتم DBScan سعی کردیم نقاط core را شناسایی کرده و از فاصله ای مناسب آن ها را ببریم.

Segmentation & RNN:

دیتاست این قسمت شامل تصویر نت شیت و یک فایل txt حاوی نام نت ها موجود در هر خط به طور جدا گانه است.

در این قسمت از شبکه lstm استفاده کردیم اما متاسفانه چون تمام نت ها به طور قطع در الگوریتم DBScan شناسایی نمی شدند یا موارد اضافه تری هم به عنوان نت شناسایی میشدند که در فایل txt نامی از آنها نبود، به همین خاطر که mapping درستی بین نت ها در نت شیت و فایل txt وجود نداشت و شبکه دچار مشکل میشد.

CTC Loss:

برای استفاده از CTC loss از مدل اماده توسعه داده شده به کراس در لینک زیر استفاده کردیم اما این بار هم به دلایل مشابه در قسمت segmentation به مشکل خوردیم و وقتی سعی کردیم مشکل را نادیده بگیریم و مدل را روی 5 نت شیت بدون ارور آزمایش کنیم سخت افزاری دچار مشکل شدیم.

CTC keras model:https://git.litislab.fr/TextRecognition/CTCModel/tree/master

CNN:

تشخیص نت شامل دو بخش نام نت(دو-ر-می-فا-…) و ارزش زمانی(گرد-سفید-سیاه-چنگ-دولا چنگ-…) مربوط نت است.که برای هر یک از این قسمت ها شبکه جداگانه آموزش دادیم. مشکل اصلی در این قسمت نبود دیتاست بود که سعی کردیم با استفاده از همان الگوریتم DBScan به تولید دیتا بپردازیم و لیبل بزنیم که نتیجه این نوع تولید دیتا وجود دو الی سه برابر دیتا در کلاس های پر کاربرد بود که پس از ترین کردن، شبکه تنها قادر به تشخیص یک نوع نت بود که سه برابر بقیه کلاس ها در آن دیتا وجود داشت. برای رفع این مشکل به علت کمبود وقت سعی کردیم دیتا ها را در همه کلاس ها یکسان کنیم اما این کار هم باعث overfit شدن شبکه با accuracy 99%   شد.

music genre recognition:
مقدمه

تشخیص ژانر موسیقی  میتواند در دسته بندی انواع موسیقی بسیار یاری رسان باشد. همچنین برای داشتن اطلاعات مربوط به یک موسیقی یکی از ویژگی های مهم میتواند ژانر آن موسیقی باشد. حال ما سعی کردیم با استفاده از شبکه های عمیق این قابلیت را ایجاد کنیم تا بتوانیم بدون گوش دادن به موسیقی و توسط کامپیوتر بتوانیم ژانر موسیقی را تشخیص دهیم.

آزمایش‌ها و داده‌ها

دیتاست:

ما برای این قسمت از دیتاست GTZAN که شامل انواع سبک های ” classical, country, disco, hip hop metal, jazz, pop, reggae, blues, rock,” است استفاده کردیم.

برای این قسمت تصمیم گرفته شد تا از مدل  RNNنوشته شده در لینک زیر استفاده شود و برای بهتر شدن آن کار شود.

http://github.com/ruohoruotsi/LSTM-Music-Genre-Classification

(دیتاست 6 کلاسه را کامل شد و بر روی شبکه آن کار شد)

برای تعیین ژانر موسیقی همانطور که در بقیه قسمت های مربوط به موسیقی در شبکه های عمیق مانند music generation مطرح است باید ویژگی های آن موسیقی را ابتدا استخراج کرد. که در اینجا از کتابخانه librosa برای این کار استفاده شده است.

ویژگی های استخراج شده شامل MFCC مربوط به طیف صدا و Spectral Centroid مربوط به مرکز طیف صداو CHROMA مربوط به اطلاعات اکتاو ها و نت های موسیقی و Spectral Contrast مربوط به کنتراست طیفی مبتنی بر اکتاو  است.

در این سمت از دو لایه LSTM برای آموزش مدل استفاده شده است که با افزایش این تعداد لایه به accuracy پایین تر بر روی دیتا ها رسیدیم و حتی سعی کردیم از شبکه کانوولوشنالی هم قبل از لایه های lstm استفاده کنیم اما نتیجه ی بهتری نگرفتیم.

در نهایت accuracy ما بر روی این داده های validation به 75% رسید اما تشخیص درستی در پی نداشت.

منابع

http://github.com/ruohoruotsi/LSTM-Music-Genre-Classification

https://git.litislab.fr/TextRecognition/CTCModel/tree/master

 

 

اعضای گروه : معصومه سلیمیان – آرزو یوسفی

music generation

اطلاعات کلی درباره موسیقی:

موسیقی چیست؟ به طور خلاصه موسیقی چیزی جز یک دنباله از نت های موسیقی نیست. ورودی ما به مدل، مجموعه ای از رویدادهای موسیقی / نت ها است.

تصویر بالا نمایشی از موسیقی است که به عنوان sheet شناخته می شود. در اینجا، موسیقی توسط یک دنباله از نت های موسیقی نشان داده شده است. هر نتموسیقی با یک spaceجدا شده است.

ABC Notation

نوع دیگر نت، با استفاده از abc است.که درواقع این نوع نت گذاری شامل دو بخش است:

بخش اول:

نشان دهنده meta data است.شامل:

x: نشان دهنده تعداد بخش های مختلف از لحاظ صدا در موسیقی است

T: عنوان آهنگ

M: علامت سری زمانی نواختن(time signiture)

L: طول زمانی پیش فرض نت ها

R: ژانر موسیقی

K: سر کلید

بخش دوم:

شامل نت ها به صورت abc است.

برای مثال در کلید sol:

a=la

b=si

c=do

d=re

e=mi

f=fa

g=sol

MIDI (Musical Instrument Digital Interface)

midi درواقع خودش صدا تولید نمیکند بلکه شامل یک سری از پیام ها مانند“note on,” “note off,” “note/pitch,” “pitch-bend,… است. این پیام ها توسط ابزار midi که ممکن است سخت افزاری و یا نرم افزاری باشد تفسیر می شوند.

تصویر بالا  یک موسیقی تولید شده با استفاده از Music21 که یک کتابخانه پایتون است که موسیقی فرمت MIDI تولید می کند را نشان می دهد.(درباره کتابخانه جلوتر توضیح داده شده است)

Event1: نت B را نشان میدهد.

Event2: آکورد E,A

Music generation

از آنجایی که Rnn خالی نمی تواند موسیقی قشنگی بنوازد ، ما نیاز به کلی preprocessing و postprocessing داریم.

Preprocessing: برای آنکه نت ها را دربیاورد

Postprocessing: شامل یک سری قوانین در علم موسیقی است مثل اینکه دو تا نت ممکن است پشت هم نتوانند بیایند،اما مدل rnn این دو نت را پشت هم قرار داده است.

از کتابخانه پایتونی music21 استفاده میکنیم که یک رابط ساده برای به دست آوردن نت های موسیقی فایل های MIDI را فراهم می کند. علاوه بر این، مابه اجازه می دهد که Note و Chord را ایجاد کنیم تا بتوانیم فایل های MIDI خودمان را به راحتی ایجاد کنیم. درواقع میتوان گفت یک language model است که به جای متن، نت های موسیقی را میگیرد و آن طرف هم به جای نت موسیقی تبدیل میکند به موسیقی. و درواقع یک مدل many to many  است.

shape of x بیانگر آن است که 60 تا sample داریم و 30 تا time step و 78 تا نت موسیقیایی مختلف توانسته استخراج کند.

مقدار y درواقع برعکس مقدار x می باشد که این به این دلیل است که ضرب و تقسیم های lstm به این صورت راحت تر بوده است. حالا درواقع مقدار 30 در y بیانگر time step و 60 نمایانگر mini batch می باشد.

N_values بیانگر تعداد نت های منحصر به فرد و indices_values درواقع شامل تبدیل آن 78  نت منحصر به فرد به زبان خاص خود کتابخانه است.

77: ‘S,0.250,<dd5,d1>’

شبکه:

یک one-hot 78 تایی می دهد که این one – hot در هر  time step  به یک  lstm می رود که این lstm درواقع یک softmax است. و یک a هم داریم که به hidden state ها وارد می شود و در هر time step  مقدار خروجی a(مقدار آپدیت شده)را به lstm بعدی می دهد.

ساختن model:

در این قسمت یک مدل می سازیم و train می کنیم که درواقع pattern های موسیقی را یاد میگیرد. برای انجام این کار، نیاز به ساخت یک مدل داریم که شامل X (𝑚,𝑇𝑥,78) و Y (𝑇𝑦، 𝑚، 78) است.

از LSTM با 64 تا  hidden stateاستفاده میکنیم.

حال سه object می سازیم:

reshapor ، ابعاد را 1*78 میکند.یعنی درواقع یک بعد می خواد اضافه کند.

Densor، که در واقع همان activation های softmax ای است که در شکل مدل دیده میشود.

چون در کراس نمی توانیم به روش many to many ، ترین(train) کنیم که بعد یک کاراکتر یک کاراکتر از آن سمپل گیری کنیم.درواقع در زمان تست چون many اش رو نداریم خودمون توی زمان بازش میکنیم و train میکنیم. بنابراین آبجکت lstm رو برای یک time step می سازیم و برای تایم استپ مثلا 30 تایی یه فور روی آن میزنیم. در واقع به این صورت که در تایم استپ اول activation یا  hidden_layer لایه های قبل را برابرصفر قرار میدهیم و ورودی آن را میدهیم که activation یا hidden layer برای استپ بعد رو میدهد و ورودی بعدی یا hidden state قبلیا رو بهش میدیم و وردی یا hidden state  بعدی رو میده.

یک تابع lambda تعریف کرده که در کل lambda  یک تابع بی نام است .که درواقع در این مثال یک mini batch ای است در تعداد time step در feature vector هایی که دارد است. که درواقع وقتی مثلا  t برابر 7 است ،n*78 برگردانده می شود.و وقتی n*30*78 است یعنی تمام mini batch در تایم استپ 7   را برمیگرداند.

مدل:

آرگومان ها شامل:

Tx : تعداد time step های ورودی

n_a : تعداد hidden state های lstm

n_values: تعداد نت های منحصر به فرد

X را با ابعاد Tx در n_values تعریف میکنیم. برای آنکه ورودی many بسازیم.

Hidden state های LSTM را می سازیم.a0,c0

به اندازه time step های ورودی (Tx) فور میزنیم.

lambda ای که توضیح دادیم را تعریف میکنیم در زمان t که در واقع زمان t آن زمانی هست که الان هستیم.

x مربوط به همان time step را برداشته و reshape میکنیم کهdimention  هایی برابر با mimibatch*1*78 داشته باشیم.

در مرحله بعد LSTM_cell را با مقادیر x,a,c فراخوانی میکنیم.به این صورت که a و c در مرحله اول مقداری برابر با 0  دارند و در دفعه های بعد خروجی این قسمت است.

حال مقدار a خروجی را به densor که شامل activation function است میدهیم. و خروجی آن را در outputs،append میکنیم.

حال تابع model را با a0,c0,X و خروجی outputs فراخوانی میکنیم:

حال مدل را با ویژگی های زیر می سازیم و train  میکنیم:

m برابر با تعداد time step است.

 Generating music

در generation، شبکه Lstm داریم که در واقع یک hidden state به آن پاس داده و یک رندم و یا صفر هم به عنوان ورودی به آن میدهیم، که در نتیجه آن یک softmax هفتاد هشت تایی داریم که index ماکسیمم را برداشته و یک one-hot هفتاد و هشت تایی دیگر درست کرده و آن را به عنوان ورودی به lstm بعدی می دهیم. مانند language model

در هر مرحله از sampeling، به عنوان ورودی activation  a و cell state c را از LSTM حالت قبلی ، به صورت مرحله به مرحله ارسال می شود و یک activation  خروجی جدید و همچنین cell state جدید دریافت می شود.

LSTM_cell,densor,n_values,n_a  را که قبلا تعریف کردیم که هرکدام چه هستند اما Ty بیانگر time step موزیک خروجی می باشد.

x0,a0,c0 را مانند قبل تعریف میکنیم و مقدار اولیه آنها را میتوان یا صفر گذاشت یا چند تا نت به عنوان ورودی به ان پاس داد.

به اندازه ty، فور میزنیم.که این ty درواقع می تواند مقدارهای بالاتر از مقداری که برای train داده ایم هم باشد.

در این قسمت x,a,c را به LSTM_cell میدهیم و مانند قبل a تولید شده را به densor میدهیم و خروجی آن را به outputs،append میکنیم و همچنین خروجی را به تابع one_hot میدهیم و خروجی را در x میریزیم.

تابع one_hot در music_utils تعریف شده است.

که درواقع 78  تا prediction میگیرد و argmax میزند و ایندکس بزرگترین prediction را میگیرد و دوباره one_hot 78 تایی  از آن می سازد و برای آن که dimention آن به dimention مدل جور در بیاد RepeatVector  روی آن میزنیم.

سپس inference_model  را با ورودی ها و خروجی ها میسازیم:

در مرحله بعد سه تا بردار صفر ساخته:

تابع زیر را صدا میزنیم که سه بردار بالا و inference_model را به عنوان آرگومان به آن پاس میدهیم.

تابع generate_music را بر روی inference_model صدا میزنیم.

Corpus: مجموعه 193 تا صدا به صورت

‘C,0.333,<P1,d-5>’

            abstract_grammars: لیست از grammer ها مانند:

‘S,0.250,<m2,P-4> C,0.250,<P4,m-2> A,0.250,<P4,m-2>’

            Tones:مجموعه ای صداهای منحصر به فرد:

‘A,0.250,<M2,d-4>’

            tones_indices: دیکشنری بین تن های منحصر به فرد از 0 تا 77

indices_tones: برعکس tones_indices

chord:درواقع مجموعه ای از نت ها می باشد. که برای پیانو 18 تا chord مختلف داریم.

یک حلقه روی 18تا که در هر بار یک sequence صدا تولید میکند.

یک curr_chords می سازیم تا روی آن تغییرات ایجاد کرده و آن را به موزیک تبدیل میکنیم.

اضافه کردن آکورد به آکورد فعلی با آفست مناسب

حال تابع predict_and_sample  را روی inference_model صدا میزنیم تا یک sequence از صداهای مختلف ایجاد کنیم.

حال به جای A و X ، نت C را جایگذاری میکنیم.

ساده سازی و سلیس کردن

با استفاده از predicted_tones, curr_chords صدا تولید میکنیم و صداهای یکسان و نزدیک به هم را حذف میکنیم و out_stream را ساخته و روی my_music.midi صدا را ذخیره میکنیم.

 

تشخیص چهره کلاسیک و جدید(deeplearning)

Face verification: همانطور که قبلا توضیح داده شد این الگوریتم می گوید این دو نفر یکی هستند یا خیر.

Face identification: این الگوریتم می گوید این دو نفر یکی هستند.

مراحل شناختی برای face identification : (برای مشاهده گیف مربوطه به http://www.iamwire.com/2017/03/modern-face-recognition-deep-learning/149697 مراجعه شود.)

  1. در ابتدا باید face تشخیص داده شود و سپس آن را crop می کنیم.
  2. در این مرحله alignment روی face انجام می شود.
  3. Embedding تصویر alignment شده مرحله قبل را درمی آوریم.
  4. مقایسه برای شناخت شخص

طبق گفته های Andrew NG برای face detection  باید حتما مراحل detection و crop چهره را انجام بدهیم تا performance خوبی داشته باشیم.

Alignment: در مقاله 2014 گروه آکسفورد برای انجام alignment یک پروسس بسیار پیچیده انجام می دادند که در این پروسس از تصویر داده شده یک مدل سه بعدی در می آورد و سپس این مدل سه بعدی را frontal می کرد و به انجام همه این عملیات alignment می گفت. اما در مقالات بعدی از alignment های ساده تری استفاده شد؛ برای مثال facenet تنها چهره را کراپ می کرد و آن را وسط صفحه می انداخت. اما با توجه به تجارب بدست آمده، مشخص شده که پروسس های پیچیده برای alignment  نه تنها performance را بهتر نمی کند بله گاهی وقتا بدتر هم می کند.

در ادامه می خواهیم بررسی کنیم که چطور می توانface  را detect کرد. در ابتدا یک روش کلاسیک را بررسی خواهیم کرد.

روش HAAR Cascade : در بسیاری از device هایی که face  را detect می کند و عکس می گیرد از این روش استفاده می شود که روشی بسیار سریع است و برای آن از opencv  کلاسیک استفاده شده است.

در این روش یک سری feature استخراج می شود که می توانند Binary Classification انجام دهند. درنهایت به وسیله نتایج همه آن ها detection انجام می شود.

در واقع با HARR Cascade مثلا می توان دریافت که این تصویر چشم هست یا خیر.

Haar features:

Feature های پایه در haar features شامل مواردی است که در تصویر بالا سمت راست دیده می شود. که همان طور که در عکس های سمت چپ می بینید یک لبه یا یک خط را detect می کنند. در واقع چیزی که از تصویر بالا برداشت می شود این است که اگر بخواهیم چشم را detect کنیم احتمالا feature ای که در تصویر دوم مشاهده می کنید به کار می آید و اگر بخواهیم بینی را detect کنیم (با توجه به سایه روشن های روی بینی) احتمالا feature ای که در تصویر سوم مشاهده می شود به کار می آید.

برای استفاده از این feature ها هر کدام ها را با تمام سایز های مختلف را روی عکس حرکت می دهند.

دیتاست این classification دارای دو کلاس face و nonface است و عکس را در سایز 24*24 در نظر می گیرد. در مجموع 180000 feature برای این کار generate کرده است و چون اگر بخواهد از تمام این feature ها در قسمت های مختلف تصویر استفاده کند overload محاسباتی اش زیاد می شود، از تکنیکی به نامintegral image استفاده کرده است و بسیاری از محاسبات تکراری را حذف کرده است.

یک سری ازfeature ها مربوط هستند و یک سری دیگر نامربوط؛ مثلاfeature  هایی که روی face نیفتاده باشند نامربوط هستند.

چون feature هایی که پیدا کرده بودند بسیار زیاد بود(180000)  در مقاله ای دیگر به نام adaBoost آمده اند feature های مهم تر را استخراج کرده اند که حدود 6000 تا بودند. برای این کار feature ها را بر اساس اهمیت و کارایی شان مرتب کرده اند. در ابتدا مهم ترین feature را روی عکس انداختند و اگر این feature هدف را پیدا نمی کرد بقیه feature ها بررسی نمی شدند. برای مثال اگر مهم ترین feature بینی را تشخیص می داد و بینی ای در تصویر پیدا نمی کرد، نتیجه می گرفتند چهره ای وجود ندارد. اما اگر بینی پیدا می شد وارد گام بعدی Cascade می شد. در گام بعدی تعداد feature هایی که باید بررسی شوند بیشتر می شود.

مراحل استفاده بعد از training:

  1. لود یک classifier
  2. یک عکس لود کرده و به این classifier می دهیم.
  3. اگر چهره ای تشخیص داده شد موقعیت چهره و طول و عرض آن را پیدا میکند.
  4. مستطیل را برای آن موقعیت رسم می کند

برای پیدا کردن HaarCascade ها کافیست HaarCascade opencv را سرچ کرده و به گیت هاب opencv بروید (https://github.com/opencv/opencv/tree/master/data/haarcascades ) در آن جا یک سری xml وجود دارد که انواع مختلف HaarCascade ها برای عملیات گوناگون در آن وجود دارد. با دانلود هرکدام می توان از آن در پروژه استفاده کرد.

در این درس از HaarCascade_frontalface و HaarCascade_eye استفاده شده است و در کنار کد این فایل های را قرار می دهیم.

از cv2.CascadeClassifier برای لود classifier دانلود شده استفاده می شود. در واقع در این قسمت می گوید که classifier بر اساس چه ویژگی هایی ساخته شود. در این مثال که frontalface به آن پاس داده شده است classifier چهره ساخته شده است که اسمش را face_classifier گذاشته ایم.

از RGB2Gray بر روی عکس استفاده می کنیم و عکس را grayscale می کنیم زیرا opencv بیشتر از توابعی استفاده می کند که روی تصاویر grayscale کار می کنند.

در این قسمت از تابع detectMultiScale استفاده شده است؛ چون می خواهیم با scale های مختلف detect کنیم. برای این کار opencv عکس را چند بار resize می کند تا بتواند چهره را تشخیص بدهد و بعد از detect شدن نسبت این عکس به عکس اصلی را پیدا می کند تا موقعیت دقیق چهره را بگوید. در واقع این تابع با یک فاکتوری pyramid درست می کند.

Faces لیستی از لیست هاست که درواقع x, y, w, h چهره های detect شده را در خود دارد.

Scale factor: دومین پارامتر تابع detectMultiScale است که می گوید با چه فاکتوری عکس را resize کند؛ به عنوان مثال وقتی این پارامتر را برابر 1.3 قرار می دهیم یعنی هربار 30 درصد عکس بزرگ تر شود.

Min Neighbors: سومین پارامتر تابع detectMultiScale است که می گوید تا چه حد Neighbor بودن مجاز باشد که معمولا بین 3 تا 6 قرار می دهیم. اگر این مقدار خیلی پایین باشد ممکن است با این مواجه شویم که برای یک چهره دو bounding box در نظر گرفته است و اگر این مقدار خیلی بالا باشد ممکن است چهره را تشخیص ندهد.

حال می خواهیم  علاوه بر چهره، چشم را هم detect کنیم پس باید علاوه بر HaarCascade_frontalface، HaarCascade_eye  را هم لود کنیم.

برای پیدا کردن eye باید اول یک چهره detect شود و در ناحیه چهره باید به دنبال eye باشیم. پس در یک حلقه for ناحیه چهره را به دو صورت رنگی و grayscale (به جهت این که الگوریتم های classifier روی عکس های grayscale بهتر جواب می دهد) جدا می کنیم.

سپس دوباره detectMultiScale را این بار روی چهره کراپ شده صدا می زنیم تا چشم ها را detect کنیم.

سپس با ایجاد for جدید از eye های detect شده و داشتن موقعیت آن ها یک مستطیل روی آنها می کشیم، قاعدتا به ازای هر face دوبار for داخل اجرا می شود.

حال می خواهیم عملیات detect چهره و چشم را به صورت live با camscanner انجام دهیم.

الگوریتم مشابه الگوریتم های قبل عمل می کند. چهره ها را پیدا می کنیم و x,y,w,h را کمی تغییر می دهیم تا چهره به صورت کامل کراپ شود. چهره را کراپ کراپ کرده و کراپ شده را نشان می دهیم.

با توجه به نمودارهای زیر که درواقع الگوریتم هایline  face (چیزهای ساده ای که قبلا به عنوان بدیهیات در نظر گرفته می شد یعنی تقریبا همه می توانستند از ان استفاده کنند مانند haarCascade ) را نشان می دهد که vj در آن همان HaarCasscade می باشد. در این نمودارها به جای آن که نمودار performance کشیده شود، نمودار roc curve کشیده شده است که درواقع roc curve به ازای recall های مختلف persision  های مختلف را می کشد.  recall در واقع تعداد face ها از مجموع همه ی چهره ها را می گوید. (به بیان دیگز چندتا از چهره ها را توانست تشخیص دهد) و persision صحت چهره بودن برایش مهم است. (به عبارتی در persision مهم نیست چند تا از چهره ها تشخیص داده شده است این مهم است که با چه اطمینانی این چهره واقعا چهره است.)

در نمودارهای زیر درواقع هرچه سطح زیر نمودار بیشتر باشد بهتر است.

Multitask-Cascade-CNN از جمله مقاله های submit شده است که کد آن توسط خود نویسنده منتشر شده و افراد دیگر در قالب های تنسورفلویی آن را پیاده سازی کرده اند به همین دلیل ما به بررسی این الگوریتم می پردازیم.

مشکل convolutional neural network این است که اگر بخواهیم فیلتر ها را روی عکس جابه جا کنیم تا چهره را تشخیص بدهیم، تعداد حالت ها زیاد است و deep learning بسیار سنگین است. به همین خاطر ایده های زیادی استفاده شد تا این مشکل حل شود. از جمله این ایده ها این بود که به جای آن که  در تمام نقاط تصویرdetection  بزنیم تنها در جاهایی که ممکن است  چهره باشد بزنیم. می توان threshold الگوریتم Haarcasscade را پایین آورد تا تمام چهره ها را تشخیص دهد (recall را بالا ببریم و اگر precision پایین هم آمد مهم نیست) حالا این چهره های detect شده را اگر به شبکه کانوولووشنالی بدهیم معقول تر است. این ایده ها مربوط به سالهای 2014 و 2016  می باشد.

در سال 2016  تمام مراحل را deep learning کردند به این صورت که در گام اول که resize می باشد یک pyramid تشکیل می دهد. در گام بعدی از شبکه p-Net (proposal network)که یک شبکه کانوولوشنالی فوق العاده سبک است استفاده می شود که فقط نقاط احتمال چهره را در می آورد (علاوه بر چهره ممکن است چیز های نامربوط دیگر را هم درآورد).

در گام بعدی نتایج حاصله از مرحله قبل را کراپ کرده و به شبکه R-Net (Refinement Network) که در این شبکه هم مکان های bounding box ها را تنظیم کرده و هم بعضی از bounding box ها را حذف می کند.

در گام بعد این بار می خواهیم precision را بالا ببریم پس خروجی R-net را به شبکه O-Net(output Network) می دهیم و از بین آنها انتخاب می کند و landmark های آنها را هم می کشد.

Lossهای شبکه ها:

یک loss این شبکه ها crossentropy دو کلاسه هست  که مسئله باینری face-nonface را پوشش می دهد:

Loss box:

Loss box ها که یک مسئله regression است، در واقع فاصله تخمین تا حقیقت را محاسبه می کند که آیا مکان bounding box درست است یا خیر:

Loss landmarks: که باز هم مسئله regression است:

Loss کل شبکه که ترکیبی از هر سه loss می باشد.

درون کد اگر بخواهیم بررسی کنیم (mtcnn-test.py)

مقدار اول hyper parameter شبکه اول(p-net)

مقدار دوم hyper parameter شبکه دوم(R-net)

مقدار سوم hyper parameter شبکه سوم(O-net)

توسط detect_face.create_mtcnn سه شبکه pnet و rnet و onet را می سازیم.

یک clone از عکس های موجود در image_path می گیریم.

متد detect_face از detect_face را صدا میزنیم تا bounding box  و landmark ها را به عنوان خروجی بدهند.

که درواقع bounding box لیستی از چهارتایی های x,y,w,h و points لیستی از x,y های 5 تا  landmark داخل هر چهره است.