// // list704.cpp   // グラフィック用にlist502.h、list502b.cppを使用する  // vfw32.libの追加が必要 // 2009.05 コーディクがない場合の終了処理追加 // #include #include // getch()の宣言 #include #include "list502.h" void f_avi( char * ); void f_avi2( BYTE *, BYTE *, int *, int *, int *, int * , int , HWND ); char * file_open( void ); void jyu(BYTE * , int * , int * ); void main() { char * pfn; pfn = file_open( ); f_avi( pfn ); printf("quit?"); getch(); return ; } void f_avi( char * pfn ) { int i,jj,k,nn,mm; AVISTREAMINFO si; PAVISTREAM pvs; HRESULT rc; PGETFRAME pvf; LPBITMAPINFOHEADER pbmpih; int th; AVIFileInit(); rc = AVIStreamOpenFromFile( &pvs, pfn, streamtypeVIDEO, 0, OF_READ, NULL); // Videoストリームをオープン if( rc ) { printf( "v open err\n" ); return; } AVIStreamInfo( pvs, &si, sizeof(AVISTREAMINFO) ); AVIStreamAddRef( pvs ); // ストリームの参照カウントを1増やす printf( "vi_Rate %7d : vi_Scale %6d : vi_Length %d \n", si.dwRate, si.dwScale, si.dwLength ); printf( "h = %d w = %d\n",si.rcFrame.right,si.rcFrame.bottom); printf("th?(50)"); scanf("%d",&th); IMG0 img00; int xy; xy = si.rcFrame.right * si.rcFrame.bottom; memset( &(img00.bih), 0, sizeof(BITMAPINFOHEADER) ); // ビットマップ情報をストリーム情報からコピー img00.bih.biWidth = si.rcFrame.right; img00.bih.biHeight = si.rcFrame.bottom; // ストリーム情報からは色、画像サイズは得られないが // DV形式の24bitカラー使用を前提に画像サイズを計算する // より柔軟性を持たせるのであるなら // AVIStreamReadFormatで完全なビットマップ情報を得るのがベスト   img00.bih.biSizeImage = xy * 3; img00.bih.biSize = sizeof(BITMAPINFOHEADER); img00.bih.biPlanes = 1; img00.bih.biBitCount = 24; img00.hi = (HINSTANCE)GetWindowLong( HWND_DESKTOP, GWL_HINSTANCE ); img00.x = 100; img00.y = 100; BYTE * bmp0; BYTE * bmp1; BYTE * bmp2; int *jx; int *jy; int *ga; bmp0 = (BYTE *)malloc( img00.bih.biSizeImage ); bmp1 = (BYTE *)malloc( img00.bih.biSizeImage ); bmp2 = (BYTE *)malloc( img00.bih.biSizeImage ); jx = (int *)malloc( si.dwLength * 2 * sizeof(int)); jy = (int *)malloc( si.dwLength * 2 * sizeof(int)); ga = (int *)malloc( si.dwLength * 2 * sizeof(int)); pvf = AVIStreamGetFrameOpen(pvs, (LPBITMAPINFOHEADER)AVIGETFRAMEF_BESTDISPLAYFMT); // 解凍の準備 if( pvf == NULL ){ printf("コーディックが見つかりません\n"); } else{ gr_reg(); gr_init( &img00 ); // グラフィックウィンドウを生成 pbmpih = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pvf, 0); // 0フレームが最初のフレーム BYTE * pp; pp = (BYTE *)pbmpih + sizeof(BITMAPINFOHEADER); for(k = 0;k < xy ;k++){ nn =( pp[k * 3] + pp[k * 3 +1] + pp[k * 3 +2] )/3; bmp0[k * 3]= bmp0[k * 3 +1] = bmp0[k * 3 +2] = nn; } int vc=0; // 1/2フレームのカウンタ img00.lpBmpData = bmp2; for( jj = 1;jj < si.dwLength ; jj++){ pbmpih = (LPBITMAPINFOHEADER)AVIStreamGetFrame(pvf,jj); pp = (BYTE *)pbmpih + sizeof(BITMAPINFOHEADER); for(k = 0;k < xy ;k++){ nn =( pp[k * 3] + pp[k * 3 +1] + pp[k * 3 +2] )/3; mm = fabs((double)(nn - bmp0[k *3])); // 微分 if (mm < th) // しきい値処理 mm = 0; else mm = 120; bmp1[k * 3] = mm; bmp0[k * 3] = nn; // 元バッファの更新 } f_avi2( bmp1, bmp2, jx, jy, ga, &vc , 0, img00.hwnd ); f_avi2( bmp1, bmp2, jx, jy, ga, &vc , 720, img00.hwnd ); } AVIStreamGetFrameClose(pvf); AVIStreamRelease( pvs ); AVIFileExit(); char ccbuf[100]; // 計算結果の書き出し char cb2[100]; i =0; while( pfn[i] != '.'){ ccbuf[i] = pfn[i]; i++; } ccbuf[i]=0; sprintf(cb2,"%s.csv",ccbuf); FILE *fp; fp = fopen(cb2,"w"); for(i = 0;i< si.dwLength * 2 -2 ;i++) fprintf(fp,"%d,%d,%d\n",ga[i],jx[i],jy[i] ); fclose(fp); SendMessage( img00.hwnd, WM_CLOSE, 0, 0 ); // グラフィック画面の終了 } free(bmp0);free(bmp1);free(bmp2); free( jx );free( jy );free( ga ); } // 1/2フレーム毎の処理 void f_avi2( BYTE bmp1[], BYTE bmp2[], int jx[], int jy[], int ga[], int * pvc , int offs , HWND hwnd) { int all, k, m, km, imin; int xp,yp; all = 0; for(k = 0;k < 240 ;k++){ for(m = 1;m < 719;m++){ km = (k * 2) * 720 + m; imin = bmp1[(km-1 + offs) *3]; // 雑音除去のために if(imin > bmp1[(km +offs)* 3] ) // 横方向の収縮処理 imin = bmp1[(km +offs)* 3]; // を行う if(imin > bmp1[(km+1+offs) * 3] ) imin = bmp1[(km+1+offs) * 3]; bmp2[km * 3] = bmp2[km * 3 +1] = bmp2[km * 3 +2] = bmp2[(km +720)* 3]= bmp2[(km+720) * 3 +1] = bmp2[(km +720)* 3 +2] = imin; all = all + imin; // 変化画素を集計 } } jyu(bmp2 , &xp, &yp); // 重心の計算 jx[*pvc] = xp; jy[*pvc] = yp; ga[*pvc]= all/120; *pvc = *pvc + 1; bmp2[(xp + yp * 720)*3] = bmp2[(xp + yp * 720)*3 +1] = bmp2[(xp + yp * 720)*3 +2] = 255; // 重心を白点で描く InvalidateRect( hwnd, NULL, FALSE); // 再描画を要求 printf("n=%d x=%d y=%d \n", all/120, xp, yp ); return; } // // 重心の計算 // void jyu(BYTE * bmp, int * x, int * y ) { int i,j; double s,sx,sy; s = 0;sx =0;sy = 0; for(i = 0;i< 480 ;i++){ for(j = 1;j<719;j++){ s = s + bmp[(i * 720 + j) * 3]; sx = sx + bmp[(i * 720 + j) * 3] * j; sy = sy + bmp[(i * 720 + j) * 3] * i; } } if (s == 0) s =1; *x = sx / s; *y = sy / s; return; } char * file_open(void ) { OPENFILENAME fname; static char fn[256]; memset(&fname, 0, sizeof(OPENFILENAME)); fname.lStructSize = sizeof(OPENFILENAME); fname.lpstrFilter = "*.*\0*.*\0\0"; fname.nFilterIndex = 1; // 1番目のファイルフィルタを使う fname.lpstrFile = fn; // 選択されたパス付きファイル名が格納されるアドレス fname.nMaxFile = sizeof(fn); fname.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; if( ! GetOpenFileName( &fname ) ) return NULL; return fn; }