金かけずに車載カメラの動画にスピード表示させる方法考えてみた。

 ION AIR PRO買ってから自転車の車載カメラ動画撮ったり見たりしてるのだが、時々スピードメーターとか心拍数とか出てる奴がある。
 どうやらdashwareとかソフト使ってるみたいなのだが、できれば金かけずにやりたい。そもそも無圧縮aviファイルって結局パラパラ漫画なんだろ。と思っていたら
http://eternalwindows.jp/winmm/avi/avi07.html
 に良い情報が。どこの誰だか知らないが感謝ですよ。
 私の使ってるGPSはeTrex VENTURE。どうせ1秒以上の間隔でしかログ取れないし(設定できるのかも知れないが知らん)それ以上の精度には興味はない。あくまで遊びである。カシミール3Dでデータ読んでコピペでエクセルを使ってポイント名、時間(秒数)、速度の3項目だけのプレーンテキストのデータファイルをin.txtと名前つけて作る。
No. 61 11 25.3
No. 62 11 31.2
No. 63 2 31.5
No. 64 5 32.8
No. 65 13 34.7…
(ダミー文字列)区切りタブ(ダミー文字列)区切りタブ(次のスピードが維持された秒数)区切りタブ(スピード)
ダミー文字列とはポイント名なのだが、あったほうがどっからログをカットするのか分かりやすいのでsscanfでdmy,dmy2と面倒を見る。
 あとはaviutlの拡張編集を使えばそれっぽいものが出来る。

#include <windows.h>
#include <stdio.h>
#include <vfw.h>
#pragma comment (lib, "vfw32.lib")
#define MAX_SEC 9999//とりあえず166分まで…。floatにしたのもなんとなくメモリ気にして。
int	dofile( float table[])
{
FILE	*fp;
int	i,j;
char	buf[256];/*テキストファイル1行の最大文字数*/
char	dmy[256];
char	dmy2[256];
int	sec;
float km;
fp = fopen( "in.txt", "r");
if( fp == NULL )
{
MessageBox(NULL, "fopenのエラー", "OK", MB_OK);
exit( 0);
}
i = 0;
while( fgets( buf, sizeof( buf), fp) != NULL )
{
//とりあえずテキストデータは「No. 60	0	0」(タブ区切り)
if( sscanf( buf, "%s %s %d %f", dmy, dmy2, &sec, &km) == 4 )
{
for( j = 0; j < sec; j++ )
{
table[i + j] = km;
}
i += j;
if( i > MAX_SEC )
{
MessageBox(NULL, "166分超えた", "OK", MB_OK);
exit( 0);
}
}
else
{
MessageBox(NULL, "sscanfのエラー", "OK", MB_OK);
exit( 0);
}
}
fclose( fp);
return i;
}
void WriteStream(PAVISTREAM pavi, LPAVISTREAMINFO lpsi, float table[])
{
HDC              hdcMem;
HBITMAP          hbmpMem, hbmpMemPrev;
DWORD            i;
TCHAR            szBuf[256];
LPVOID           lpBits;
BITMAPINFOHEADER bmiHeader;
ZeroMemory(&bmiHeader, sizeof(BITMAPINFOHEADER));
bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
bmiHeader.biWidth       = lpsi->rcFrame.right;
bmiHeader.biHeight      = lpsi->rcFrame.bottom;
bmiHeader.biPlanes      = 1;
bmiHeader.biBitCount    = 24;
bmiHeader.biCompression = BI_RGB;
bmiHeader.biSizeImage   = bmiHeader.biHeight * ((3 * bmiHeader.biWidth + 3) / 4) * 4;
AVIStreamSetFormat(pavi, 0, &bmiHeader, sizeof(BITMAPINFOHEADER));
hdcMem = CreateCompatibleDC(NULL);
hbmpMem = CreateDIBSection(NULL, (LPBITMAPINFO)&bmiHeader, DIB_RGB_COLORS, &lpBits, NULL, 0);
hbmpMemPrev = (HBITMAP)SelectObject(hdcMem, hbmpMem);
SetBkMode(hdcMem, TRANSPARENT);
for (i = 0; i < lpsi->dwLength; i++) {
sprintf(szBuf, "%4.1fkm/h", table[i]);
FillRect(hdcMem, &lpsi->rcFrame, (HBRUSH)GetStockObject(GRAY_BRUSH));
DrawText(hdcMem, szBuf, -1, &lpsi->rcFrame, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
AVIStreamWrite(pavi, i, 1, lpBits, bmiHeader.biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
}
SelectObject(hdcMem, hbmpMemPrev);
DeleteObject(hbmpMem);
DeleteDC(hdcMem);
}
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpszCmdLine, int nCmdShow)
{
int			nframe;//フレーム総数。
float	table[MAX_SEC];//1秒毎のkm/h。
PAVIFILE      pfile;
PAVISTREAM    pavi;
AVISTREAMINFO si;
nframe = dofile( table);
AVIFileInit();
if (AVIFileOpen(&pfile, TEXT("out.avi"), OF_CREATE | OF_WRITE, NULL) != 0) {
MessageBox(NULL, TEXT("ファイルの作成または書き込みオープンに失敗しました。"), TEXT("OK"), MB_OK);
AVIFileExit();
return 0;
}
ZeroMemory(&si, sizeof(AVISTREAMINFO));
si.fccType    = streamtypeVIDEO;
si.fccHandler = comptypeDIB;
si.dwScale    = 1;
si.dwRate     = 1;//1秒1フレーム。
si.dwLength   = nframe;
si.dwQuality  = (DWORD)-1;
SetRect(&si.rcFrame, 0, 0, 32*3, 32);//3倍しただけ
if (AVIFileCreateStream(pfile, &pavi, &si) != 0) {
MessageBox(NULL, TEXT("ストリームの作成に失敗しました。"), TEXT("OK"), MB_OK);
AVIFileRelease(pfile);
AVIFileExit();
return 0;
}
WriteStream(pavi, &si ,table);
MessageBox(NULL, TEXT("書き込みを終了しました。"), TEXT("OK"), MB_OK);
AVIStreamRelease(pavi);
AVIFileRelease(pfile);
AVIFileExit();
return 0;
}
カテゴリーbike

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください