2016年3月22日火曜日

MFC、opencv、USBカメラ

机の上でテストした基板の状態などの写真を簡単に撮影して、結果報告や資料として纏めておきたいということで、USBカメラをPCに接続して簡単に写真が撮れないかと。opencvを使うと簡単にできるらしいということで。
既知の人には今さら何を言ってるんだろうと思われるかもしれないけど。とりあえず。

まず、USBカメラは、、、

ELECOM WEBカメラ 200万画素 1/4インチCMOSセンサ ガラスレンズ搭載 筒型 イヤホンマイク付 ブラック UCAM-DLA200HBK

 

を選択。amazonで3千円、少し古い型のようだけど、ガラスレンズだということで決めた。

VisualStudio2013、MFCにて簡単なシャッターを押すだけのモニタを作る。

まず、適当なダイアログプロジェクトを作る。

そのプロジェクトにopencvを参照させるには、ツールメニューのNugetパッケージマネージャー、ソリューションのNugetパッケージの管理を開く。

右上の オンラインの検索 に opencvと入れて検索させる。
たぶん先頭に出てくる OpenCV OpenCV is a library of programming for realtime computer vision.のインストール釦を押す。
これでopencvが使えるようになる。
-------------------
stdafx.h
-------------------
#include <opencv2/core/core.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
を追加する。
 
 大体下記のソースを参照して貰えば、概要は分かると思います。実際はスレッドを起こして実行しています。
cv::VideoCapture(int カメラ番号)この番号はPCに接続しているカメラの番号なので、0から始まる。私の場合はノートPCにカメラが既に付いているので1が外付けのカメラだった。OSが認識する順なので、立ち上げ時に繋いでいると順序が入れ替わる可能性がある。結構不便。
cv::Mat これにイメージが取り込まれる。cam >> cam1image
cv::imwrite()、ファイル名の拡張子でJPGだったりPNGなどを指定できる。
CvvImageはDCとの仲介用で、これはネットからのコピペです。なかなか見つからなかった。権利上の問題があるかもしれないので、ここに貼り付けるのは憚れるので、以下のURLを見てください。
http://blog.csdn.net/vsooda/article/details/7547431
中国語ですが、ソース表示の上にViewPlain釦があります。

CvvImageを探す以外はすごく簡単でした。今時は簡単にできるのだなと感慨に耽ってしまった。

で、カメラをスタンドにグルーで付けて、上から撮影できるようにした。





 簡単だったというメモでした。

 
void PCamClass::Run()
{
 // Override
 cv::VideoCapture cam(m_nNum);
 cam.set(CAP_PROP_FRAME_WIDTH, 1600);
 cam.set(CAP_PROP_FRAME_HEIGHT, 1200);
 DWORD dwLastTick = ::GetTickCount();
 while (1)
 {
  if ((::GetTickCount() - dwLastTick) < 334) // 3fps
  {
   Sleep(50);
   continue;
  }
  dwLastTick = ::GetTickCount();
  cv::Mat cam1image;
  cam >> cam1image; 
  
  if (m_bGetJPEG && !m_bGotJPEG)
  {
   /// Save to the FileName
   cv::imwrite(m_strFileName, cam1image);
   m_bGotJPEG = true;
  }

  CvvImage cimg;
  IplImage img = cam1image;

  cimg.CopyOf(&img);

  if (IsWindow(m_hWnd))
  {
   HDC hDC = ::GetDC(m_hWnd);
   cimg.DrawToHDC(hDC, &m_rectDraw);
   ReleaseDC(m_hWnd, hDC);
  }
  DWORD dwRet = ::WaitForSingleObject( this->m_hTerminateEvent, 0);
  switch (dwRet)
  {
  case WAIT_OBJECT_0: // Prio End
   return;
  }
 }
}

2016年3月12日土曜日

MFC MDI ドキュメントタイプ選択の画面を出したくない。

MFCのMDIでは拡張子に応じて、ドキュメントタイプを選択して、ドキュメントテンプレートでCDocumentとCViewを開くようになっている。
しかし、空のドキュメントを開かせようとすると、プログラム起動時にドキュメントタイプを選択するダイアログが出てしまう。

これは知らないユーザにとっては何を選択するべきか、判りにくい。

で、空のドキュメントは常にデフォルトのドキュメントタイプを開かせておき、その後、実ファイルを開いた時だけ該当のドキュメントタイプが利用できる様にしたい場合。

拡張子だけで、中身のないファイルを扱えるようにしてあるので、ドキュメントタイプを指定して新規ファイルを作成できなくても問題がないようになっている前提である。ちょっと特殊かもしれないが、とにかく選択ダイアログは判りにくいので表示しない。


CWinApp::InitInstace()
{

   ................

    CMultiDocTemplate* pDocTemplate;
    pDocTemplate = new CMultiDocTemplate(IDR_XXXXXXXXTYPE,
        RUNTIME_CLASS(CXXXXXXXXDoc),
        RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
        RUNTIME_CLASS(CXXXXXXXXView));
    if (!pDocTemplate)
        return FALSE;
    AddDocTemplate(pDocTemplate);

    通常はここに追加のテンプレートを定義するのだが、コマンドラインに指定がなければ追加しない。
    if (strlen(m_lpCmdLine))
    {
        pDocTemplate = new CMultiDocTemplate(IDR_YYYYYYYYTYPE,
            RUNTIME_CLASS(CYYYYYYYYDoc),
            RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
            RUNTIME_CLASS(CYYYYYYYYView2));
        if (!pDocTemplate)
            return FALSE;
        AddDocTemplate(pDocTemplate);
    }
   ................

  pMainFrame->UpdateWindow();
  // このInitInstance()の最後で、追加しなかったドキュメントタイプを追加しておく
    if (!strlen(m_lpCmdLine))
    {
        pDocTemplate = new CMultiDocTemplate(IDR_YYYYYYYYTYPE,
            RUNTIME_CLASS(CYYYYYYYYDoc),
            RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム
            RUNTIME_CLASS(CYYYYYYYYView2));
        if (!pDocTemplate)
            return FALSE;
        AddDocTemplate(pDocTemplate);
    }
}