Opencvってデスクトップキャプチャサポートしてないの?
いよいよOpenCVを使って、ポイントサイトやゲームやらなにやらを操作してみよう!
と思ったが、サンプルコード集をいくら眺めてもデスクトップをキャプチャするようなコードは見当たらない
USBカメラをキャプチャするものばかり発見される
OK Webによさげなものがあったので実行してみると・・・
http://okwave.jp/qa/q7001914.html
スクリーンショットのような機能ができた
常に画面を更新したいため、while(1)で囲んでループさせると、うまい具合に常に画面を更新し続けることに成功
#include <windows.h>
#include <wingdi.h>
#include <string.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main(int argc, char **argv)
{
HWND desktop;
RECT rc;
HDC hdc;
BITMAPINFO bmpInfo;
LPDWORD lpPixel;
HDC hMemDC;
HBITMAP hBitmap;
BITMAP bmBitmap;
int width, height;
IplImage *convertIplImg;
// スクリーンの情報を得る
desktop = GetDesktopWindow();
GetWindowRect(desktop, &rc);
width = rc.right;
height = rc.bottom;
while (1){
// DIBの情報を設定する
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;
// DIBSection作成
hdc = GetDC(desktop);
hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, (void**)&lpPixel, NULL, 0);
hMemDC = CreateCompatibleDC(hdc);
SelectObject(hMemDC, hBitmap);
// スクリーンをDIBSectionにコピー
hdc = GetDC(desktop);
BitBlt(hMemDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
ReleaseDC(desktop, hdc);
// ビットマップ情報の取得
GetObject(hBitmap, sizeof(BITMAP), &bmBitmap);
// Bitmap構造体からIplImageへコピー
convertIplImg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 4);
memcpy(convertIplImg->imageData, bmBitmap.bmBits, width*height * 4);
cvFlip(convertIplImg, convertIplImg, 0);
// OpenCVウィンドウの作成&画像の表示
cvNamedWindow("Desktop Image", CV_WINDOW_AUTOSIZE);
cvShowImage("Desktop Image", convertIplImg);
// 終了処理
// cv::destroyAllWindows();
cvReleaseImage(&convertIplImg);
DeleteDC(hMemDC);
DeleteObject(hBitmap);
PostQuitMessage(0);
int key = cv::waitKey(1);
if (key == 'q')
{
break;//whileループから抜ける.
}
}
return 0;
}
ただ、この方法だとプログラム行も多く、スクリーンショットを常に連打し続けるようでなんとなく気持ち悪い
もう少し別の視点からデスクトップキャプチャを行えないか探してみた
超初心者がOpenCVを使って遊んでみた -4- デスクトップキャプチャ
と思ったが、サンプルコード集をいくら眺めてもデスクトップをキャプチャするようなコードは見当たらない
USBカメラをキャプチャするものばかり発見される
OK Webによさげなものがあったので実行してみると・・・
http://okwave.jp/qa/q7001914.html
スクリーンショットのような機能ができた
常に画面を更新したいため、while(1)で囲んでループさせると、うまい具合に常に画面を更新し続けることに成功
#include <windows.h>
#include <wingdi.h>
#include <string.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main(int argc, char **argv)
{
HWND desktop;
RECT rc;
HDC hdc;
BITMAPINFO bmpInfo;
LPDWORD lpPixel;
HDC hMemDC;
HBITMAP hBitmap;
BITMAP bmBitmap;
int width, height;
IplImage *convertIplImg;
// スクリーンの情報を得る
desktop = GetDesktopWindow();
GetWindowRect(desktop, &rc);
width = rc.right;
height = rc.bottom;
while (1){
// DIBの情報を設定する
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;
// DIBSection作成
hdc = GetDC(desktop);
hBitmap = CreateDIBSection(hdc, &bmpInfo, DIB_RGB_COLORS, (void**)&lpPixel, NULL, 0);
hMemDC = CreateCompatibleDC(hdc);
SelectObject(hMemDC, hBitmap);
// スクリーンをDIBSectionにコピー
hdc = GetDC(desktop);
BitBlt(hMemDC, 0, 0, width, height, hdc, 0, 0, SRCCOPY);
ReleaseDC(desktop, hdc);
// ビットマップ情報の取得
GetObject(hBitmap, sizeof(BITMAP), &bmBitmap);
// Bitmap構造体からIplImageへコピー
convertIplImg = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 4);
memcpy(convertIplImg->imageData, bmBitmap.bmBits, width*height * 4);
cvFlip(convertIplImg, convertIplImg, 0);
// OpenCVウィンドウの作成&画像の表示
cvNamedWindow("Desktop Image", CV_WINDOW_AUTOSIZE);
cvShowImage("Desktop Image", convertIplImg);
// 終了処理
// cv::destroyAllWindows();
cvReleaseImage(&convertIplImg);
DeleteDC(hMemDC);
DeleteObject(hBitmap);
PostQuitMessage(0);
int key = cv::waitKey(1);
if (key == 'q')
{
break;//whileループから抜ける.
}
}
return 0;
}
ただ、この方法だとプログラム行も多く、スクリーンショットを常に連打し続けるようでなんとなく気持ち悪い
もう少し別の視点からデスクトップキャプチャを行えないか探してみた
超初心者がOpenCVを使って遊んでみた -4- デスクトップキャプチャ