読者です 読者をやめる 読者になる 読者になる

メヘンニミン

たくさんの言語に触れたい.走り書きで見る整理ブログです.

画像からQRコードを読み取る(OpenCV + libencodeqr編)

f:id:enlosph:20150109170622j:plain:w800

今回やることやで!

OpenCVC/C++用ライブラリです.JavaPython向けもあるようですが,僕はOpenCvSharpというC#向けにラッパーされたライブラリもよく使用しています.

OpenCV環境を整える(雑)

今回はVS2010環境でうまくいきました.openCV,今回はv2.4.10をインストール.x64ビット環境の場合,

のパスを通しておきましょう.再起動orログオフも忘れずに!

Physics-Station: OpenCV を Visual Studio で使う方法

また,上のリンクの「静的リンクライブラリの設定」から,opencv_lib.hppをダウンロードして

  • C:\opencv\build\include\opencv2

に置くと便利です.opencv_lib.hppの中身は,以下のようにOpenCVのバージョンに合わせて書き換えてください.

#if _DEBUG
#pragma comment(lib, "opencv_calib3d2410d.lib")
#pragma comment(lib, "opencv_contrib2410d.lib")
#pragma comment(lib, "opencv_core2410d.lib")
#pragma comment(lib, "opencv_features2d2410d.lib")
#pragma comment(lib, "opencv_flann2410d.lib")
#pragma comment(lib, "opencv_gpu2410d.lib")
#pragma comment(lib, "opencv_highgui2410d.lib")
#pragma comment(lib, "opencv_imgproc2410d.lib")
#pragma comment(lib, "opencv_legacy2410d.lib")
#pragma comment(lib, "opencv_ml2410d.lib")
#pragma comment(lib, "opencv_nonfree2410d.lib")
#pragma comment(lib, "opencv_objdetect2410d.lib")
#pragma comment(lib, "opencv_ocl2410d.lib")
#pragma comment(lib, "opencv_photo2410d.lib")
#pragma comment(lib, "opencv_stitching2410d.lib")
#pragma comment(lib, "opencv_superres2410d.lib")
#pragma comment(lib, "opencv_ts2410d.lib")
#pragma comment(lib, "opencv_video2410d.lib")
#pragma comment(lib, "opencv_videostab2410d.lib")
#else
#pragma comment(lib, "opencv_calib3d2410.lib")
#pragma comment(lib, "opencv_contrib2410.lib")
#pragma comment(lib, "opencv_core2410.lib")
#pragma comment(lib, "opencv_features2d2410.lib")
#pragma comment(lib, "opencv_flann2410.lib")
#pragma comment(lib, "opencv_gpu2410.lib")
#pragma comment(lib, "opencv_highgui2410.lib")
#pragma comment(lib, "opencv_imgproc2410.lib")
#pragma comment(lib, "opencv_legacy2410.lib")
#pragma comment(lib, "opencv_ml2410.lib")
#pragma comment(lib, "opencv_nonfree2410.lib")
#pragma comment(lib, "opencv_objdetect2410.lib")
#pragma comment(lib, "opencv_ocl2410.lib")
#pragma comment(lib, "opencv_photo2410.lib")
#pragma comment(lib, "opencv_stitching2410.lib")
#pragma comment(lib, "opencv_superres2410.lib")
#pragma comment(lib, "opencv_ts2410.lib")
#pragma comment(lib, "opencv_video2410.lib")
#pragma comment(lib, "opencv_videostab2410.lib")
#endif

ソリューションエクスプローラーにて,プロジェクト名を右クリック=>プロパティ=>構成プロパティ=>VC++ディレクトリで,インクルードディレクトリに(ソースによりけりで)以下の2つのどちらか,または両方を追加します.

さらに,ライブラリディレクトリに以下を追加.

構成マネージャーにて,プラットフォームがx64でない場合は,新規作成でx64にしましょう.

メインのプログラム(main.cpp)には,下記の2行を追加します.

#include <opencv2/opencv.hpp>
#include <opencv2/opencv_lib.hpp>


コンパイルで「x64x86で競合する」エラーが出た場合,構成プロパティ=>リンカー=>詳細設定で,対象コンピューターをMachineX64にしましょう.だめなら,上記x64x86の見直し.

画像中のQRコードをデコードするには?

今回はライブラリlibencoderqr-0.9.3を使用します.ちなみに,似たような名前のlibqrencoderは,生成用のCライブラリです.ややこしい.

中身のsrc\libdecodeqr\libdecoder.dswVisual Studioで開きましょう.そして上記と同様の設定を行います.

  • インクルードディレクトリに追加(両方)
  • 構成マネージャーでプラットフォームをx64に変更

準備ができたら「デバッグ開始」.うまくいくと,Debugフォルダにlibdecodeqr.libが生成されます.このlibと,cpp,hファイルも全て,自分のプロジェクトのDebugフォルダのある階層にコピーしましょう.

次!自分のプロジェクトソースに以下の3行を追加.

#include "decodeqr.h"
#pragma comment(lib, "WS2_32.LIB")
#pragma comment(lib, "libencodeqr.lib")

これでライブラリが使用可となりました.下記に,IplImage変数imgの処理例を示します.Webカメラ画像からIplImageを獲得する場合は,後述します.

qr_decoder_set_image_buffer( decoder, img ); // 画像をセット
if( !qr_decoder_is_busy( decoder ) )
{
  short sz = 25;
  short stat = qr_decoder_decode( decoder, sz );
  for( sz = 25, stat = 0; ( sz >= 3 ) && ( ( stat & QR_IMAGEREADER_DECODED ) == 0 ); sz -= 2 )
    stat = qr_decoder_decode( decoder, sz );
}

int text_size = 0;
unsigned char* text = new unsigned char[ text_size ];
QrCodeHeader header;
if( qr_decoder_get_header( decoder, &header ) ) // デコード
{
  if( text_size < header.byte_size + 1 )
    {
     if( text ) delete[] text;
      text_size = header.byte_size + 1;
      text = new unsigned char[ text_size ];
    }
  qr_decoder_get_body( decoder, text, text_size ); // ここでtextにデコード結果が保存される
  CvFont dfont;
  cvInitFont (&dfont, CV_FONT_HERSHEY_COMPLEX, 1.0f, 1.0f);
  cvPutText(img, (char*)text, cvPoint(65, 60), &dfont, CV_RGB(0, 255, 0)); // 画像に直接文字を描いてみる
}
delete[] text;

参考先.

プログラム備忘録 OpenCV を使って QRcode の解析 その2

画像からQRコードを切り取るには?

切り取った画像を入手したいだけなら,こちらが非常に参考になります.上記libencodeqrの中身を参考にしたアルゴリズムの解説と,ソースファイルが置かれています.

OpenCVでQRコード検出器を書く

QRコード検出器プログラムの中身を全てDebugフォルダのある階層に突っ込みます.includeは,こんな感じ.

  • main.cpp(メインファイル)
#include <opencv2/opencv.hpp>
#include <opencv2/opencv_lib.hpp>
#include "QRDetector.h"
  • QRDetector.h
#include <opencv/cv.h>
#include <opencv/cxcore.h>
#include <opencv/highgui.h>

main.cppは,同階層のtest.jpgが切り取り対象です.Webカメラを利用する場合は,こんな感じ.

  • main.cpp
IplImage *img;
IplImage *qrimg;

CvCapture *videoCapture = NULL; // カメラキャプチャの初期化
videoCapture = cvCreateCameraCapture( 0 ); // Webカメラの取得
cvNamedWindow( "camera", CV_WINDOW_AUTOSIZE ); // ウインドウを作成

while( 1 )
{
    c = cvWaitKey( 2 );
    if(c == '\x1b') break; // ESCキーで閉じる
    IplImage *img = cvQueryFrame( videoCapture ); // カメラから1フレーム取得する
    if( img != 0 ){
        qrimg = detectQRcode(img, 10); // QR部分を切り取る
        if(qrimg->height < img->height) img = qrimg; // 成功なら挿し替え
        cvShowImage( windowName, img ); // ウインドウに画像を表示する
    }
}
cvReleaseImage(&img);
cvReleaseImage(&qrimg);


(追記 2015.9.4)
上記を含めたプログラムをGitHubで公開しました.

精度は?

あまりよくない.ここまでやって!

方針は?

そこで次回はZXing編.C#,そしてAndroidでの実装です!