Windows Vista Home Premium SP2 32ビットです。
OpenCV2.0と、
http://dixq.net/forum/blog.php?u=536&b=2362のBMPのライブラリを使用しています。
カメラはDigioのMCW-14Wです。
カメラからの画像を取得し、最終的には加工して表示したいのですが、
画像の取得がうまくいきません。
うまくいかないコードはこれです。
► スポイラーを表示
#include <windows.h>
#include <highgui.h>
#include "bmpio.h"
LPCSTR szWindowClass = "GAME_CLASS";
LPCSTR szWindowTitle = "ウィンドウタイトル";
/*必要な変数*/
int end=0;
int active;
HDC gamen;
HBITMAP gamenbmp;
HDC uragamen;
HBITMAP uragamenbmp;
HANDLE hthread;
unsigned int threadid;
HWND hMainWnd;
/*自分の変数*/
/*char folder[MAX_PATH];*/
/*自分の変数ここまで*/
/*プロトタイプ宣言*/
/*システム関数*/
void wndresizebyclient(HWND,int,int);
int GameThread(int);
/*APIを使いやすくするラッパ*/
int FillRect2(HDC,int,int,int,int,HBRUSH);
HFONT CreateFont2(int,char*);
int TextOut2(HDC,int,int,char*);
int GetTextSize(HDC,char*,LPSIZE);
/*自分の関数*/
/*自分の関数ここまで*/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch (message) {
case WM_CREATE:
active=1;
break;
case WM_ACTIVATE:
active=LOWORD(wParam);
break;
case WM_COMMAND:
switch (LOWORD(wParam)) {
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
BitBlt(hdc,0,0,640,480,uragamen,0,0,SRCCOPY);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
WNDCLASSEX wcex;
HANDLE maebmp;
HANDLE uramaebmp;
HDC windc;
/*int i,j,len;*/
DWORD exitcode;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = (WNDPROC)WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
hMainWnd = CreateWindow(szWindowClass,
szWindowTitle, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
NULL, NULL, hInstance, NULL);
if (!hMainWnd)
return FALSE;
wndresizebyclient(hMainWnd,640,480);
ShowWindow(hMainWnd, nCmdShow);
UpdateWindow(hMainWnd);
active=1;
/*裏画面の作成*/
windc=GetDC(hMainWnd);
gamen=CreateCompatibleDC(windc);
gamenbmp=CreateCompatibleBitmap(windc,640,480);
maebmp=SelectObject(gamen,gamenbmp);
/*描画用裏画面の作成*/
uragamen=CreateCompatibleDC(windc);
uragamenbmp=CreateCompatibleBitmap(windc,640,480);
uramaebmp=SelectObject(uragamen,uragamenbmp);
/*実行ファイルがあるフォルダを取得*/
/*GetModuleFileName(NULL,(CHAR*)folder,MAX_PATH);
len=lstrlen(folder);
j=len-1;
for(i=0;i<len;i++) {
if(folder[i] & 0x80)i++;
else if(folder[i]==92)j=i;
}
folder[j+1]=0;*/
/*スレッドの開始*/
hthread=CreateThread(NULL,0,
(LPTHREAD_START_ROUTINE)&GameThread,0,0,
(DWORD*)&threadid);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
end=1;
GetExitCodeThread(hthread,&exitcode);
while(exitcode==STILL_ACTIVE) {
Sleep(10);/*CPUに負荷をかけない*/
GetExitCodeThread(hthread,&exitcode);/*スレッドの終了を待機*/
}
CloseHandle(hthread);
SelectObject(gamen,maebmp);
DeleteObject(gamenbmp);
DeleteDC(gamen);
SelectObject(uragamen,uramaebmp);
DeleteObject(uragamenbmp);
DeleteDC(uragamen);
return msg.wParam;
}
void wndresizebyclient(HWND hWnd,int x,int y) {
RECT size;
RECT wndsize;
GetClientRect(hWnd,&size);
GetWindowRect(hWnd,&wndsize);
wndsize.right=wndsize.right-wndsize.left;
wndsize.bottom=wndsize.bottom-wndsize.top;
SetWindowPos(hWnd,NULL,0,0,x+wndsize.right-size.right,y+wndsize.bottom-size.bottom,SWP_NOMOVE | SWP_NOREPOSITION | SWP_NOZORDER);
}
int GameThread(int param) {
/*変数の宣言*/
unsigned long maetime;
int frame;
long sleeptime;
/*自分が使う変数の宣言*/
CvCapture *videoCapture;
IplImage *image;
IplImage *image2;
bmp_t* bmp;
int x,y;
HBITMAP hbmp;
/*自分が使う変数の宣言ここまで*/
/*fps用変数の宣言*/
char fpstext[1024]="0.00fps";
unsigned long fpskizyuntick,fpsmaetime,fpsnowtime;
int fpscount;
/*自分が使う変数はここで宣言する*/
/*ここまで*/
/*自分の初期化*/
videoCapture = cvCreateCameraCapture( 0 );
if(videoCapture==NULL) {
MessageBox(hMainWnd,"error","error",MB_OK | MB_ICONWARNING);
return 0;
}
cvSetCaptureProperty (videoCapture, CV_CAP_PROP_FRAME_WIDTH, 640);
cvSetCaptureProperty (videoCapture, CV_CAP_PROP_FRAME_HEIGHT, 480);
bmp=bmpMake(640,480);
/*自分の初期化ここまで*/
/*変数の初期化*/
maetime=GetTickCount();
frame=0;
/*fpsの初期化*/
fpscount=0;
fpskizyuntick=GetTickCount();
fpsmaetime=fpsnowtime=0;
/*メインループ*/
while(end==0) {
if(active) {
/*誤操作防止*/
/*ウィンドウがアクティブの時だけ処理する*/
/*画面に描画するときはgamenを使う*/
/*画面の初期化*/
FillRect2(gamen,0,0,640,480,GetStockObject(WHITE_BRUSH));
/*ゲームの処理をここに書く*/
image = cvQueryFrame( videoCapture );
image2 = cvCloneImage(image);
for (y = 0; y < image2->height; y++) {
for (x = 0; x < image2->width; x++) {
getBmpXY(bmp,x,y).b = image2->imageData[image2->widthStep * y + x * 3]; // B
getBmpXY(bmp,x,y).g = image2->imageData[image2->widthStep * y + x * 3 + 1]; // G
getBmpXY(bmp,x,y).r = image2->imageData[image2->widthStep * y + x * 3 + 2]; // R
}
}
cvReleaseImage(&image2);
hbmp=bmpSaveToHandle(gamen,bmp);
DeleteObject(SelectObject(gamen,hbmp));
/*ゲームの処理ここまで*/
/*画面の転送*/
BitBlt(uragamen,0,0,640,480,gamen,0,0,SRCCOPY);
InvalidateRect(hMainWnd,NULL,FALSE);
UpdateWindow(hMainWnd);
}
fpsnowtime=GetTickCount()-fpskizyuntick;
if(fpsnowtime>=1000) {
wsprintf(fpstext,"カメラテスト - %d.%02dfps",
fpscount+((1000-fpsmaetime)*100/
(fpsnowtime-fpsmaetime))/100,
((1000-fpsmaetime)*100/
(fpsnowtime-fpsmaetime))%100);
fpskizyuntick=GetTickCount();
fpsmaetime=0;
fpscount=0;
SetWindowText(hMainWnd,fpstext);
} else {
fpscount++;
fpsmaetime=fpsnowtime;
}
/*fpsの計測終了*/
/*60fpsにする処理
http://dixq.net/rp/43.htmlを参考に*/
frame++;
sleeptime=(frame<60)?
(maetime+(long)((double)frame*(1000.0/60.0))-GetTickCount()):
(maetime+1000-GetTickCount());
if(sleeptime>0)Sleep(sleeptime);
if(frame>=60) {
frame=0;
maetime=GetTickCount();
}
}
/*自分の終了処理*/
cvReleaseCapture( &videoCapture );
bmpFree(bmp);
/*終了処理*/
return 0;
}
/*APIを使いやすくするラッパ*/
int FillRect2(HDC hDC,int sx,int sy,int dx,int dy,HBRUSH hBrush) {
RECT rc;
rc.top=sy;
rc.left=sx;
rc.right=dx;
rc.bottom=dy;
return FillRect(hDC,&rc,hBrush);
}
HFONT CreateFont2(int nHeight,char* lpszFace) {
return CreateFont(nHeight,0,0,0,FW_NORMAL,0,0,0,
DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
DEFAULT_PITCH,lpszFace);
}
int TextOut2(HDC hDC,int nXStart,int nYStart,char* lpString) {
return TextOut(hDC,nXStart,nYStart,lpString,lstrlen(lpString));
}
int GetTextSize(HDC hDC,char* lpString,LPSIZE lpSize) {
return GetTextExtentPoint32(hDC,lpString,lstrlen(lpString),lpSize);
}
Compiler=-I"C:\OpenCV2.0\include\opencv"
CppCompiler=-I"C:\OpenCV2.0\include\opencv"
Linker=-L"C:\OpenCV2.0\lib" -L. -lcxcore200.dll -lhighgui200.dll -lbmpio -lgdi32 -Wl,--subsystem,windows
こっちのコードでは問題なくカメラの画像が表示されます。
► スポイラーを表示
#include <stdio.h>
#include <windows.h>
#include <highgui.h>
int main()
{
// カメラからのビデオキャプチャを初期化する
CvCapture *videoCapture = cvCreateCameraCapture( 0 );
//CvCapture *videoCapture = cvCaptureFromCAM(0);
if( videoCapture == NULL )
{
MessageBox(0,"error","error",MB_OK | MB_ICONWARNING | MB_TOPMOST);
return -1;
}
//キャプチャサイズを指定する
cvSetCaptureProperty (videoCapture, CV_CAP_PROP_FRAME_WIDTH, 640);
cvSetCaptureProperty (videoCapture, CV_CAP_PROP_FRAME_HEIGHT, 480);
// ウィンドウを作成する
char windowName[] = "camera";
cvNamedWindow( windowName, CV_WINDOW_AUTOSIZE );
// 何かキーが押下されるまで、ループをくり返す
while( cvWaitKey( 1 ) == -1 )
{
// カメラから1フレーム取得する
IplImage *image = cvQueryFrame( videoCapture );
// ウィンドウに画像を表示する
cvShowImage( windowName, image );
}
// ビデオキャプチャを解放する
cvReleaseCapture( &videoCapture );
// ウィンドウを破棄する
cvDestroyWindow( windowName );
return 0;
}
gcc -I"C:\OpenCV2.0\include\opencv" -L"C:\OpenCV2.0\lib" cameratest.c -o cameratest.exe -lcxcore200.dll -lhighgui200.dll -Wl,--subsystem,windows
表示が可能なOpenCVのバージョン、もしくはその他の解決策があれば教えてください。
よろしくお願いします。