Más contenido relacionado
La actualidad más candente (20)
Similar a Kashiwa.R#1 画像解析とパターン認識における R の利用 (20)
Kashiwa.R#1 画像解析とパターン認識における R の利用
- 2. 生物画像解析の特性
多次元 (時間,立体,波長…) 多様性(生物種,部位,観察法…)
t, z, l
データサイズ・枚数 (n) 多目的性 (何に着目するか)
100 ms/枚 位置・局在 濃度・電位 運動 数・形・長さ
1024*1024 pixel/枚
12 bits/pixel
→ 4 GiBytes / 5 分
自動化・計算機支援に向く 研究者(人間)の柔軟性が不可欠
AI?? パターン認識?? 機械学習?? データマイニング??
・ 多様な画像と目的をカバーできる適応性・汎用性
・ 数値化による客観性,自動化による高速性
- 3. シロイヌナズナ気孔
アクチン繊維
「画像→画像」の例
共焦点画像 高周波数成分の抽出 二値化像 細線化像
(繊維等の強調処理) (白黒画像)
「画像→数値」の例
気孔開閉の指標 アクチン繊維の配向の指標
短径 / 長径 長径 気孔に対する
アクチン繊維の角度 q
短径 q
気孔
灰色: 気孔領域 この場合, この場合,
黒色: アクチン繊維 短径 / 長径=0.47 アクチン繊維の角度=54.3°
- 4. 159 デジタル画像は数値が並んだもの
153
x
(3, 0)
輝度30
(x,y) = (0, 0) (3, 2)
輝度 35 輝度 21
y 159列
表示を縮小
153行
- 6. ImageJ
Java .オープンソース.NIH の人が開発.生物学分野で多用される.
拡張性:
* 独自仕様のマクロ
* Java等JVM用言語でのプラグイン
* JavaプラットフォームでのAPI
可搬性・速度・スケール性:
* Java に準ずる.
画像のモデルがバイオ向き
* 画素について u8, u16, float ...
* Z軸,時間軸でのスタック化
(3次元以上の高次元画像)
以降の顕微鏡画像は全て http://ome.grc.nia.nih.gov/iicbu2008/ (IICBUデータベース) より取得.
- 18. Rserve: TCP/IP を介した R の利用
connect R console と ImageJ を別プロセスで動かしつつ,
ImageJ データのやりとりをすることができれば
R 便利そうなので,そのうちトライしたい.
(Java) http://www.rforge.net/Rserve/
- 19. rJava: R から Java を呼出す
JRI: Java から R を呼出す
call
ImageJ これを使って ImageJ と R をむすんだ
R プロダクトを簡単に 2 つ紹介します.
(Java) call http://www.rforge.net/rJava/
- 20. RImageJ: R から ImageJ を呼出す
R で実質6行のパッケージ.
これだけでも ImageJ マクロのサブセット
が R コンソールから使える.
インタラクティブな操作は不明.
http://romainfrancois.blog.free.fr/index.php?post/2009/06/22/using-ImageJ-from-R%3A-the-RImageJ-package
- 21. Bio7: ImageJ と R,その他を統合
ImageJ や R の良さが一部
失なわれているように思う.
あと挙動が怪しい気が…?
- 22. JRI (Java → R) を試す
導入 (ubuntuの場合)
export R_HOME=/usr/lib/R
export CLASSPATH=${CLASSPATH}:${R_HOME}/site-library/rJava/jri/JRI.jar
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${R_HOME}/site-library/rJava/jri
% sudo apt-get install r-cran-rjava
試用
% scala
scala> val engine=new org.rosuda.JRI.Rengine(Array("--no-save"),false,null)
engine: org.rosuda.JRI.Rengine = Thread[Thread-4,5,main]
Rは別のJavaスレッドで動く
scala> engine.eval("sum(iris$Sepal.Length)").asDouble
res0: Double = 876.5
scala> engine.eval("iris$Sepal.Length").asDoubleArray.sum
res1: Double = 876.5000000000002
これを使って ImageJ から R を使ってみることにした.
- 23. ImageJ から R を使って画像の学習と分類をする
?
ゴルジ体 リソソーム 課題画像 4. 教師データから分類森を作り,
教師画像群
課題データを分類
ImageJ randomForest package
1. 画像 7. 表示 3. 特徴等 5. 分類結果
今回の plugin R
2. 特徴等 6. 分類結果
JRI (Java/R)
JNI (Java/C)
- 24. 今回のプラグインのソースリスト (一部)
object Ijp extends KbiPlugIn {
private val imgClassA = arg("imgClassA", KbiGenericDialogObj.Choice.empty)
private val imgClassB = arg("imgClassB", KbiGenericDialogObj.Choice.empty)
def config(argStr: String): Option[() => Any] = runWith(imp => {
val winList = KbiWinListObj.all()
imgClassA.resetChoice(winList) ユーザに教師画像を
imgClassB.resetChoice(winList)
input(imgClassA, imgClassB) 2セット(A, B)指定してもらう.
def idx2imp(idx: Int): Imp = winList.getImpFromIdx(idx) match {
case null => KbiExc("image not found")
case imp => imp
}
new TrainAndClassifier(idx2imp(imgClassA().idx), idx2imp(imgClassB().idx))
})
}
R engine の管理.
private object Rengine { R は初回使用時のみ初期化する.
private lazy val engine = new org.rosuda.JRI.Rengine(Array("--no-save"),
false, null)
def eval(s: String): org.rosuda.JRI.REXP = engine.eval(s)
}
- 25. private class TrainAndClassifier(impA: Imp, impB: Imp) extends ProcNotShow {
private val featureExtractor = str2featureSet("glcmPlain")
private val vectorsA = ips2features(UtilImg.ist2ips(impA.getStack))
private val vectorsB = ips2features(UtilImg.ist2ips(impB.getStack))
private val nDim = vectorsA(0).size 教師画像からの特徴抽出
private def ips2features(ips: Array[Ip]) = for (ip <- ips) yield
featureExtractor.extract(ip).values.drop(2).toArray
def proc(istQ: Ist, impQ: Imp, kpl: KbiPlugIn) {
val ipsQ = UtilImg.ist2ips(istQ)
val vectorsQ = ips2features(ipsQ) 課題画像からの特徴抽出
val cmdsForR = Util.withArrBuf[String](acc => {
def addVectorStr(i: Int) {
acc += "tf%d <- c(%s,%s)".format(i, vectorsA.map(_(i)).mkString(","),
vectorsB.map(_(i)).mkString(","))
acc += "qf%d <- c(%s)".format(i, vectorsQ.map(_(i)).mkString(","))
}
acc += "library(randomForest)" R に渡すコマンドを生成
for (i <- 0 until nDim) addVectorStr(i)
acc += "imgClass <- c(%s,%s)".format( (学習と分類)
Array.fill(vectorsA.size)("'A'").mkString(","),
Array.fill(vectorsB.size)("'B'").mkString(","))
acc += "dTeach <- data.frame(%s,imgClass)".format((0 until nDim).map(n =>
"f%d=tf%d".format(n, n)).mkString(","))
acc += "dQuery <- data.frame(%s)".format((0 until nDim).map(n =>
"f%d=qf%d".format(n, n)).mkString(","))
acc += "rf <- randomForest(formula=imgClass ~., data=dTeach)"
acc += "predicted <- as.integer(predict(rf, dQuery))"
})
- 26. cmdsForR.forall(cmd => Rengine.eval(cmd) != null) match {
case false => KbiExc("error occurred in R") R の呼出
case true => {
val predicted = Rengine.eval("predicted").asIntArray
KbiExc.assert(predicted != null, "error occurred in R: predicted")
val (ipsEstA, ipsEstB) = Util.withArrBuf[Ip, Ip]((accA, accB) =>
for ((lbl, idx) <- predicted.zipWithIndex) lbl match {
case 1 => accA += ipsQ(idx)
case 2 => accB += ipsQ(idx)
分類結果に応じて
})
if (ipsEstA.size > 0) UtilImg.show(ipsEstA)
課題画像を
}
if (ipsEstB.size > 0) UtilImg.show(ipsEstB) 2つに分けて表示.
}
}
}
今回は R script を生成するために
double[] a = { 1.2, 2.4, 3.6 };
を
String s = String.format("f1 <- c(%g, %g, %g)", a[0]…
Rengine.eval(s);
のようにデータを文字列中に埋め込んでから評価しているが,
Rengine.assign("f1", array);
の方が速度や誤差の面では望ましい.
- 29. ゴルジ体 リソソーム
エンドソームの分類状況(一部) リソソームぽい
ゴルジ体ぽい
8 vs 83
エンドソームは今回の特徴量と分類法と
画像セットでは,ゴルジ体よりリソソームに
似た局在をしている.