2020年6月12日金曜日

マスク着用を判定する。

おじさんの会社では、入り口のゲートのところにカメラが置いてあって、マスクをしているかチェックされます。
間違ってマスクを会社に置いたまま外に出ると、二度と社内に入れなくなります。

AIがマスク着用判定、注意も 東大発ベンチャーがシステム開発
https://www.sankeibiz.jp/business/news/200317/bsc2003170500006-n1.htm

いいなぁ、東大生が作ると新聞に載るけど、おじさんが一時間くらいで作っても誰も褒めてくれない・・・。おじさんさみしい。

世の中にあるマスク着用判定プログラムは、いろいろなライブラリが必要で、なかなか軽量なものがない。
そこで、他のライブラリを必要としない単体で動くコンパクトなものを作ってみました。


まず、いつもの通り学習済みデータを取ってきます。

https://github.com/didi/maskdetection
ここのmodelのフォルダにある学習済みデータを取ってきます。
100Mバイトもある。
そう思っていたけど、ResNet50でできているのね。

次に、以前作った最小限のOpenCVもとってきます。
http://yomeiotani.blogspot.com/2019/07/pose-estimation.html

ソースコードはこんな感じ。
一時間くらいでサクッと作れます。
----------------------------------------------------
#include<stdio.h>
#include<string>
#include<vector>
#include<iostream>

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION


#include "opencv2_core.hpp"
#include "opencv2_imgproc.hpp"
#include "opencv2_imgproc_imgproc_c.h"
#include "opencv2_dnn.hpp"

#include "stb_image.h"
#include "stb_image_write.h"

void changeb_g(unsigned char* p, int x, int y, int c)
{
int ct = x*y;
int i;
unsigned char t;
for (i = 0; i < ct; i++) {
t = p[0];
p[0] = p[2];
p[2] = t;
p[3] = 255;
p += c;
}
}

int main()
{
unsigned char* p;
int x=-1, y=-1, n=-1;

// Specify the paths for the 2 files
std::string protoFile = "deploy.prototxt";
std::string weightsFile = "face_mask.caffemodel";


// Read the network into Memory
cv::dnn::Net net = cv::dnn::readNetFromCaffe(protoFile, weightsFile);

//
p = stbi_load("nomask5.jpg", &x, &y, &n, 4);
//p = stbi_load("mask5.jpg", &x, &y, &n, 4);
if (p == NULL || x < 1 || y < 1)return 1;
changeb_g(p, x, y, 4);
cv::Mat color = cv::Mat(y, x, CV_8UC4);
memcpy(color.data, p, x * 4 * y);
stbi_image_free(p);

cv::Mat img;
cv::cvtColor(color, img, CV_BGRA2BGR);
cv::resize(img, img, cv::Size(224, 224));

cv::Mat inpBlob = cv::dnn::blobFromImage(img, 1.0, cv::Size(224, 224), cv::Scalar(104, 117, 123));

// Set the prepared object as the input blob of the network
net.setInput(inpBlob);


cv::Mat output = net.forward();
std::cout << output<<std::endl;

float result = 0.0;
result = output.at<float>(0);

if (result > 0)printf("mask\n");
else printf("nomask\n");

return 0;
}

----------------------------------------------------

結果は以下の通り。
10枚くらいためしましたが全部正解。

----------------------------------------------------
Attempting to upgrade batch norm layers using deprecated params: face_mask.caffemodel
Successfully upgraded batch norm layers using deprecated params.
[-0.98020822]
nomask

Attempting to upgrade batch norm layers using deprecated params: face_mask.caffemodel
Successfully upgraded batch norm layers using deprecated params.
[1.4664154]
mask
----------------------------------------------------

なんだぁマスク装着判定ってこんな簡単に作れるのか。
これはいい商売になるねぇ。



0 件のコメント:

コメントを投稿