当初の目的であったOpenCVでのゲーム操作をやってみた
今回のターゲットはDDONのソーサラースペリングを自動化
既にDDONは引退してしまったため、DDONを使ってOpenCVの自動化を試してみた
いろいろ試行錯誤して、こんな感じに
流れとしては↓
OpenCVでデスクトップキャプチャ
|
DDONのソーサラー詠唱に合わせ、魔法陣の位置をキャリブレーション
|
魔法陣の位置をROIし、スペリングの光っている玉の位置を検出
|
マウスのカーソルを光っている玉の方向に自動移動
#include <iostream>
#include <opencv2/core/core.hpp>
#include <windows.h>
#include <string.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
int main()
{
int center_x = 0, center_y = 0;
HWND desktop;
RECT rc;
POINT pt;
cv::Point max_pt1;
desktop = GetDesktopWindow();
GetWindowRect(desktop, &rc);
cv::VideoCapture cap(2);
cap.set(CV_CAP_PROP_FRAME_WIDTH, rc.right);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, rc.bottom);
if (!cap.isOpened()) return -1;
//マッチングファイルの読み込み
cv::Mat green_img = cv::imread("matt.png", 1);
if (green_img.empty()) return -1;
cv::Mat magic_img = cv::imread("matt1.png", 1);
if (magic_img.empty()) return -1;
while (1)
{
cv::Mat frame;
cap >> frame; // get a new frame from camera
cv::Mat img1(frame, cv::Rect(max_pt1.x, max_pt1.y, magic_img.cols, magic_img.rows));
cv::Mat result_img;
// テンプレートマッチング
cv::matchTemplate(img1, green_img, result_img, CV_TM_CCOEFF_NORMED);
// 最大のスコアの場所を探す
cv::Rect roi_rect(0, 0, green_img.cols, green_img.rows);
cv::Point max_pt;
double maxVal;
cv::minMaxLoc(result_img, NULL, &maxVal, NULL, &max_pt);
// 最大スコアの座標
center_x = (max_pt.x + green_img.cols / 2) - (magic_img.cols / 2);
center_y = (max_pt.y + green_img.rows / 2) - (magic_img.rows / 2);
// 最大スコアの結果を表示
//std::cout << "移動X=" << center_x << ",移動Y=" << center_y << "), score=" << maxVal << std::endl;
if (maxVal > 0.95)
{
//マウスの現在の座標を取得する
GetCursorPos(&pt);
//マウスの位置を移動する
SetCursorPos(pt.x + center_x*0.4, pt.y + center_y*0.4);
//Sleep(100);
//std::cout << "移動X=" << center_x << ",移動Y=" << center_y << "), score=" << maxVal << std::endl;
}
cv::imshow("画像マッチング", img1);
int key = cv::waitKey(1);
if (key == 'q')
{
break;//whileループから抜ける.
}
else if (key == 's')
{
//フレーム画像を保存する.
cv::imwrite("img.png", frame);
}
else if (key == 'c')
{
cv::Mat result_img1;
// テンプレートマッチング
cv::matchTemplate(frame, magic_img, result_img1, CV_TM_CCOEFF_NORMED);
// 最大のスコアの場所を探す
cv::Rect roi_rect1(0, 0, magic_img.cols, magic_img.rows);
double maxVal1;
cv::minMaxLoc(result_img1, NULL, &maxVal1, NULL, &max_pt1);
if (maxVal1 < 0.8)
{
continue;
}
}
}
cv::destroyAllWindows();
return 0;
}
起動直後は詠唱の場所がわからないため、matt1.pngというファイルに詠唱画像を入れておき、Cボタンを押すことで座標を特定させる
画像マッチングウィンドウで無事詠唱の座標が特定されたことがわかる
結果としては、
ソーサラーの詠唱が始まり、スペリング入力画面にすると自動的に玉の方向にマウスを動かすことに成功した
もともと、スペリング中はマウスカーソルは出ないしプレイに差支えはなく、また自動でスペリング入力をしてくれ、スペリングをやめるとマウスの自動移動もなくなるので便利化にはなったが、スピード的には手入力の方が若干早いため慣れている人は手入力の方が良いという悲しい内容に
繰り返し作業の要素が強すぎてDDONは辞めてしまったが、OpenCVを活用してダンジョン周回、お金稼ぎも可能と思われる
いろいろ試行錯誤して、こんな感じに
流れとしては↓
OpenCVでデスクトップキャプチャ
|
DDONのソーサラー詠唱に合わせ、魔法陣の位置をキャリブレーション
|
魔法陣の位置をROIし、スペリングの光っている玉の位置を検出
|
マウスのカーソルを光っている玉の方向に自動移動
#include <iostream>
#include <opencv2/core/core.hpp>
#include <windows.h>
#include <string.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
int main()
{
int center_x = 0, center_y = 0;
HWND desktop;
RECT rc;
POINT pt;
cv::Point max_pt1;
desktop = GetDesktopWindow();
GetWindowRect(desktop, &rc);
cv::VideoCapture cap(2);
cap.set(CV_CAP_PROP_FRAME_WIDTH, rc.right);
cap.set(CV_CAP_PROP_FRAME_HEIGHT, rc.bottom);
if (!cap.isOpened()) return -1;
//マッチングファイルの読み込み
cv::Mat green_img = cv::imread("matt.png", 1);
if (green_img.empty()) return -1;
cv::Mat magic_img = cv::imread("matt1.png", 1);
if (magic_img.empty()) return -1;
while (1)
{
cv::Mat frame;
cap >> frame; // get a new frame from camera
cv::Mat img1(frame, cv::Rect(max_pt1.x, max_pt1.y, magic_img.cols, magic_img.rows));
cv::Mat result_img;
// テンプレートマッチング
cv::matchTemplate(img1, green_img, result_img, CV_TM_CCOEFF_NORMED);
// 最大のスコアの場所を探す
cv::Rect roi_rect(0, 0, green_img.cols, green_img.rows);
cv::Point max_pt;
double maxVal;
cv::minMaxLoc(result_img, NULL, &maxVal, NULL, &max_pt);
// 最大スコアの座標
center_x = (max_pt.x + green_img.cols / 2) - (magic_img.cols / 2);
center_y = (max_pt.y + green_img.rows / 2) - (magic_img.rows / 2);
// 最大スコアの結果を表示
//std::cout << "移動X=" << center_x << ",移動Y=" << center_y << "), score=" << maxVal << std::endl;
if (maxVal > 0.95)
{
//マウスの現在の座標を取得する
GetCursorPos(&pt);
//マウスの位置を移動する
SetCursorPos(pt.x + center_x*0.4, pt.y + center_y*0.4);
//Sleep(100);
//std::cout << "移動X=" << center_x << ",移動Y=" << center_y << "), score=" << maxVal << std::endl;
}
cv::imshow("画像マッチング", img1);
int key = cv::waitKey(1);
if (key == 'q')
{
break;//whileループから抜ける.
}
else if (key == 's')
{
//フレーム画像を保存する.
cv::imwrite("img.png", frame);
}
else if (key == 'c')
{
cv::Mat result_img1;
// テンプレートマッチング
cv::matchTemplate(frame, magic_img, result_img1, CV_TM_CCOEFF_NORMED);
// 最大のスコアの場所を探す
cv::Rect roi_rect1(0, 0, magic_img.cols, magic_img.rows);
double maxVal1;
cv::minMaxLoc(result_img1, NULL, &maxVal1, NULL, &max_pt1);
if (maxVal1 < 0.8)
{
continue;
}
}
}
cv::destroyAllWindows();
return 0;
}
起動直後は詠唱の場所がわからないため、matt1.pngというファイルに詠唱画像を入れておき、Cボタンを押すことで座標を特定させる
画像マッチングウィンドウで無事詠唱の座標が特定されたことがわかる
結果としては、
ソーサラーの詠唱が始まり、スペリング入力画面にすると自動的に玉の方向にマウスを動かすことに成功した
もともと、スペリング中はマウスカーソルは出ないしプレイに差支えはなく、また自動でスペリング入力をしてくれ、スペリングをやめるとマウスの自動移動もなくなるので便利化にはなったが、スピード的には手入力の方が若干早いため慣れている人は手入力の方が良いという悲しい内容に
繰り返し作業の要素が強すぎてDDONは辞めてしまったが、OpenCVを活用してダンジョン周回、お金稼ぎも可能と思われる