winapiにおいてcreatewindow関数を使用して親ウィンドウの中に子ウィンドウを作成してその子ウィンドウにカメラからの映像をリアルタイムで表示することは可能ですか?
また可能ならどのようにすればいいのでしょうか?
環境はvisual studio2013 for windows desktop、 C++、 カメラ映像の取得にはopencvを使用しています。
カメラ映像の表示方法
Re: カメラ映像の表示方法
>カメラ映像の取得にはopencvを使用しています。
まずopencvのコードを提示してください。(Win32ConsoleApplication ではありませんか?)
まずopencvのコードを提示してください。(Win32ConsoleApplication ではありませんか?)
Re: カメラ映像の表示方法
>カメラ映像の取得にはopencvを使用しています
カメラ映像であれば,大抵,横幅は4の倍数だろうから,
BitBlt()などで簡単にDCに描画できます.
#とかいう話ではなくて, リアルタイム の部分のための工夫が主題なのでしょうか?
カメラ映像であれば,大抵,横幅は4の倍数だろうから,
BitBlt()などで簡単にDCに描画できます.
#とかいう話ではなくて, リアルタイム の部分のための工夫が主題なのでしょうか?
Re: カメラ映像の表示方法
カメラ映像をvideoCaptureで取得してリアルタイムで表示したいです.
いかに主要なコードを掲載します。
いかに主要なコードを掲載します。
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("opencv");
if (!RegisterClass(&winc)) return -1;
hwnd = CreateWindow(
TEXT("opencv"), TEXT("画面"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE,
0, 0, 1350, 800,
NULL, NULL, hInstance, NULL
);
CreateWindow(//ここで作成したウィンドウにカメラ映像を表示させたい
TEXT("STATIC"), NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER ,
100, 0, 800, 700,
hwnd, NULL, hInstance, NULL
);
CreateWindow(
TEXT("BUTTON"), TEXT("111"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
1000, 100, 200, 50,
hwnd, (HMENU)BUTTON_ID1, hInstance, NULL
);
CreateWindow(
TEXT("BUTTON"), TEXT("aaa"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
1000, 400, 100, 50,
hwnd, (HMENU)BUTTON_ID2, hInstance, NULL
);
CreateWindow(
TEXT("BUTTON"), TEXT("bbb"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
1200, 400, 100, 50,
hwnd, (HMENU)BUTTON_ID3, hInstance, NULL
);
CreateWindow(
TEXT("BUTTON"), TEXT("ccc"),
WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON,
1000, 300, 80, 40,
hwnd, (HMENU)BUTTON_ID4, hInstance, NULL
);
CreateWindow(
TEXT("BUTTON"), TEXT("ddd"),
WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON,
1125, 300, 80, 40,
hwnd, (HMENU)BUTTON_ID5, hInstance, NULL
);
CreateWindow(
TEXT("BUTTON"), TEXT("eee"),
WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON,
1250, 300, 80, 40,
hwnd, (HMENU)BUTTON_ID6, hInstance, NULL
);
if (hwnd == NULL) return -1;
while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
return msg.wParam;
}
Re: カメラ映像の表示方法
手元にWEBカメラ等が無かったので、とりあえず動画ファイルを全力で描画するサンプルを作ってみました。
子ウィンドウに描くとかは面倒くさいのでやってません。
子ウィンドウに描くとかは面倒くさいのでやってません。
#include <Windows.h>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
static HBITMAP g_hBitmap;
static HDC g_hBitmapDC;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
switch (message) {
case WM_CREATE:
hdc = GetDC(hWnd);
g_hBitmap = CreateCompatibleBitmap(hdc, 800, 600);
g_hBitmapDC = CreateCompatibleDC(hdc);
SelectObject(g_hBitmapDC, g_hBitmap);
ReleaseDC(hWnd, hdc);
return NOERROR;
case WM_DESTROY:
DeleteDC(g_hBitmapDC);
DeleteObject(g_hBitmap);
PostQuitMessage(0);
return NOERROR;
case WM_PAINT:
{
PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps);
BitBlt(hdc, 110, 10, 800, 600, g_hBitmapDC, 0, 0, SRCCOPY);
EndPaint(hWnd, &ps);
return NOERROR;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpCmdLine, int nCmdShow) {
HWND hwnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("opencv");
if (!RegisterClass(&winc)) return -1;
hwnd = CreateWindow(
TEXT("opencv"), TEXT("画面"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE,
0, 0, 1350, 800,
NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) return -1;
cv::VideoCapture reader("C:\\TEMP\\test.avi");
if (!reader.isOpened())
{
return -1;
}
while (true)
{
if (PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE))
{
break;
}
else if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// リアルタイムループ
cv::Mat image;
reader >> image;
// とりあえず、取得できなくなったら終了する
if (image.empty())
{
break;
}
BITMAPINFO bi;
ZeroMemory(&bi, sizeof bi);
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = image.cols;
bi.bmiHeader.biHeight = -image.rows;
bi.bmiHeader.biBitCount = image.channels() * 8;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biCompression = BI_RGB;
SetDIBits(g_hBitmapDC, g_hBitmap, 0, image.rows, image.data, &bi, DIB_RGB_COLORS);
InvalidateRect(hwnd, NULL, FALSE);
}
}
return 0;
}
Re: カメラ映像の表示方法
ありがとうございます。少し方法は違いますが自分でも作ってみました。しかし、webカメラ映像は読み込めるのに今回作っているプロジェクト(win32プロジェクト)ではaviutilでavi出力したファイルが読み込めませんでした。
しかし今回のプロジェクトとは別のプロジェクト(コンソールアプリケーション)では読み込むことが出来ました。
今回のプロジェクトで読み込めたのはAGデスクトップレコーダーでキャプチャーした動画ファイルは読み込むことが出来ました。
これは何が原因なのでしょか?
コードは以下になります。
Header.hには
以下の物を読み込んでいます。
#include<opencv2/opencv.hpp>
#include<opencv2/opencv_lib.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<windows.h>
#include <process.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <Commdlg.h>
#include <SDKDDKVer.h>
#include<iostream>
#include<stdio.h>
#define STATIC_ID0 00
#define BUTTON_ID1 0
#define BUTTON_ID2 1
#define BUTTON_ID3 2
#define BUTTON_ID4 3
#define BUTTON_ID5 4
#define BUTTON_ID6 5
#define BUTTON_ID7 6
しかし今回のプロジェクトとは別のプロジェクト(コンソールアプリケーション)では読み込むことが出来ました。
今回のプロジェクトで読み込めたのはAGデスクトップレコーダーでキャプチャーした動画ファイルは読み込むことが出来ました。
これは何が原因なのでしょか?
コードは以下になります。
Header.hには
以下の物を読み込んでいます。
#include<opencv2/opencv.hpp>
#include<opencv2/opencv_lib.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<windows.h>
#include <process.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include <Commdlg.h>
#include <SDKDDKVer.h>
#include<iostream>
#include<stdio.h>
#define STATIC_ID0 00
#define BUTTON_ID1 0
#define BUTTON_ID2 1
#define BUTTON_ID3 2
#define BUTTON_ID4 3
#define BUTTON_ID5 4
#define BUTTON_ID6 5
#define BUTTON_ID7 6
#include"Header.h"
using namespace cv;
using namespace std;
Mat imgMatCamera1;
Mat imgMatCamera2;
Mat imgMatAvi;
Mat imgMatSyn1;
Mat imgMatSyn2;
IplImage *imgFromOpenCV1 = NULL;
IplImage *imgFromOpenCV2 = NULL;
IplImage img1;
IplImage img2;
HWND hwnd;
HWND hwPic = NULL;
HDC hDC = NULL;
HDC hDCPic = NULL;
DWORD dwThread;
BITMAPINFO bmpInfo1;
unsigned long* bmpData1 = NULL;
BITMAPINFO bmpInfo2;
unsigned long* bmpData2 = NULL;
void iplTobmp(const IplImage*, BITMAPINFO&, unsigned long*);
unsigned int __stdcall CameraCaptureThread(PVOID pv);
HANDLE threadHandle1 = NULL;
BOOL endFlag1 = FALSE;
unsigned int __stdcall GuideThread(PVOID pv);
HANDLE threadHandle2 = NULL;
BOOL endFlag2 = FALSE;
//スレッド1起動関数
void function1(HWND hwnd) {
threadHandle1 = (HANDLE)_beginthreadex(
NULL,
0,
CameraCaptureThread,
NULL,
0,
(unsigned int*)&dwThread);
if (!threadHandle1) {
MessageBox(hwnd, TEXT("DEBUG"), TEXT("スレッド起動エラー"), MB_OK);
}
}
//スレッド2起動関数
void function2(HWND hwnd) {
threadHandle2 = (HANDLE)_beginthreadex(
NULL,
0,
GuideThread,
NULL,
0,
(unsigned int*)&dwThread);
if (!threadHandle2) {
MessageBox(hwnd, TEXT("DEBUG"), TEXT("スレッド起動エラー"), MB_OK);
}
}
//iplimageからbmp変換
void iplTobmp(const IplImage* srcIplImage, BITMAPINFO& bmpInfo, unsigned long* bmpData) {
int width = srcIplImage->width;
int height = srcIplImage->height;
ZeroMemory(&bmpInfo, sizeof(bmpInfo));
bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmpInfo.bmiHeader.biWidth = width;
bmpInfo.bmiHeader.biHeight = height;
bmpInfo.bmiHeader.biPlanes = 1;
bmpInfo.bmiHeader.biBitCount = 32;
bmpInfo.bmiHeader.biCompression = BI_RGB;
unsigned long pixel;
unsigned char r, g, b;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
b = srcIplImage->imageData[srcIplImage->widthStep * i + j * 3];
g = srcIplImage->imageData[srcIplImage->widthStep * i + j * 3 + 1];
r = srcIplImage->imageData[srcIplImage->widthStep * i + j * 3 + 2];
pixel = 0x00000000;
pixel = (r << 16) + (g << 8) + b;
bmpData[j + (height - i - 1) * width] = pixel;
}
}
}
//カメラ映像の表示
unsigned int __stdcall CameraCaptureThread(PVOID pv) {
VideoCapture cap1(0);
if (!cap1.isOpened()) {
return -1;
}
while (1){
if (endFlag1 == TRUE) {
break;
}
cap1 >> imgMatCamera1;
imgMatSyn1 = imgMatCamera1;
img1 = imgMatSyn1;
imgFromOpenCV1 = &img1;
//メモリを確保
if (bmpData1 != NULL) {
HeapFree(GetProcessHeap(), 0, bmpData1);
}
bmpData1 = (LPDWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, imgFromOpenCV1->width * imgFromOpenCV1->height * 4);
//iplImageからDIBへ変換
iplTobmp(imgFromOpenCV1, bmpInfo1, bmpData1);
//ここで描画
StretchDIBits(hDC,
15, 20, imgFromOpenCV1->width*1.3, imgFromOpenCV1->height*1.3,
0, 0, imgFromOpenCV1->width, imgFromOpenCV1->height,
bmpData1, &bmpInfo1, DIB_RGB_COLORS, SRCCOPY);
}
return 0;
}
//動画の表示
unsigned int __stdcall GuideThread(PVOID pv) {
//VideoCapture cap12(0);
VideoCapture video("C:\\Users\tatebe riku\\Documents\\Visual Studio 2013\\Projects\\Win32Project1\\Win32Project1\\ddd.avi");
//if (!cap12.isOpened()) {
//return -1;
//}
if (!video.isOpened()) {
MessageBox(hwnd, TEXT("DEBUG"), TEXT("ファイルopenエラー"), MB_OK);
return -1;
}
while (1){
if (endFlag2==TRUE) {
break;
}
//cap12 >> imgMatCamera2;
video >> imgMatAvi;
//imgMatSyn2 = imgMatCamera2 +imgMatAvi;
img2 = imgMatAvi;
imgFromOpenCV2 = &img2;
//メモリを確保
if (bmpData2 != NULL) {
HeapFree(GetProcessHeap(), 0, bmpData2);
}
bmpData2 = (LPDWORD)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, imgFromOpenCV2->width * imgFromOpenCV2->height * 4);
//iplImageからDIBへ変換
iplTobmp(imgFromOpenCV2, bmpInfo2, bmpData2);
//ここで描画
StretchDIBits(hDC,
15, 20, imgFromOpenCV2->width*1.3, imgFromOpenCV2->height*1.3,
0, 0, imgFromOpenCV2->width, imgFromOpenCV2->height,
bmpData2, &bmpInfo2, DIB_RGB_COLORS, SRCCOPY);
}
return 0;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
hwPic = GetDlgItem(hwnd, STATIC_ID0);
hDC = GetDC(hwPic);
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_COMMAND:
switch (LOWORD(wp)) {
case BUTTON_ID1:
function1(hwnd);
break;
case BUTTON_ID2://開始
endFlag1 = TRUE;
WaitForSingleObject(threadHandle1, INFINITE);
CloseHandle(threadHandle1);
if (imgFromOpenCV1 != NULL){
HeapFree(GetProcessHeap(), 0, bmpData1);
}
if (threadHandle2 != NULL) {
MessageBox(hwnd, TEXT("DEBUG"), TEXT("スレッド起動エラー"), MB_OK);
//break;
}
function2(hwnd);
break;
case BUTTON_ID3://終了
break;
case BUTTON_ID4:
break;
case BUTTON_ID5:
break;
case BUTTON_ID6:
break;
}
return 0;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
//ウィンドウの設定
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("opencv");
if (!RegisterClass(&winc)) return -1;
hwnd = CreateWindow(
TEXT("opencv"), TEXT("Training System"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE,
0, 0, 1350, 800,
NULL, NULL, hInstance, NULL);
CreateWindow(
TEXT("STATIC"), NULL,
WS_CHILD | WS_VISIBLE | WS_BORDER | SS_BITMAP ,
0, 0, 870, 660,
hwnd, (HMENU)STATIC_ID0, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("WebCamera start-up"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
900, 80, 250, 50,
hwnd, (HMENU)BUTTON_ID1, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("Sample display"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
900, 400, 150, 50,
hwnd, (HMENU)BUTTON_ID2, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("Sample Exit"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
1170, 400, 150, 50,
hwnd, (HMENU)BUTTON_ID3, hInstance, NULL);
CreateWindow(
TEXT("STATIC"), TEXT("Select Level"),
WS_CHILD | WS_VISIBLE | WS_BORDER ,
880, 220, 450, 100,
hwnd, NULL, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("Beginner"),
WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON,
900, 250, 120, 50,
hwnd, (HMENU)BUTTON_ID4, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("Intermediate"),
WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON,
1050, 250, 120, 50,
hwnd, (HMENU)BUTTON_ID5, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("Advanced"),
WS_CHILD | WS_BORDER | WS_VISIBLE | BS_AUTORADIOBUTTON,
1200, 250, 120, 50,
hwnd, (HMENU)BUTTON_ID6, hInstance, NULL);
CreateWindow(
TEXT("BUTTON"), TEXT("Judge"),
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
1200, 500, 120, 50,
hwnd, (HMENU)BUTTON_ID7, hInstance, NULL);
if (hwnd == NULL) return -1;
while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
return msg.wParam;
}
Re: カメラ映像の表示方法
opencvのプロジェクトはコンソールアプリケーションですね。
映像表示のプロジェクトはwin32プロジェクトですね。
これらの混在には工夫がいります。
http://independence-sys.net/main/?p=2612
に記述がありますがめんどうです。
私のホームページには混在する方法がかいてありますが(win32プロジェクトでコンソールアプリケーションを動かす)opencvは試したこはありません。(OpenCVのVersionとコードを提示頂ければテストしてみれますが)
http://cswin10.nisinippon.com/cs/cs1/vs ... /dx01.html
映像表示のプロジェクトはwin32プロジェクトですね。
これらの混在には工夫がいります。
http://independence-sys.net/main/?p=2612
に記述がありますがめんどうです。
私のホームページには混在する方法がかいてありますが(win32プロジェクトでコンソールアプリケーションを動かす)opencvは試したこはありません。(OpenCVのVersionとコードを提示頂ければテストしてみれますが)
http://cswin10.nisinippon.com/cs/cs1/vs ... /dx01.html
Re: カメラ映像の表示方法
すみませんが、今何が問題なのかよくわかりません。ttb さんが書きました:ありがとうございます。少し方法は違いますが自分でも作ってみました。しかし、webカメラ映像は読み込めるのに今回作っているプロジェクト(win32プロジェクト)ではaviutilでavi出力したファイルが読み込めませんでした。
しかし今回のプロジェクトとは別のプロジェクト(コンソールアプリケーション)では読み込むことが出来ました。
今回のプロジェクトで読み込めたのはAGデスクトップレコーダーでキャプチャーした動画ファイルは読み込むことが出来ました。
これは何が原因なのでしょか?
もう少し整理して書いてもらえないでしょうか?
win32 プロジェクトのことでしょうか?コードは以下になります。
コンソールアプリケーションの方はどうなっていますか?
Re: カメラ映像の表示方法
Mathさん
opencvのバージョンは2.4.9です。
結城紬さん
問題になっているのは今回作成したwin32プロジェクトにおいてopencvのVideoCapture関数で再生できない動画ファイルが存在するということです。
具体的にはAviUtilでavi出力したものが再生できず困っています。
そこで動画ファイル自体に問題があるのかと思い、別で作成していたコンソールアプリケーションで再生したところ再生できたので動画自体には問題はないという判断に至りました。
今回作りたいプログラムはwin32プロジェクトの方なので再生できず困っています。
opencvのバージョンは2.4.9です。
結城紬さん
問題になっているのは今回作成したwin32プロジェクトにおいてopencvのVideoCapture関数で再生できない動画ファイルが存在するということです。
具体的にはAviUtilでavi出力したものが再生できず困っています。
そこで動画ファイル自体に問題があるのかと思い、別で作成していたコンソールアプリケーションで再生したところ再生できたので動画自体には問題はないという判断に至りました。
今回作りたいプログラムはwin32プロジェクトの方なので再生できず困っています。
Re: カメラ映像の表示方法
コードを見直していてファイルパスの一部に¥が一つ抜けているのを発見しました。
修正したところしっかりと再生することができました。
こんな簡単なミスでお騒がせして申し訳ありませんでした。
また、協力していただいた皆様、本当にありがとうございました。
修正したところしっかりと再生することができました。
こんな簡単なミスでお騒がせして申し訳ありませんでした。
また、協力していただいた皆様、本当にありがとうございました。