【画像認識】「Caffe」とUSBカメラで数字認識!実装方法編
改良
Caffeソリューションに「classification」プロジェクトがあります。
#Caffeの環境構築の方法はコチラ
USBカメラで数字を認識するためには、
「classification」プロジェクトの「classification.cpp」を修正するだけです。
もともと「classification」は引数で与えた画像の識別結果を返す
という処理になります。
そこで、今回は、引数で指定した画像を使うのではなく、
USBカメラで撮影した画像を識別に使うように改良します。
改良内容は、
「classification.cpp」のmain関数を以下のように変えるだけです。
#不要処理を削ればもっとスマートになると思います。手抜きです(^_^;
int main(int argc, char** argv) { if (argc != 6) { std::cerr << "Usage: " << argv[0] << " deploy.prototxt network.caffemodel" << " mean.binaryproto labels.txt img.jpg" << std::endl; return 1; } ::google::InitGoogleLogging(argv[0]); string model_file = argv[1]; // 学習処理のモデル string trained_file = argv[2]; // 学習モデル string mean_file = argv[3]; string label_file = argv[4]; Classifier classifier(model_file, trained_file, mean_file, label_file); string file = argv[5]; std::cout << "---------- Prediction for " << file << " ----------" << std::endl; cv::Mat img = cv::imread(file, -1); CHECK(!img.empty()) << "Unable to decode image " << file; std::vector<Prediction> predictions = classifier.Classify(img); /* Print the top N predictions. */ for (size_t i = 0; i < predictions.size(); ++i) { Prediction p = predictions[i]; std::cout << std::fixed << std::setprecision(4) << p.second << " - \"" << p.first << "\"" << std::endl; } //****************************** // USBカメラによる識別 //****************************** // カメラデバイスをオープンする cv::VideoCapture cap(0); // カメラデバイスが正常にオープンしたか確認する if (!cap.isOpened()) { return -1; } cv::Mat tmp; cap >> tmp; int size = 100; int sx = tmp.cols / 2 - size / 2; int sy = tmp.rows / 2 - size / 2; cv::Rect targetRect(sx, sy, size, size); // (1)動画ファイルを書き出すの準備を行う cv::VideoWriter writer("videofile.avi", CV_FOURCC_MACRO('X', 'V', 'I', 'D'), 30.0, cv::Size(640, 480), true); // (2)動画ファイル書き出しの準備に成功したかチェックする(失敗していればエラー終了する) if (!writer.isOpened()){ return -1; } bool reverseFlag = true; // ネガポジ反転 // 無限ループ while (1) { cv::Mat frame; cap >> frame; cv::Mat target(frame, targetRect); // グレースケールに変換する //cv::cvtColor(target, target, CV_RGB2GRAY); if (reverseFlag){ target = ~target; } // 識別処理 std::vector<Prediction> predictions = classifier.Classify(target); // 識別結果表示 Prediction p = predictions[0]; std::stringstream ss; ss << std::fixed << std::setprecision(4) << p.second << " - \"" << p.first << "\""; cv::putText(frame, ss.str(), cv::Point(sx-20, sy-10), 1, 1.5, cv::Scalar(0, 0, 255), 2); cv::rectangle(frame, targetRect, cv::Scalar(0, 255, 0), 3); // 画像を表示する cv::imshow("window", frame); // 動画書き込み writer << frame; // キー入力を取得する int key = cv::waitKey(1); // qを押すと終了する if (key == 113) { break; }else if (key == 115) { //sを押すと画像を保存する cv::imwrite("img.png", frame); } else if (key == 114){ if (reverseFlag){ reverseFlag = false; } else{ reverseFlag = true; } } } cv::destroyAllWindows(); }
実行
classification.cppを改良後、ビルドします。
そして、生成された「classification.exe」を使い、
以下のバッチ処理を実行するとUSBカメラが起動し、
映像の中心にある矩形内の数字を識別します。
※ちなみにカレントディレクトリは「caffe-master\Build\x64\Release\bat」です。
SET ROOT_DIR=..\ cd %ROOT_DIR% classification.exe .\examples\mnist\lenet.prototxt .\examples\mnist\lenet_iter_10000.caffemodel .\binaryproto\meanfile.binaryproto .\examples\mnist\test_leveldb\labels.txt .\testimg\one\one.bmp pause