Cameralib 64の応用

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;
//---------------------------------------------------------------------------
#endif

Unit1.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枚の画像からテンプレートを抜き出すのが次のプログラムになります。

コメント