{"id":12304,"date":"2021-05-24T09:00:48","date_gmt":"2021-05-24T13:00:48","guid":{"rendered":"https:\/\/blogs.mathworks.com\/pick\/?p=12304"},"modified":"2021-05-24T09:21:58","modified_gmt":"2021-05-24T13:21:58","slug":"face-detection-with-deep-learning","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/pick\/2021\/05\/24\/face-detection-with-deep-learning\/","title":{"rendered":"Face Detection with Deep Learning"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p><a href=\"http:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/911\">Brett<\/a>'s Pick this week is <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/73947-mtcnn-face-detection\"><tt>MTCNN Face Detection<\/tt><\/a>, by <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/10732621\">Justin Pinkney<\/a>, a MathWorks colleague from our Consulting Department.<\/p><!--\/introduction--><p>We have provided the functionality to detect faces using MathWorks' tools since 2012. Our face detectors, which live in the <a href=\"https:\/\/www.mathworks.com\/products\/computer-vision.html\">Computer Vision Toolbox<\/a>, rely on the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Viola%E2%80%93Jones_object_detection_framework\">Viola-Jones algorithm<\/a>, and are very easy to implement:<\/p><pre class=\"language-matlab\">img = imread(<span class=\"string\">'visionteam.jpg'<\/span>);\r\nimshow(img)\r\nfaceDetector = vision.CascadeObjectDetector();\r\nbboxes = step(faceDetector, img);\r\nfigure\r\nimshow(img)\r\ntitle(<span class=\"string\">'Face Detection using the Cascade Object Detector'<\/span>)\r\n<span class=\"keyword\">for<\/span> ii = 1:size(bboxes, 1)\r\n    drawrectangle(<span class=\"string\">'Position'<\/span>, bboxes(ii, :), <span class=\"string\">'facealpha'<\/span>, 0);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/VisonTeamDetected.png\" alt=\"\"> <\/p><p>The default model for the (tunable) cascade object detector uses classification and regression tree analysis (CART) of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Haar-like_feature\">\"Haar-like\" features<\/a>. As you can see above, the models often work quite well. Additionally, you can engage a 'FrontalFaceLBP' model to detect faces using <a href=\"https:\/\/en.wikipedia.org\/wiki\/Local_binary_patterns\">\"Local Binary Patterns.\"<\/a> Both models work well for the image above, to detect faces that are upright and forward facing.<\/p><p>There are other detection models you can invoke with the CascadeObjectDetector, including 'UpperBody', 'EyePair' (big and small), 'LeftEye' and 'RightEye' (two options), 'ProfileFace', 'Mouth', and 'Nose'. (In addition, you can readily <a href=\"https:\/\/www.mathworks.com\/help\/vision\/ref\/traincascadeobjectdetector.html\">train your own!<\/a>)<\/p><p>Which brings me to today's Pick.<\/p><p>Justin's submission implements <a href=\"https:\/\/arxiv.org\/abs\/1604.02878\">\"Multi-task Cascaded Convolutional Networks\" (MTCCN)<\/a> to solve the face detection problem. Having options is good; the built-in models don't <i>always<\/i> work well:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/WCDetected.png\" alt=\"\"> <\/p><p>Note the large number of false positives, in both instances.<\/p><p>In contrast, the MTCCN model works remarkably well on this image:<\/p><pre class=\"language-matlab\">[bboxes, scores, landmarks] = mtcnn.detectFaces(img);\r\nfigure\r\nimshow(img)\r\ntitle(<span class=\"string\">'MTCNN'<\/span>)\r\n<span class=\"keyword\">for<\/span> ii = 1:size(bboxes, 1)\r\n    drawrectangle(<span class=\"string\">'Position'<\/span>, bboxes(ii, :), <span class=\"string\">'facealpha'<\/span>, 0);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/WCDetected2.png\" alt=\"\"> <\/p><p>Another thing I appreciate is that facial landmarks are provided automatically as outputs of the MTCNN Model:<\/p><pre class=\"language-matlab\">hold <span class=\"string\">on<\/span>\r\nxs = landmarks(:, :, 1);\r\nys = landmarks(:, :, 2);\r\n<span class=\"keyword\">for<\/span> ii = 1:size(xs, 1)\r\n    <span class=\"keyword\">for<\/span> jj = 1:size(xs, 2)\r\n        plot(xs(ii, jj), ys(ii, jj), <span class=\"string\">'r.'<\/span>)\r\n    <span class=\"keyword\">end<\/span>\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/WCDetected2WithDots.png\" alt=\"\"> <\/p><p>The MTCNN model also appears to be fairly robust; it even works on the 'cameraman' image, despite the fact that the face in the image is clearly not forward facing. (Both vision.CascadeObjectDetector face detectors fail on the image, at least with default parameterizations.)<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/CameramanDetected.png\" alt=\"\"> <\/p><p>I should also note that whereas the built-in Toolbox functions can adapt to RGB or grayscale images, the MTCNN detector operates on only on RGB images. But that's an easy problem to address:<\/p><pre class=\"language-matlab\"><span class=\"keyword\">if<\/span> size(img, 3) == 1\r\n    img = repmat(img, [1 1 3]);\r\n<span class=\"keyword\">end<\/span>\r\n<\/pre><p>Thanks, Justin! This is a nice addition to our detection tools!<\/p><p>As always, I welcome your <a href=\"http:\/\/blogs.mathworks.com\/pick\/?p=12304#respond\">thoughts and comments<\/a>.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_7569373407ed4bb3a92851d4050242f7() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='7569373407ed4bb3a92851d4050242f7 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 7569373407ed4bb3a92851d4050242f7';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2021 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_7569373407ed4bb3a92851d4050242f7()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2021a<br><\/p><\/div><!--\r\n7569373407ed4bb3a92851d4050242f7 ##### SOURCE BEGIN #####\r\n%% Face Detection with Deep Learning\r\n%\r\n% <http:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/911 Brett>'s\r\n% Pick this week is\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/73947-mtcnn-face-detection |MTCNN Face Detection|>,\r\n% by <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/10732621 Justin Pinkney>, \r\n% a MathWorks colleague from our Consulting Department.\r\n\r\n%%\r\n% We have provided the functionality to detect faces using MathWorks' tools\r\n% since 2012. Our face detectors, which live in the <https:\/\/www.mathworks.com\/products\/computer-vision.html Computer Vision\r\n% Toolbox>, rely on the\r\n% <https:\/\/en.wikipedia.org\/wiki\/Viola%E2%80%93Jones_object_detection_framework\r\n% Viola-Jones algorithm>, and are very easy to implement:\r\n\r\n%%\r\n% \r\n%   img = imread('visionteam.jpg');\r\n%   imshow(img)\r\n%   faceDetector = vision.CascadeObjectDetector();\r\n%   bboxes = step(faceDetector, img);\r\n%   figure\r\n%   imshow(img)\r\n%   title('Face Detection using the Cascade Object Detector')\r\n%   for ii = 1:size(bboxes, 1)\r\n%       drawrectangle('Position', bboxes(ii, :), 'facealpha', 0);\r\n%   end\r\n\r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/VisonTeamDetected.png>>\r\n% \r\n\r\n%%\r\n% The default model for the (tunable) cascade object detector uses\r\n% classification and regression tree analysis (CART) of\r\n% <https:\/\/en.wikipedia.org\/wiki\/Haar-like_feature \"Haar-like\" features>.\r\n% As you can see above, the models often work quite well. Additionally, you\r\n% can engage a 'FrontalFaceLBP' model to detect faces using\r\n% <https:\/\/en.wikipedia.org\/wiki\/Local_binary_patterns \"Local Binary Patterns.\"> \r\n% Both models work well for the image above, to detect faces\r\n% that are upright and forward facing.\r\n%\r\n% There are other detection models you can invoke with the CascadeObjectDetector, including \r\n% 'UpperBody', 'EyePair' (big and small), 'LeftEye' and 'RightEye' (two options), 'ProfileFace', \r\n% 'Mouth', and 'Nose'. (In addition, you can readily <https:\/\/www.mathworks.com\/help\/vision\/ref\/traincascadeobjectdetector.html train your own!>)\r\n%\r\n%% \r\n% Which brings me to today's Pick. \r\n%\r\n% Justin's submission implements\r\n% <https:\/\/arxiv.org\/abs\/1604.02878 \"Multi-task Cascaded Convolutional Networks\" (MTCCN)> \r\n% to solve the face detection problem. Having options is good; the built-in\r\n% models don't _always_ work well: \r\n%%\r\n% \r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/WCDetected.png>>\r\n% \r\n%%\r\n% Note the large number of false positives, in both instances. \r\n\r\n%% \r\n% In contrast, the MTCCN model works remarkably well on this image:\r\n\r\n%%\r\n% \r\n%   [bboxes, scores, landmarks] = mtcnn.detectFaces(img);\r\n%   figure\r\n%   imshow(img)\r\n%   title('MTCNN')\r\n%   for ii = 1:size(bboxes, 1)\r\n%       drawrectangle('Position', bboxes(ii, :), 'facealpha', 0);\r\n%   end\r\n\r\n%%\r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/WCDetected2.png>>\r\n\r\n%%\r\n% Another thing I appreciate is that facial landmarks are provided\r\n% automatically as outputs of the MTCNN Model:\r\n\r\n%%\r\n% \r\n%   hold on\r\n%   xs = landmarks(:, :, 1);\r\n%   ys = landmarks(:, :, 2);\r\n%   for ii = 1:size(xs, 1)\r\n%       for jj = 1:size(xs, 2)\r\n%           plot(xs(ii, jj), ys(ii, jj), 'r.')\r\n%       end\r\n%   end\r\n\r\n%%\r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/WCDetected2WithDots.png>>\r\n\r\n%%\r\n% The MTCNN model also appears to be fairly robust; it even works on the\r\n% 'cameraman' image, despite the fact that the face in the image is clearly\r\n% not forward facing. (Both vision.CascadeObjectDetector face detectors\r\n% fail on the image, at least with default parameterizations.)\r\n\r\n%%\r\n% <<https:\/\/blogs.mathworks.com\/pick\/files\/CameramanDetected.png>>\r\n\r\n%%\r\n% I should also note that whereas the built-in Toolbox functions can adapt\r\n% to RGB or grayscale images, the MTCNN detector operates on only on RGB\r\n% images. But that's an easy problem to address:\r\n\r\n%%\r\n% \r\n%   if size(img, 3) == 1\r\n%       img = repmat(img, [1 1 3]);\r\n%   end\r\n\r\n%% \r\n% Thanks, Justin! This is a nice addition to our detection tools!\r\n\r\n%%\r\n% As always, I welcome your <http:\/\/blogs.mathworks.com\/pick\/?p=12304#respond\r\n% thoughts and comments>.\r\n##### SOURCE END ##### 7569373407ed4bb3a92851d4050242f7\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/pick\/files\/VisonTeamDetected.png\" onError=\"this.style.display ='none';\" \/><\/div><p>Brett's Pick this week is MTCNN Face Detection, by Justin Pinkney, a MathWorks colleague from our Consulting Department.We have provided the functionality to detect faces using MathWorks' tools since... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/pick\/2021\/05\/24\/face-detection-with-deep-learning\/\">read more >><\/a><\/p>","protected":false},"author":34,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/12304"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/users\/34"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/comments?post=12304"}],"version-history":[{"count":2,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/12304\/revisions"}],"predecessor-version":[{"id":12318,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/12304\/revisions\/12318"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/media?parent=12304"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/categories?post=12304"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/tags?post=12304"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}