スマフォゲーをOpenCVで操作出来ないか試してみた
FFGMや時のドラゴン等のスタミナ要素が無いゲームをやっているとひたすら同じ作業の繰り返しで、レベル上げがめんどくさくなってくる
OpenCVを使って画像判別しながらスマフォ操作すればいいんじゃないかといろいろ試してみた
Android Opencvを使うためにいろいろインストール
・JDK
・JRE
・Eclipse
・Android SDK
・Android Development Tool (ADT)
・OpenCV packege for Android
なんとかEcliseを使ってAndroid上でOpencvを実行することに成功!
しかし、ゲームアプリ上でタッチイベントがうまく動かない・・・
Google先生に確認すると、Androidはセキュリティ上、他のアプリを操作出来ないようになっているとのこと
仕方がないからWindowsのOpencv使ってADB SHELLからスマフォ操作することにした
流れは、
スマフォのスクリーンショットを撮影、保存
|
画像をPCに移動
|
予め作成しておいた目的の画像(おまかせボタン)がマッチングしたらそのボタンの座標を取得しTap命令をPCからスマフォに送る
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
int main(int argc, char *argv[])
{
int key, tap_x, tap_y;
FILE *file;
// テンプレート画像
cv::Mat tmp_img = cv::imread("omakase.png", 1);
if (tmp_img.empty()) return -1;
while (1){
system("adb shell screencap -p /sdcard/screen.png");
system("adb pull /sdcard/screen.png");
// 探索画像
cv::Mat search_img = cv::imread("screen.png", 1);
if (search_img.empty()) continue;
cv::Mat result_img;
// テンプレートマッチング
cv::matchTemplate(search_img, tmp_img, result_img, CV_TM_CCOEFF_NORMED);
// 最大のスコアの場所を探す
cv::Rect roi_rect(0, 0, tmp_img.cols, tmp_img.rows);
cv::Point max_pt;
double maxVal;
cv::minMaxLoc(result_img, NULL, &maxVal, NULL, &max_pt);
// マッチング度合で処理を変更
if (maxVal < 0.6) continue;
// 最大スコアの場所
roi_rect.x = max_pt.x;
roi_rect.y = max_pt.y;
// 最大スコアの中央値
tap_x = max_pt.x + tmp_img.cols / 2;
tap_y = max_pt.y + tmp_img.rows / 2;
// 最大スコアの結果を表示
std::cout << "(TAP_X=" << tap_x << ",TAP_Y=" << tap_y << ", x=" << max_pt.x << ", y=" << max_pt.y << "), score=" << maxVal << std::endl;
// 探索結果の場所に矩形を描画
cv::rectangle(search_img, roi_rect, cv::Scalar(0, 0, 255), 3);
// 結果の画像を表示
cv::namedWindow("result", CV_WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
cv::imshow("result", search_img);
char *passbuf = "adb shell input touchscreen tap %d %d",tap_x,tap_y;
printf(passbuf);
key = cvWaitKey(1);
if (key == 'q') {
break;
}
else if (key == 's'){
cv::imwrite("output.png", search_img);
}
}
}
スマフォのスクリーンショット(生画像)
おまかせ攻撃画像
一番苦労したのは変数をadb shellで指定するところ
当初、tap_x,tap_yと変数をそのまま指定していたがうまく代入されず、グーグル先生の指導のもと%dに代入してprintfすれば行けることを発見した
後は状況に応じて、判別する画像、その際の動作を組み込めば自動レベルアップを簡単に実行することが出来るだろう
次回はOpenCVではない番外編
UWSCで同じようにスマフォを操作してみる