Androidのビルド済みapkファイルを実機に書き込む(おそらく)一番簡単な方法

今日はプログラミング後のお話。

Androidアプリの開発は、Android Studioといった専用IDEだけでなく、UnityやUnreal Engineなどのゲームエンジンからもできるようになり、ますます敷居が低くなっています。
それらのツールから作成したアプリをビルドすると、apkファイル(Windowsでいうexeみたいなもの)が出来上がりますが、これを書き込むことで作成したアプリをAndroid端末で実行できるようになります。

ただ、すでにapkファイルが出来上がっているのに、いちいち開発環境を開き、ビルドして書き込むのは面倒です。
そこで、以下の手順を
1. gmailでビルドしたapkファイルを添付し、自分自身にメールを送りましょう。
2. Android端末でgmailアプリから送ったメールを開き、添付ファイルのリンクを選択します。
3. ダウンロード後にインストールの確認通知が来るので、許可すると実機にインストールされます。

…これだけ

以上の3ステップでビルド済みのapkファイルがインストールできます。
※事前に、セキュリティ設定の「開発元不明のアプリ」にはチェックしておきましょう。

(今のところgmailのみで確認。ほかのメールサービスについては未検証ですが、ファイル添付ができるものなら、サイズ上限内であれば可能かと)
gmailは25MBの上限がありますが、それ以上のファイルはgoogleドライブにアップすることで対応できます。

デメリットとしては、以下の点があげられるかと
1. インターネット環境につながっていないと実行できない
2. 外部にアプリが漏れてしまう可能性がある

ちなみに、実機へapkを書きこむ手法は他にもいくつかあります。
apkファイルをAndroid端末(実機)にインストールする方法


もしネット上でファイルをやり取りするのに問題がなければ、お試しあれ(^-^)/

テーマ : Android
ジャンル : 携帯電話・PHS

UnityでOpenCV その3

最近、ブログの更新がtwitter連携ばかりですいません((´・ω・`;))
今日は久しぶりに、UnityOpenCVの続きを書こうと思います。
今回はいよいよ、画像処理のメインの一つ「輪郭抽出」をやっていきます。

【前回のおさらい】
この記事を参照。
前回は二値化処理がメインでした。
・二値化処理は、濃淡のある画像(グレー)を、一定の閾値で白黒(モノクロ)画像にする
・グレー画像のMatに、Imgproc.thresholdメソッドを施すだけ
・自動で閾値を判断させる(適応的閾値処理)には、Imgproc.adaptiveThresholdメソッドを使う


【輪郭抽出とは】
輪郭抽出とは、画像の特定の領域の境界線、つまり輪郭を求めるための処理です。
ただ、どこの領域を選ぶかが非常に重要で、適切に選べないと思ったように輪郭が抽出できない、あるいは処理が重いといった結果となります。

【抽出の前処理】
この輪郭抽出の領域をアルゴリズムに与えるための処理として、前回の二値化処理が出てきたわけです。
ただ、単純な二値化では細かいノイズや輪郭のギザギザ、余計な部分などが残ることも多く、輪郭が思うように抽出できないこともあります。

そこで適応的閾値処理でフィルタ(ガウシアンフィルタメディアンフィルタ)をかけて、平滑化(スムージング)を施すことで、細かい領域を省いて抽出したい部分を強調することができます。

フィルタをかけるだけでなく、二値化処理で現れた画素領域自体を膨張、あるいは収縮することで細かい部分を取り除く手法もよく使われます。膨張処理はImgproc.erode、収縮処理はImgproc.dilateメソッドを使います。
また、これらの処理を繰り返して抽出範囲を得るオープニング・クロージング処理もあり、これらはImgproc.morphologyExメソッドを使います。

【抽出処理】
前述の処理を施してようやく領域がわかったところで、いよいよ輪郭を求める処理に入ります。
OpenCVではImgproc.findContoursメソッドを使うだけで簡単に求められます。

輪郭は単にそれぞれの場所に点々と存在するだけでなく、輪郭の中にさらに輪郭が出てくることもあります(ちょうど等高線のようなイメージ)。そのため、輪郭抽出の方法もいくつかあり、外側だけを抜き取るか内側も含めるか、あるいは輪郭の各点(ピクセル)もそのまま記憶するかある程度近似するかをメソッド内で指定できます。

【輪郭線の近似】
輪郭線の近似は、主に直線近似凸包近似という手法があります。
前者は、ある距離以内の点を一直線にまとめて結ぶもので、グラフの近似曲線をつないでいくイメージに近いといえます。
後者は、輪郭をすべて含む最小の凸図形で囲む方式で、「輪ゴムで囲うようにぴったりと囲んだ線の図形」とたとえられます。
(もちろん、近似せずに各点からなる輪郭線をそのまま使うのもOK)

輪郭の各点を近似して取得するのはfindContoursメソッドで行いますが、直線近似はImgproc.approxPolyDP、凸包近似はImgproc.convexHullメソッドで求めます。

と、技術的な解説が長くなってしまったため、実装については次の記事で解説します。

【参考】
画像処理の流れについては、こちらの記事がわかりやすいと思います。
機械学習のためのOpenCV入門

適応的閾値処理のフィルタについては、こちらを参照。
ガウシアンフィルタメディアンフィルタ

平滑化処理の膨張・収縮などについてはこちらを参照。
膨張・収縮・オープニング・クロージング

ImgProc.findContoursの動作については以下を参照
opencv 2.2 documentation - OpenCV.jp
findContours関数の仮まとめ

画素領域の構造ツリーと処理に関しては、ラベリングを参照。
イメージングソリューション ラベリング

テーマ : ゲーム開発
ジャンル : コンピュータ

そういえば、UnityのMathfって

クラスじゃないんですね。

と、何故わざわざこんな事を書くかというと、実は拡張メソッドを入れられなかったからでした。
少し前にMathfに拡張メソッドを入れようとしたのですが、スクリプトを入れてもなぜか一向にメソッドが出てきませんでした。
(後日、ただの勘違いだとわかりましたが(汗))

ちなみに、拡張メソッドの書き方はこんな感じ。

//拡張メソッドの一例(Vector3の場合)
public static class Vector3Extend
{
public static void ExtendMethodSample(this Vector3 self, Vector3 a, vector3 b)
{
//(2番目以降の引数は、自由に決められる)
//書きたい処理
}
}


で、小一時間悩んだ挙句、Mathfのソースを見てみると
Unity_Vector3.png

「これ、構造体だったのか。。。」

クラスじゃないから拡張メソッドを入れられないのかと盛大に勘違いしていましたが、
結局、拡張メソッドはインスタンスからしか呼び出せない仕様になっているのを忘れていただけでした...orz

なので、Mathfに拡張メソッドを入れたい場合は、下のように使います。

//Mathfの拡張メソッド
public static class MathfExtend
{
public static void Sample(this Mathf self)
{
//書きたい処理
}
}

//...

//実際の処理
Mathf math = new Math();
mathf.Sample();


結局、拡張メソッドを使う場合はインスタンスを作らないといけないのに、いつものMathf構造体(のメソッド)と同じようにクラスから直接呼び出そうとして参照されないだけでした...orz
そんなわけで、皆様も気を付けましょう(たぶん当方だけでしょうが(^_^;))

あ、Mathfがクラスではないのがちょっと意外でした。

テーマ : ゲーム開発
ジャンル : コンピュータ

覚えておくと(たぶん)便利な素敵設定たち(主にUnityのインスペクタ関連)

どうも、Reveです。
今回もUnity関係の備忘録兼Tipsです。
(それにしても、最近の投稿がUnityばっかりですね(^-^;)。もう少し別の分野でも記事が書きたい...。)

Unityでは、インスペクタと呼ばれる3DCGなどオブジェクトの設定を確認・変更できるパネルがあります。
(インスペクタの画像)

これが少し工夫をすることで、自作のスクリプト内にあるフィールド(変数)の数値をIDE(統合開発環境)を開かずに編集できたり、使い勝手をよくすることができます。

インスペクタを拡張する理由】
ですが、何故インスペクタ上で変数を変えられるようにするのか。
一言でいえば、ちょっとした調整がすぐにできてとても便利だからです。

わざわざ「あのキャラクターの体力値をもう少し大きくしたい」といった小さな調整で、IDEからキャラに関するスクリプトを開いて数値を変えるのは時間も浪費しますし面倒です(最近のVisual Studioが特に重いもので...。まあ便利だから使いますがw)。

特に長いコードになると、変数を探す作業も時間がかかってしまい、ミスを犯す可能性も高くなるので、GUI上で変更する方がメリットが多いのです。

また、作成した後にUnityエディタ上でテストプレイなどをしてもらい、その場で値を調整してもらうといったことも可能なので、
プログラマでない人との共同作業にもうってつけなのです(さすがにコードを読ませて修正してもらうのはほぼ不可能なので)。

インスペクタを拡張する手法】
(C#前提です。Javascriptは知らん)

とりあえずフィールドなどに属性(Attribute)をつけるだけ。
また、変数の型によってもインスペクタ上での見え方が変化します。なお標準では、数値や文字を入力するフィールドが出てきます。

あるいは、CustomEditorを駆使してエディタ拡張をすれば独自のインスペクタも作成できるのですが、
長くなってしまうので今回は割愛。

【そもそも属性(Attribute)って?】
プログラムに関するメタデータ、砕けて言えば追加の設定を付けるものです。
詳細は以下のリンク先を参照

- ++C++; // 未確認飛行 C
(C#に関するサイトではトップクラスです)
http://ufcpp.net/study/csharp/sp_attribute.html

使い方も簡単で、フィールド変数やクラスなどの上につけたい属性を書くだけでOK

//...
[SerializeField] //属性(SerializeField:クラス内で宣言した変数が、インスペクタ上に反映)
int sampleField; //この変数がインスペクタ上に表示
//...


【各設定の効果】
では、属性の使い方も分かったところで、早速その効果を見てみましょう。
当方がよく使うものを中心にまとめてみました。

[Attribute]
SerializeField
- 変数の入力欄をインスペクタ上に表示 (public変数にした時と同じ効果)
- privateやprotectedなどでも表示可能
- デフォルト値を代入すると、入力欄にもその値が予め入れられる(変更可)
- Unity標準にはないクラス使う場合は、後述のSerializableと併用
System.Serializable
- クラスをインスペクタ上に表示できるようにする(構造体には使えない)
- (a)対象のクラスにこの属性をつけ、(b)このクラス型で宣言したフィールドにSerializeFieldを与えることで、このクラス内部の変数が表示される(アクセシビリティに注意)
Range
- 変数の設定できる範囲を指定
- 入力がスライダーバー形式に
Multilines(TextArea)
- テキスト(string)の複数行表示が可能(改行が反映される)
- 二者の違いは、右端で折り返すかどうか(TextAreaが折り返す)
Header
- 上にタイトルをつける
- 設定値のカテゴリ分けに便利
Tooltip
- 変数名が書かれた部分にマウスポインタを置くと、その説明文が表示される
- 説明文は引数で記載
RequireComponent(typeof("クラス名"))
- クラス自体に付属させる
- そのクラスに必要なクラスを指定できる
- この属性を付けたクラスをオブジェクトにつける際、必要なクラスがまだない場合は自動で一緒に取り付けてくれる。
- また、この属性付きクラスをつけたまま、要求される別のクラスを外そうとするとエラーメッセージが出る

[型宣言]
配列やリスト
- 要素数と、各要素の値を入力する
- 中の要素の表示/非表示が切り替え可能
bool型
- 入力がチェックボックス形式に
enum(列挙型)
- ドロップダウン形式
- enumを定義して、そのenum型の変数をpublic、またはSerializeField属性にする
Vector3(Vector2)、Rectなど一部のUnity標準クラス
- それぞれのクラスに応じた入力形式に

[そのほか]
UnityEngine.Events.UnityEvent
- 手軽にイベント(何かをきっかけに発生する処理)の実装が可能
- このクラスのフィールドを宣言し、そのフィールドがあるクラス内のメソッドでInvokeメソッドを呼び出せばイベント発生
- イベントの割り当て方は、uGUIでのボタンなどへのイベント設定と同じ方法
- UnityEventへ割り当てられるメソッドには制約があるため、それを配慮して中の処理を与えていく

//...
[SerializeField]
UnityEngine.Events.UnityEvent onSomethingHappen;
//...
void Update(){
if(条件を満たす){
if(onSomethingHappen != null) onSomethingHappen.Invoke(); //割り当てられたメソッドを上から順に処理
}
}


と、上記のAttributeをすべて一つに当てはめるとこうなります。
Attributes_Unity.png

ごちゃごちゃじゃねーかw
まあ、こんな風にいっぺんに盛り込む必要はないのですが、仕様に応じて適したものを使っていけば
ゲーム開発の効率も断然よくなる(ようになるかも)。
この情報が開発の手助けに少しでも慣れば幸いです。

続きを読む

テーマ : ゲーム開発
ジャンル : コンピュータ

Unityで角度制限付きの回転を行う方法

どうも、久しぶりの更新になってしまいました。
今日は備忘録を兼ねたUnityの使い方です。

Unityを使ってゲーム作りをしていると、回転が難しいという話があると思います。
実際、スクリプトでの回転操作はなかなか難しいですし、感覚がうまくつかめないところがあると思います。
特に、角度に制限を付けて回転をさせるのはネットでもなかなか見つからず、実装に苦戦している方も少なくないのではないでしょうか。

そこで、当方の実装方法を(備忘録を兼ねて)公開しようと思います。
あまり良い方法ではないかもしれませんが、もし参考になれば幸いです。

【方法とプログラム】
では、さっそくソースからどうぞ。
なお、ここでは前提として上下左右(XとY軸)の方向のみの回転

//現在の角度
Vector2 rotateAngle;
//制限する角度量
Vector2 rotateLimit;

void Update()
{
//対応するキー(デフォルトではa,s,w,dキー)を押すと、このスクリプトを付けた自身が回転
rotateProcess(new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")), 10f); //2番目の引数は、好きな値で
}

void rotateProcess(Vector2 delta, float speed)
{
//回転する方向と速度を決定
Vector2 rotVector = delta.normalized * speed * Time.deltaTime;

float rotH = getRotateAngle(rotVector.x, ref rotateAngle.x, rotateLimit.x / 2);
float rotV = getRotateAngle(-rotVector.y, ref rotateAngle.y, rotateLimit.y / 2);

//砲塔を回転
transform.rotation = Quaternion.AngleAxis(rotateAngle.x, transform.up) * Quaternion.AngleAxis(rotateAngle.y, transform.right);
//transform.Rotate(rotV, rotH, 0); //こちらは失敗
}

float getRotateAngle(float rotDelta, ref float angle, float rotMax = 90)
{
float result = rotDelta;

//予定の回転角度
float nextRot = angle + rotDelta;
//回転できる最大角度を超えたら
if (nextRot > rotMax)
{
result = rotMax - angle;
}
//回転できる最低角度を超えたら
else if (nextRot < -rotMax)
{
result = -rotMax - angle;
}

//回転後の角度も渡しておく
angle += result;
return result;
}


主な手順は以下の二つです。
1. 今の回転角度を求める
2. 1. で求めた角度をもとに、Quaternion.AngleAxitメソッドで回転させる

まず、1. は自作メソッドのgetRotateAngleから求めています。
引数は、左から (回転させたい角度量)、(回転前の角度)、(最大/最小角の絶対値) となっています。
ここでは、2番目の回転前の角度に、1番目の角度量を足して回転後の角度を求め、それが角度の制限値を超えていたら制限に収まるように回転量を調整しています。

戻り値は回転の角度量ですが、2番目の引数が参照(ref)となっているため、回転後の角度値も同時に求められます(実は、こちらの回転後の角度値を2.で使います)。

続いて2.の処理(自作のrotateProcessメソッド)ですが、回転量をQuaternionでもとめて、transform.rotationに入れています。
Quaternionは苦手な方もいらっしゃるかもしれませんが、Unity(に限らないかもしれませんが)で少し複雑な回転処理をさせようとすると必要になってきます。

とはいえ、今回使うのはQuaternion.AngleAxisメソッドのみです。
このメソッドは、引数に (回転させたい角度値)、(回転軸) を指定します。回転軸はVector3で指定するので、軸の伸びている方向と考えるとわかりやすいかもしれません。
オブジェクトに突き刺す軸を決めて、その軸を基に何度回転させるかといったイメージです。

今回のスクリプトは、上下と左右それぞれの回転をQuaternion.AngleAxisで求め、それをオブジェクトのrotationに代入して回転させます。AngleAxisメソッドで求められる回転は、上下、あるいは左右のみのものですが、実はQuaternion同士を掛け合わせると、二つの回転を反映した回転(Quaternion)が求められます。

そのため、以下の式で回転を求められるのです。
(オブジェクトのrotation) = (上下方向のQuaternion) * (左右方向のQuaternion)

なので、計算した角度とAngleAxisで求めたQuaternion同士を掛け合わせると角度制限を設けた回転が求められます。
今回は0°を中心に左右対称で角度の制限値を与えていますが、getRotateAngleの処理を少し変えれば非対称に角度の制限を設けることも可能です。

続きを読む

テーマ : ゲーム開発
ジャンル : コンピュータ

プロフィール

Reveちゃん

Author:Reveちゃん
コンビでやってます。
夢担当と技術担当がいます。

大学院卒業 → ロボットベンチャー(漆黒)就職 → 1年で退職 → ベトナムで仕事中(今ここ) → メディアアーティスト(未来☆)

リンクフリーです。

最新記事
最新コメント
月別アーカイブ
カテゴリ
アクセス数
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR