7-segment digits detectionのためのテンプレート自動撮影
60秒毎にキャプチャーして、適切なファイル名でセーブするプログラム。Cameralib 64自体は、
ここから入手してください。下記のような追加のヘッダーをincludeすることで、EDSDKやNikon SDKのコールバックを水面下に押し込めるようにしました。つまり“隠蔽”ですね。
EdsError EDSCALLBACK ProgressFunc(EdsUInt32 inPercent, EdsVoid* inContext, EdsBool* outCancel)
{
return EDS_ERR_OK;
}
void UpdateProgressBar(unsigned long value)
{
//Form1->TransferProgress->Position = value;
}これをnoprogressbar.hとかで作成して、includeすればprogressbar等を用意しない場合の、linkエラーが回避できます。今回は、この形式を使いました。さて、副題の7-segment-digits detection云々は、

このような画像入力から画面内の数字を自動検出する試みです。さて、検出はテンプレートマッチングで行う予定で、このサイトでは、
ここで述べた画像相関係数の計算をして、一番近い数字を拾い出すわけです。原理等は、上記から参照願います。まずフォームから、

TImagex1,TButtonx2,TMemox1,TTimerx1,TEditx1を配置します。動作中のショットは、

です。分の1位の数字を目視で確認して、その数字をTEditに入れて、上図のように秒が10前後の時点で、”Start”ボタンをクリックすると、一分に一枚の画像を適切な名前で自動保存します。10分間で計10枚画像を得れば、そこで終了です。Unit1.hは、
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <Vcl.ComCtrls.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TImage *Image1;
TButton *Start;
TEdit *StartNum;
TButton *Take;
TTimer *Timer1;
TMemo *Memo1;
void __fastcall TakeClick(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
void __fastcall StartClick(TObject *Sender);
void __fastcall Timer1Timer(TObject *Sender);
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endifUnit1.cppは、
#include <vcl.h>
#pragma hdrstop
#include "cameralib.h"
#include "noprogressbar.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
Camera* camera;
extern int filecount;
int Live=0;
int framenum = 1;
int startframe;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
camera = new Camera();
Memo1->Lines->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TakeClick(TObject *Sender)
{
void* data;
long size;
filecount = 1;
TMemoryStream* ImageStream = new TMemoryStream();
camera->TakePictureToStream();
data = camera->getbuffer();
size = camera->getsize();
ImageStream->WriteBuffer(data,size);
ImageStream->Position = 0;
Image1->Picture->LoadFromStream(ImageStream);
//Image1->Refresh();
delete ImageStream;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete camera;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::StartClick(TObject *Sender)
{
startframe = StrToInt(StartNum->Text);
void* data;
long size;
String filename = "frame" + IntToStr(startframe) + ".jpg";
filecount = 1;
//camera->TakePictureToFile( filename);
TMemoryStream* ImageStream = new TMemoryStream();
camera->TakePictureToStream();
data = camera->getbuffer();
size = camera->getsize();
ImageStream->WriteBuffer(data,size);
ImageStream->Position = 0;
Image1->Picture->LoadFromStream(ImageStream);
Image1->Refresh();
delete ImageStream;
Image1->Picture->SaveToFile(filename);
Memo1->Lines->Add("saving " + filename);
startframe++;
framenum++;
Timer1->Enabled = true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
void* data;
long size;
String filename = "frame" + IntToStr(startframe) + ".jpg";
filecount = 1;
//camera->TakePictureToFile( filename);
TMemoryStream* ImageStream = new TMemoryStream();
camera->TakePictureToStream();
data = camera->getbuffer();
size = camera->getsize();
ImageStream->WriteBuffer(data,size);
ImageStream->Position = 0;
Image1->Picture->LoadFromStream(ImageStream);
Image1->Refresh();
delete ImageStream;
Image1->Picture->SaveToFile(filename);
Memo1->Lines->Add("saving " + filename);
startframe++;
if( startframe > 9 )
startframe -= 10;
framenum++;
if( framenum > 10 ){
Timer1->Enabled = false;
Memo1->Lines->Add("capture done");
}
}
//---------------------------------------------------------------------------“Take”ボタンを押すと、得られる画像をTImage上で確認できます。その流れで、てっきり
camera->TakePictureToFile(filename);
できると思ったのですが、そういう関数は無いと怒られました。確認したらCameralib内には作っていませんでした。(笑)Cameralib作り直してもいいんだけど、指定ファイル名でセーブするのは、
String filename = "frame" + IntToStr(startframe) + ".jpg";
filecount = 1;
//camera->TakePictureToFile( filename);
TMemoryStream* ImageStream = new TMemoryStream();
camera->TakePictureToStream();
data = camera->getbuffer();
size = camera->getsize();
ImageStream->WriteBuffer(data,size);
ImageStream->Position = 0;
Image1->Picture->LoadFromStream(ImageStream);
Image1->Refresh();
delete ImageStream;
Image1->Picture->SaveToFile(filename);
のごとく、一旦TMemoryStreamで受けて、それをSaveToFileすることで実現しました。得られた画像ですが、

これが”frame0.jpg”で、全部掲載するのもスペースの無駄なので、

これが”frame9.jpg”です。今回は、1分に一枚の言わばtime-lapse撮影をしたわけですが、もっと長時間間隔でのtime-lapse撮影や、トリガー条件でなどの柔軟な撮影ができますね。
さて、これらの10枚の画像からテンプレートを抜き出すのが次のプログラムになります。




コメント