2012年2月26日日曜日

画像を回転する その2 - OpenCV for Android


前回は第5引数以下を省略したImgproc.warpAffine()メソッドについて実験しました。
今回は第5引数以下についても、それぞれの定数でどんな変化が見られるかやってみましょう。

Imgproc.warpAffine(Mat src, Mat dst, Mat M, Size dsize,
int flags, int borderMode, Scalar borderValue)

Mat src         処理したい元画像のMat
Mat dst         変換後Mat
Mat M          2×3の変換行列
Size dsize       変換後Matのサイズ
int flags         補間手法
int borderMode     ピクセル外挿手法
Scalar borderValue  定数境界モードで利用されるピクセル値


flagsについてはImgprocに用意された以下の定数から選択します。
定数は画像サイズを変更すると同じで、サイズが変わる場合の補完手法というところでしょうか。
また、それと組み合わせて使うオプションフラグが1つあります。

INTER_NEAREST  最近傍補間
INTER_LINEAR   バイリニア補間(デフォルト)
INTER_AREA     ピクセル領域の関係を利用したリサンプリング
INTER_CUBIC    4x4の近傍領域を利用するバイキュービック補間
INTER_LANCZOS4 8x8の近傍領域を利用するLanczos法の補間

WARP_INVERSE_MAP M が逆変換であることを意味する
(上記と組み合わせて使うオプションフラグ)


borderModeについてはImgprocに用意された以下の定数から選択します。
この定数で、回転することで空白となる部分の扱いが決まります。

BORDER_REPLICATE    画像境界の値を複製してコピー
BORDER_CONSTANT   borderValueで指定したピクセル値
BORDER_REFLECT     画像境界で反射するようにコピー
BORDER_WRAP       画像自身を繰り返しコピー
BORDER_REFLECT_101   画像境界で反射するようにコピー
BORDER_REFLECT101    画像境界で反射するようにコピー
BORDER_DEFAULT     画像境界で反射するようにコピー
BORDER_TRANSPARENT 元画像を変更しない

「BORDER_REFLECT」、「BORDER_REFLECT_101」、「BORDER_REFLECT101」、「BORDER_DEFAULT」の差は分かりませんでした。


borderValueについてはborderModeで「BORDER_CONSTANT」を選択した際に利用するピクセル値を決めます。
デフォルトではゼロです。


flagsについてはおそらくサイズ変更の時と同じだと思いますので、オプションフラグだけ試します。

元画像。

「INTER_LINEAR」で変換。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR);

オプションフラグを立ててみます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR | Imgproc.WARP_INVERSE_MAP);

なるほど。変換行列が逆に扱われて、変換結果も逆になるわけですね。


続いてborderModeについてやってみましょう。

画像境界の値がそのままコピーされます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REPLICATE);


指定したピクセル値で埋めます。
デフォルトではScalarがゼロで面白くないので、色をつけてみます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_CONSTANT,
  new Scalar(200, 150));


ミラー的な感じで埋めます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REFLECT);


回転することでBitmapの外側に出てしまった領域で埋めます。
スライドパズルが作れそうですね。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_WRAP);


「BORDER_REFLECT」と区別がつきません。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REFLECT_101);


「BORDER_REFLECT」と区別がつきません。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REFLECT101);


「BORDER_REFLECT」と区別がつきません。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_DEFAULT);


元画像をそのままにして変換先にだけ上書きします。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_TRANSPARENT);


ちなみに単なる回転だけではなく、サイズや形状が変わるとどうなるのでしょう。
ちょっとやってみましょう。

BORDER_REPLICATE

BORDER_REFLECT

BORDER_WRAP

まぁ想定通りの結果ですね。

という事で、定数が多いと長くなりますが、また別のメソッドでも使いそうなので、覚えておくと良いでしょう。

Read More...

T-01AにWindows Phone 7をインストールする!その4(WP7.5をインストールするつもりが文鎮化)


WP7を苦労して入れましたが、いまいち使い勝手が良くなさそうだったので、MangoことWP7.5をインストールしてみます。

手順は前回同様で、ROMファイル以下からダウンロードしました。
http://htcfanboys.com/download/mirolg/?action=view&file=3019


インストール開始!

・・・・

・・・・

・・・・

畜生ォ 持って行かれたァ!!!

進捗が46%のところでバッテリーが切れました。


現状を整理します。

T-01Aのライフはゼロ。
そしてOSが起動していないと充電出来ない。

つまり、高級文鎮の錬成に成功した。という事です。

充電器つないでる時の挙動を見てると、数秒充電すると起動して、使い果たすと電源が落ちる。
これを繰り返しているように見えます。


当然ダウンロードモードでも駄目。

起動したら即バッテリーを落として、またすぐ接続して数秒間の充電。
ってのを繰り返したら充電されたりしないかなぁ。。


まぁたぶん無理なので、バッテリーチャージャーでも買いますかね。



追記:バッテリーチャージャーを買って充電を済ませ、無事インストール完了しました。
教訓:充電大事。
Read More...

最終行が見えない?BloggerへSyntaxHighlighter導入 その2


どうやらSyntaxHighlighterにはバグがあるようで、最終行が見えなくなったりする模様。

いちいちスクロールしないと見えないのでは、ちょっと都合が悪いので対応します。

以下をCSSに追加。

.syntaxhighlighter {
  overflow-y: hidden !important;
}
.syntaxhighlighter table {
  margin-bottom: 1em !important;
}

6行目の後に空白が出来ましたね。
コレで大丈夫なはずです。

Read More...

コレ無しではコードは掲載出来ない!BloggerへSyntaxHighlighter導入


ソースをガンガン掲載するブログなので、SyntaxHighlighterぐらい使わなきゃ駄目でしょう。

ということでやってみます。

Bloggerの管理画面から[テンプレート]⇒[HTMLの編集]に進みます。

以下コードを<head>タグの直後に貼り付けます。

  

それだけです。
あとは記事を書く際に以下のように記述します。
????には「java」や「xml」など、中身を何の言語として解釈すれば良いかが入ります。

<pre class="brush:????">
中身
</pre>

過去の記事も直そうかなぁ。。

Read More...

2012年2月25日土曜日

T-01AにWindows Phone 7をインストールする!その3(ROM焼き)



ドライバがWindows 7に対応していなかったため、今回はWindows 7のXP Modeを利用して、うまくいくか試してみます。

XP Modeを使うのは初めてですが、部屋の奥にころがっているXPをサルベージしてくるよりは楽なのではないでしょうか。きっと。

取りあえずXP Modeで再度TG Downloaderのインストールからやりなおしてみましたが、思ったより軽く快適に動くんですね。
なかなかやるな。Microsoft。


ドライバのインストールまでうまくいったので、続きです。


1.ブートローダを焼く
TG Downloaderを起動し、[ポート変更]から「Toshiba Download Port 2」を選択します。



[Download Mode起動]をクリックするとT-01AのLEDが白く点灯します。

[ファイル選択]から「wp7boot.bin」を選択し、[ダウンロード開始]をクリックすると、T-01AのLEDがレインボーに輝き、自らの生まれ変わりを祝福します。





2.
ドライバのインストールQPSTのインストール

T-01Aのカメラボタンを押しながら電源ボタンを押すことで、WP7のダウンロードモードに入ります。
LEDは青く点灯します。

PCに接続し、「その2」で用意した「base_source_bootloader」のフォルダの中から手動でドライバをインストールします。
ちなみに、32bit用、64bit用で、それぞれXP用と7用らしきフォルダがありますが、Windows 7で試したところうまくいきませんでした。

引き続きXP Modeで作業し、「その2」で用意したQPSTをインストールします。


5.ROMを焼く

いよいよROM焼きです。
まずは、「すべてのプログラム」の「QPST」にある「QPST Configuration」を起動します。

[Ports]タブの[Add New Port]をクリックし、「USB/QC Diagnostic」のポートを追加します。


続いて、同じく「すべてのプログラム」の「QPST」にある「Software Download」を起動します。
メニューの[Options]から[Settings]を選択し、[NV Backup Directory]に「NV Backup」が選択されていることを確認します。
同じ画面で4つのチェックボックス全てにチェックを入れ、[ARMPRG to use for mobile already in download mode]のプルダウンで「QSD8650 2.0 (NAND flash)」を選択し、「OK」を押します。



[Software Download]タブの[Port]には「QPST Configurarion」で追加したポートを、[Phone Image]には、「base_source_bootloader」フォルダの「ENPRG8650.hex」をそれぞれ[Browse...]から選択します。


[Multi-Image]タブの[Image Folder]には「base_source_bootloader」フォルダを選択、[Boot System]のプルダウンで「Sec Boot 2.0」を選択し、「Advanced」ボタンをクリックします。



開いた画面で4つ既にチェックが入っているので、さらに[AMSS Apps Boot Loader]と[Microsoft WinMobile]と[DSP 1]にチェックを入れます。
ブートローダを入れなおしてる雰囲気ですが、理由は良く分かりません。
また、[AMSS Apps Image]にはチェックしないそうですが、これも理由は謎です。


[OK]で戻って、[Start]で開始です。


・・・


はい、なんかエラー出ました。

「Could Not Communicate with Flash Programmer」

いやいや、出来ないとか言うなよ。やるしかないんだよ。

ということで、ちょっと顔を引きつらせながら、もう一度各項目を選択し直して、再度実行してみたところ、うまくいきました。

XP Modeでやっているせいか、1時間以上かかりましたが、無事インストール完了しました。





Read More...

T-01AにWindows Phone 7をインストールする!その2(ドライバのインストール失敗)


T-01AへのWP7のインストールの続きです。

ちなみに、ここから先は高級文鎮を錬成する可能性がある危険極まりない作業です。
賢者の石を持っている方以外は、体の一部を持っていかれる覚悟で臨んで下さい。

バッテリーは必ず満タンで開始して下さい。
文鎮化の主な理由はきっとこれじゃないでしょうか。


1.必要なファイルを準備

ブートローダ
wp7boot.bin
http://www.4shared.com/zip/MOvoBKH2/upgrade_wp7_bootloader.html

ブートローダやドライバ
base_source_bootloader
http://www.4shared.com/rar/8Ru81lOT/base_source_bootloader.html

WP7のROM
flash.bin
http://www.4shared.com/rar/W5ZWSwDE/windows_phone_seven_1.html

Qualcomm Product Support Tools (QPST)
www.x-drivers.ru_qualcomm_qpst_2.7.323_(2008-09-19).zip
http://www.x-drivers.com/catalog/flash/mobile_phones/companies/qualcomm/models/qpst/12051.html


2.短絡を行う準備

バッテリー、SIMカードを取り外し、SIMカードのスロット部分に狙いを定めます。


シールのようなものなので、爪楊枝的なもので引っぺがします。


シールの下から出てきた丸い端子3つの内、左右2つを通電させる作業が短絡と呼ばれていて、T-01AへのカスタムROMのインストールではおなじみな作業なようです。
まぁようは、ショートさせるって事ですね。


3.ドライバをインストールする

SDカードを外した状態で、 左右2つを通電させながらT-01Aの電源を入れます。
ホッチキスの針などでやるのがメジャーなようですが、見当たらなかったのでアルミホイルを使ってみました。


うまくいくとダウンロードモードになり、LEDランプが緑に点灯します。
PCにT-01Aを接続し、自動ではうまくいかないので、手動でドライバのインストールを行います。

手動でやってもうまくドライバを読み込んでくれなかったので、ドライバが入った「TG01W Download Driver」フォルダ(自分の環境下ではC:\Program Files (x86)\TOSHIBA\TG01W Download Driver\)にある、「tsbtgdl0.inf」を開き「Pid_0d80」の部分を「Pid_0d6c」に置換します。

「ドライバソフトウェアの発行元を検証できません」というおなじみの警告が出るので、気にせずインストールします。

「ドライバーはこのプラットフォーム用ではありません」

え?

・・・・

はい。どうやらドライバがWindows 7に対応していないようです。

ということで、うまくいくかどうか分かりませんが、Windows 7のXPモードで試してみようと思います。


Read More...

T-01AにWindows Phone 7をインストールする!その1(TG Downloaderのインストール)


Nexus OneにカスタムROMを入れたりして遊んでいるうちに、T-01AにWP7が降って来て、それに飽きたころにはNexus OneにAndroid4.0が降って来て。。。
などと秋ぐらいには妄想していたのですが、早々に諦めてGalaxy Nexusを購入してしまいました。

もはやT-01AにWP7が入ったところで、メイン機として使うことはありません。
しかし、そこにカスタムROMがあるのなら、入れるしかないのです。

ということで、今回はT-01Aを代価としてWindows Phone 7を錬成してみようと思います。

まずはTG Downloaderのインストールから。


1.TG Downloaderをダウンロード

適当に検索すると色々と出てきますが、以下からダウンロードしました。
http://rapidshare.com/files/390234761/TG_Downloader.rar



2.インストール

解凍すると、中身は「setup.exe」というファイルのみなので実行します。
※ T-01AはまだPCに接続しないで下さい。

インストールが完了したら次はTG Download Driverのインストールです。
インストーラの起動にチェックを入れたまま完了します。

なんだか物々しい警告が。

自分の環境ではインストール先は以下。
C:\Program Files (x86)\TOSHIBA\TG01W Download Driver\

3.TG Downloaderの実行

デスクトップにショートカットが出来ているので、TG Downloaderを実行します。

まずは[Select Support Phone]というウインドウが開きますので、[TG01W]を選択します。

はい。何やらエラーです。
以下ウィンドウが何回も開いて、そして消えました。。


もう一度TG Downloaderを実行してみます。
特に問題無く起動しました。


Read More...

2012年2月22日水曜日

画像を回転する その1 - OpenCV for Android


画像を回転するには、アフィン変換という処理を行います。

Imgproc.getAffineTransform()メソッドで変換元と変換先の3点を指定して変換行列を計算し、Imgproc.warpAffine()メソッドで実際に変換を実行します。

Imgproc.getAffineTransform(List<Point> src, List<Point> dst)

List<Point> src  変換元の3点
List<Point> dst  変換先の3点

「Point」クラスはdouble値を2つメンバに持つクラスで、主に点座標を表します。


Imgproc.warpAffine(Mat src, Mat dst, Mat M, Size dsize,
    int flags, int borderMode, Scalar borderValue)

Mat src         処理したい元画像のMat
Mat dst         変換後Mat
Mat M          2×3の変換行列
Size dsize       変換後Matのサイズ
int flags         補間手法
int borderMode     ピクセル外挿手法
Scalar borderValue  定数境界モードで利用されるピクセル値


下の3つの引数は正直よく分からないのですが、省略出来るのでちょっと先送りします。


それでは実際にやってみましょう。
//変換元Matを使いまわすとエラーになるため、
//同じサイズのMatを用意します。
Mat dstMat = mat.clone();

//変換元の3点
List<Point> src_pt = new ArrayList<Point>();
src_pt.add(new Point(200, 200));
src_pt.add(new Point(250, 200));
src_pt.add(new Point(200, 100));

//変換先の3点
List<Point> dst_pt = new ArrayList<Point>();
dst_pt.add(new Point(300, 100));
dst_pt.add(new Point(300, 50));
dst_pt.add(new Point(200, 100));

//アフィン変換行列を計算
Mat affineTrans =
  Imgproc.getAffineTransform(src_pt, dst_pt);

//変換
Imgproc.warpAffine(mat, dstMat, affineTrans,
  dstMat.size());
今回から画面はlandscapeでキャプチャします。
まずは元画像。





変換後。



変換先の座標を少し変えて角度を変えてみます。
List<Point> dst_pt = new ArrayList<Point>();
dst_pt.add(new Point(300, 70));
dst_pt.add(new Point(300, 50));
dst_pt.add(new Point(200, 100));


3点であらわした三角形の形が変わると、画像も合わせて歪む訳ですね。
次回は後半3つの引数について実験してみます。



Read More...

2012年2月20日月曜日

画像を2値化する その2 - OpenCV for Android



引き続き画像を2値化です。
今回はImgproc.adaptiveThreshold()メソッドを使用してみます。

Imgproc.adaptiveThreshold(Mat src, Mat dst, double maxValue,
  int adaptiveMethod, int thresholdType, int blockSize, double C)

Mat src         処理したい元画像のMat
Mat dst          変換後Mat
double maxValue   条件を満たすピクセルに割り当てられる値
int adaptiveMethod  適応的閾値アルゴリズムの種類
int thresholdType   閾値処理の種類
int blockSize      閾値を算出するために使用する近傍領域のサイズ
double C        平均または加重平均から引かれる定数

はい、正直意味が分かりません。
この辺の知識経験の無さを実験でカバーするのがこのブログの趣旨なので気にしません。

ちなみに、blockSizeには2で割り切れない整数を利用します。
(偶数だと実行エラーとなります)

thresholdTypeについてはthreshold()のtypeに選択出来る定数の中の「THRESH_BINARY」か「THRESH_BINARY_INV」を選択出来ます。
adaptiveMethodについてはImgprocに以下定数が用意されています。

ADAPTIVE_THRESH_MEAN_C
閾値 T(x,y)は,(x,y)の近傍blockSize x blockSizeの平均からCを引いた値

ADAPTIVE_THRESH_GAUSSIAN_C
閾値 T(x,y)は,(x,y)の近傍blockSize x blockSizeの加重平均からCを引いた値

はい、やっぱり分かりませんね。

で在るが故に、実際にやってみましょう。
Imgproc.adaptiveThreshold(mat, mat, 255,
  Imgproc.ADAPTIVE_THRESH_MEAN_C,
  Imgproc.THRESH_BINARY, 7, 8);

Imgproc.adaptiveThreshold(mat, mat, 255,
  Imgproc.ADAPTIVE_THRESH_MEAN_C,
  Imgproc.THRESH_BINARY, 7, 2);

Imgproc.adaptiveThreshold(mat, mat, 255,
  Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
  Imgproc.THRESH_BINARY, 7, 8);

Imgproc.adaptiveThreshold(mat, mat, 255,
  Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C,
  Imgproc.THRESH_BINARY, 7, 2);


うーん。。あんまり差が分からないですね。

ちなみに版画みたいに見えるのはイソギンのせいです。
版画で画像検索すると似たようなのがたくさんhitして、だんだん版画にしか見えなくなってきました。




Read More...

画像を2値化する その1 - OpenCV for Android


画像を2値化するには、Imgproc.threshold()メソッドを使用します。

Imgproc.threshold(Mat src, Mat dst, double thresh, double maxval, int type)


 Mat src        処理したい元画像のMat
 Mat dst        変換後Mat
 double thresh     閾値
 double maxval     最大値
 int type        閾値処理の種類


typeについてはImgprocに以下定数が用意されています。


 THRESH_BINARY    閾値以下の値は0に,それ以外はmaxValに
 THRESH_BINARY_INV  閾値より大きい値は0に,それ以外はmaxValに
 THRESH_TRUNC     閾値より大きい値は閾値に,それ以外はそのままに
 THRESH_TOZERO    閾値より大きい値はそのままに,それ以外は0に
 THRESH_TOZERO_INV 閾値以下の値はそのままに,それ以外は0に


また、特殊な値として「THRESH_OTSU」というものもあります。
上記と組み合わせて使用し、その場合Otsuアルゴリズムとやらを使って最適な閾値を決定するため、threshは無効となります。
8bit画像にのみ有効なようです。


それでは実際にやってみましょう。
Imgproc.threshold(mat, mat, 100.0, 255.0,
  Imgproc.THRESH_BINARY);


∑(゚Д゚;)エーッ

ぜんぜん2値じゃないw
ということで、グレースケールに変換してから2値化してみます。
きっとそういうことです。


THRESH_OTSUを使って閾値を自動にします
Imgproc.threshold(mat, mat, 0.0, 255.0,
  Imgproc.THRESH_BINARY | Imgproc.THRESH_OTSU);


Imgproc.threshold(mat, mat, 0.0, 255.0,
  Imgproc.THRESH_BINARY_INV | Imgproc.THRESH_OTSU);  


Imgproc.threshold(mat, mat, 0.0, 255.0,
  Imgproc.THRESH_TRUNC | Imgproc.THRESH_OTSU);


Imgproc.threshold(mat, mat, 0.0, 255.0,
  Imgproc.THRESH_TOZERO | Imgproc.THRESH_OTSU);


Imgproc.threshold(mat, mat, 0.0, 255.0,
  Imgproc.THRESH_TOZERO_INV | Imgproc.THRESH_OTSU);



イソギンのワサワサ感が2値化された後でもたまらないですねぇ。


Read More...

2012年2月19日日曜日

画像をネガポジ反転する - OpenCV for Android



画像をネガポジ反転するには、C++では単純にNot演算子「~」でMatを反転します。

Javaでは直接オブジェクトをビット演算出来ないので、Coreに用意されたstaticメソッドを利用します。

各ビット演算にあたるのは、Core.bitwise_and()、Core.bitwise_or()、Core.bitwise_not()、Core.bitwise_xor()です。
同じくMat同士の算術演算ではCore.gemm()、Core.add()、Core.subtract()、Core.multiply()あたりを利用します。

Core.bitwise_not(Mat src, Mat dst)


 Mat src        処理したい元画像のMat
 Mat dst        変換後Mat


それでは実際にやってみましょう。

いつもの画像を反転してみます。
Core.bitwise_not(mat, mat);


うーん。。これであってるんでしょうか?
良く分からないのでグレースケールに変換してからやってみましょう。
まず普通にグレースケールへ変換。



続いてネガポジ反転。



うーん。。。
何やら思っていたのと違います。

画像を変えてみましょう。
私のエルニドフォルダから一枚。


グレースケール。


ネガポジ反転。
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGB2GRAY);
Core.bitwise_not(mat, mat);
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_GRAY2BGRA, 4);



想定した結果になりました。
ちなみにBGRAに変換した後に反転すると以下のようになります。


処理はBGRAへ変換する前に実施するべきなようです。
Chromeの画像もそのようにしたところうまくいきました。



関係無いですが、エルニドはいいところです。

Read More...