2019年7月4日木曜日

人物のシルエット画像を作る

万引きシーンや暴力シーンってどうやって検出するんだろね。
いろいろ調べてみると大体以下の流れのよう。

https://www.ieice.org/publications/conference-FIT-DVDs/FIT2015/data/pdf/H-021.pdf

1.HOGで人物のエリアを特定
2.シルエット画像を作る。
3.シルエット画像からHLACなどの特徴量を計算
4.特徴量をSVMで学習させる。

前回のブログで3は書きました。昔ブログで1も書いた気がするので、本日は2です。

おじさん、研究者や教授でもないのに。なんで夜中に論文読まないといけないんだ。
最近論文を読むとすらすら一発で動くコードが書けるようになってきました。
なんか危ない。

いろいろな論文で、歩行特徴とか行動特徴を計算するためにはシルエット画像がある前提になっています。AIや画像処理の分野っていろいろ分業されてるのね。

HOGで簡単にシルエットできるみたいに書いてありますが、結構調べたけどHOGでは人物のエリアを特定できるだけで二値化してもきれいなシルエット画像なんて作れねーよ。
ということで本日はどうやってシルエット作成を作るのか実験します。

いろいろ調べると背景差分法というのがあるらしい。
人間は動くので、動画の差分からシルエットを作れるっぽいですね。
http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_video/py_bg_subtraction/py_bg_subtraction.html
http://kimamani89.com/2019/04/30/post-420/

なるほど。だけど気に入らない。
おじさんの嫌いなPythonじゃないか。

C言語に書き直します。
------------------------
#include <stdio.h>
#include <vector>

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION

#include "core.hpp"
#include "imgproc.hpp"
#include "imgproc_c.h"

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


using namespace std;


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;
int n, m;
int i;

//load image
p = stbi_load("haikei1.jpg", &x, &y, &n, 4);
if (p == NULL || x < 1 || y < 1)return 1;
changeb_g(p, x, y, 4);
cv::Mat color1 = cv::Mat(y, x, CV_8UC4);
cv::Mat gray1;
memcpy(color1.data, p, x * 4 * y);
stbi_image_free(p);
cv::cvtColor(color1, gray1, CV_BGR2GRAY);

p = stbi_load("haikei2.jpg", &x, &y, &n, 4);
if (p == NULL || x < 1 || y < 1)return 1;
changeb_g(p, x, y, 4);
cv::Mat color2 = cv::Mat(y, x, CV_8UC4);
cv::Mat gray2;
memcpy(color2.data, p, x * 4 * y);
stbi_image_free(p);
cv::cvtColor(color2, gray2, CV_BGR2GRAY);

p = stbi_load("haikei3.jpg", &x, &y, &n, 4);
if (p == NULL || x < 1 || y < 1)return 1;
changeb_g(p, x, y, 4);
cv::Mat color3 = cv::Mat(y, x, CV_8UC4);
cv::Mat gray3;
memcpy(color3.data, p, x * 4 * y);
stbi_image_free(p);
cv::cvtColor(color3, gray3, CV_BGR2GRAY);

if (color1.cols != color2.cols || color1.rows != color2.rows) {
return 1;
}
if (color1.cols != color3.cols || color1.rows != color3.rows) {
return 1;
}

char th = 20;

cv::Mat diff1;
cv::Mat dst1;
cv::absdiff(gray1, gray2, diff1);
cv::threshold(diff1, dst1, th, 255, cv::THRESH_BINARY);

cv::Mat diff2;
cv::Mat dst2;
cv::absdiff(gray2, gray3, diff2);
cv::threshold(diff2, dst2, th, 255, cv::THRESH_BINARY);

cv::Mat dst;
cv::add(dst1, dst2, dst);
cv::medianBlur(dst, dst, 5);

cv::Mat color;
cv::cvtColor(dst, color, CV_GRAY2RGBA);
stbi_write_png("result.png", x, y, 4, color.data, 4 * x);

return 0;
}
------------------------

人物のシルエット作成の分野って交差点を歩いている人の画像で実験するのね。
ffpmegでaviファイルから以下の三枚の画像を切り出します。



 2フレームだけの差分だとなかなかきれいなシルエットが作れません。
だから3フレームで差分の和を取るのね。

この点点点点ってノイズどうすればいいのでしょう。
なんかゴマ塩ノイズっていうらしい。
調べるとメディアンフィルターを通さないといけないっぽい。


なんかそれっぽくなってきた。
でもまだまだシルエットをきれいに作れないじゃないか。
このシルエットでHLAC計算して本当にSVMで学習させれば行動認識とか万引き検出できるんだろうか?
続く。


0 件のコメント:

コメントを投稿