OpenCV で簡単な画像処理を体験する
前ページでOpenCV を用いた画像処理を試すための準備が整ったので、
本ページでいくつかの例を試してみよう。
本ページの例は全て、前ページで用いた ConsoleApplication1 に手を加えることで実現する。
ConsoleApplication1 は、
- デスクトップ上にある画像をimread関数により開き、
- 開いた画像をimgという名前の Mat 変数に格納し、
- imgをimshow関数により画面に表示
という流れを実現していた。
この流れに下記の処理を加えることで、画像のグレースケール化を実現してみよう。変更が必要な箇所が太字で書かれていることに注意。
- デスクトップ上にある画像をimread関数により開き、
- 開いた画像をimgという名前の Mat 変数に格納し、
- imgをグレースケール化してgrayという名前の Mat 変数に格納し
- grayをimshow関数により画面に表示
それを実現するのが下記のコードである。やはり、変更が必要な箇所のみ太字になっている。
const char* windowName = "Image";
cv::Mat img = cv::imread("C:\\Users\\student\\Desktop\\kogakuin.png");
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
cv::imshow(windowName, gray);
cv::waitKey(0);
変更が終ったら実行してみよう。グレースケール化された画像が表示されるはずである。
グレースケール化ができたら、今度は画像を白か黒かの二値で表す二値化を行ってみよう。
グレースケール化の続きとして実現するのならば、下記の太字の処理を追加する。
- デスクトップ上にある画像をimread関数により開き、
- 開いた画像をimgという名前の Mat 変数に格納し、
- imgをグレースケール化してgrayという名前の Mat 変数に格納し
- grayを二値化してbinaryという名前の Mat 変数に格納し
- binaryをimshow関数により画面に表示
それをコードで表すと下記のようになる。やはり、グレースケール化からの変更点を太字で表している。
const char* windowName = "Image";
cv::Mat img = cv::imread("C:\\Users\\student\\Desktop\\kogakuin.png");
cv::Mat gray;
cv::Mat binary;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
cv::threshold(gray, binary, 127, 255, cv::THRESH_BINARY);
cv::imshow(windowName, binary);
cv::waitKey(0);
このように、必要な処理を追加することで様々な画像処理を行うことができる。
最後に、Webカメラからの映像取得を行ってみよう。
ノートPCの場合、ディスプレイ上部にカメラがあることが多いので、そちらからの映像が取得される。
それにより、これまでと異なり、映像を静止画からではなくカメラからの動画として取得することになる。
必要なプログラムは下記のようになっている。これまで通り変更点のみを太字で表している。
「const char* windowName = "Image";」の行と「return(0);」の行の間が丸ごと差し替えられていることに注意。
const char* windowName = "Image";
cv::VideoCapture cap(0);
if(!cap.isOpened())//カメラデバイスが正常にオープンしたか確認.
{
return -1;
}
while (1)
{
cv::Mat img;
cap >> img;
// 必要に応じてここに画像処理
cv::imshow(windowName, img);//画像を表示.
int key = cv::waitKey(1);
if (key == 113)//qボタンが押されたとき
{
break;//whileループから抜ける.
}
}
cv::destroyAllWindows();
return(0);
なお、このプログラムでは、プログラム中にコメントが記されているように、
映像上でキーボードの「q」をタイプするとプログラムが終了するようになっている。
また、ここで下記の行の数字「0」はPCに取り付けられているカメラの番号になる。
cv::VideoCapture cap(0);
多くのノートPCの場合、「0」 はユーザー側を向いたフロントカメラを指す。
タブレットPCの場合、画面の裏にもリアカメラがあることが多く、その場合リアカメラは「1」となるだろう。
さらに、USB経由でWebカメラを接続した場合、その次の番号 (2) が割り当てられるだろう (リアカメラがない場合の USB 経由のカメラ番号は 1 のはずである)。
適切な番号を指定することで、用いたいカメラを利用すること。
ここまでの知識を用いて、下記の演習を行ってみよう。いずれも、本ページの知識のみで実現できる。
- Webカメラからの映像取得の例を変更し、グレースケール化された映像が表示されるようにせよ
- Webカメラからの映像取得の例を変更し、二値化された映像が表示されるようにせよ
ここまで長い解説を行い、皆さんに OpenCV を体験してもらった。
ここから先の内容を深めたければ、書籍などで自分で勉強する必要がある。
この際、下記の知識をあらかじめ知っておかないと混乱のもととなるであろう。
まず、OpenCV のバージョンにはバージョン2系とバージョン3系以降の複数あり、文法が異なることがある。
特に、バージョン2系とそれ以外の違いが大きいので注意しなければならない。
- OpenCV 2系
- OpenCV 3系以降 (本ページは 4.3.0 で解説)
さらに、プログラムの書き方として下記の2通りがある。
- C インタフェース (ただし、OpenCV 4 系以降では削除された)
- C++ インタフェース (本ページで解説)
画像のオープンの記法はCインターフェースとC++インタフェースとで下記のように全く異なる。
//Cインターフェース
IplImage* img = cvLoadImage("C:\\Users\\student\\Desktop\\kogakuin.png");
//C++インターフェース
cv::Mat img = cv::imread("C:\\Users\\student\\Desktop\\kogakuin.png");
皆さんがインターネットや書籍を調べる際、それが「OpenCV 2系の解説か OpenCV 3系以降の解説か」、
「記法はCインターフェースかC++インタフェースか」は常に意識しなければならない。
特に、Cインターフェースは最新のOpenCV 4系以降で削除されたので、C++ インタフェースを用いるのが基本である。
これらの対応関係を記したのが以下の表である。
|
OpenCV 2系
|
OpenCV 3系
|
OpenCV 4系
|
Cインターフェース
|
◯
|
△ 動くかもしれないがサポート対象外
|
×
|
C++インターフェース
|
◯
|
◯
|
◯
|
そのようなわけで、皆さんが探すべきなのは「C++インターフェースによるOpenCV3系以降の解説」である。
書店や図書館で書籍を探す際に参考にすると良い。
ConsoleApplication1.cpp のプログラム部を丸ごと以下に差し替えると顔認識のプログラムになる。
内容がやや難しいのでおまけ扱いとするが、実行自体は難しくないだろう。
ただし、二箇所ある world430 の部分は C:\opencv\build\x64\vc15\bin に存在するファイル名に書き換えること (OpenCV のバージョン番号に該当する)。
#include <iostream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#ifdef _DEBUG
#pragma comment(lib, "opencv_world430d.lib")
#else
#pragma comment(lib, "opencv_world430.lib")
#endif
int main()
{
const char* windowName = "Image";
cv::VideoCapture cap(0);
if (!cap.isOpened())//カメラデバイスが正常にオープンしたか確認.
{
return -1;
}
//顔認識用のカスケードを用意
std::string cascade_path = "C:\\opencv\\sources\\samples\\winrt\\FaceDetection\\FaceDetection\\Assets\\haarcascade_frontalface_alt.xml";
cv::CascadeClassifier cascade;
cascade.load(cascade_path);
while (1)
{
cv::Mat img;
cap >> img;
cv::Mat gray;
//グレースケール化
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
// gray から顔を探して赤い長方形を img に描画
std::vector<cv::Rect> faces;
cascade.detectMultiScale(gray, faces, 1.1, 2, 0 | cv::CASCADE_SCALE_IMAGE, cv::Size(30, 30));
for (auto face : faces) {
cv::rectangle(img, face, cv::Scalar(0, 0, 255), 2);
}
cv::imshow(windowName, img);//画像を表示.
int key = cv::waitKey(1);
if (key == 113)//qボタンが押されたとき
{
break;//whileループから抜ける.
}
}
cv::destroyAllWindows();
return 0;
}
前のページ「Visual Studio と OpenCV をインストールする」
Windows 上の Visual Studio で OpenCV を使う