SlideShare a Scribd company logo
ImageJ を使った画像解析実習
数・形態・分布の解析
第194回農林交流センターワークショップ
「 植物科学・作物育種におけるフェノーム解析
- はじめて画像解析を行う研究者のための入門実習 - 」
2015-09-18 09:15-10:20 (実習75分)
実習主担当: 朽名 夏麿
例: 葉緑体の形の解析 (粒子解析)
二値画像
グレイスケール画像
Analyze >
Analyze Particles…
例: アクチン繊維の配向解析
共焦点画像 バンドパスフィルタ
による繊維等の強調
二値化像 細線化像
短径 / 長径
短径
長径
気孔開閉の指標
気孔に対する
アクチン繊維の角度
アクチン繊維の配向の指標
気孔
θ
気孔
θ
気孔
この場合,
短径 / 長径=0.47
この場合,
アクチン繊維の角度=54.3°
灰色: 気孔領域
黒色: アクチン繊維
シロイヌナズナ気孔
アクチン繊維
バンドパスフィルタ
Process > FFT > Bandpass Filter...
解析対象のおおよその大きさをもとに強調する処理.
ノイズ,背景,シェーディングの影響を抑制する.
細胞表層微小管のプラス端
輝度プロファイル(左図の黄色い線)
バンドパスフィルタによる焦点外物体の影響除去
原画像(明視野像) 処理後
焦点外にある細胞やナイロンメッシュの影響を抑えることができる.
BDM処理した
BY-2細胞
BY-2プロトプラスト
から得た単離液胞
アクチン繊維配向の定量と可視化
向き: 配向の平均角度
長さ: 配向の整列性
明るさ(擬似色): 繊維の密度
* stomata-actin.tif を開く.
* Image > Stacks > Z Project... >
Projection type = Max Intensity
* Process > FFT > Bandpass Filter...
Filter large... = 5
Filter small... = 1
Tolerance... = 0
* Image > Adjust > Threshold... >
… > Apply
* Process > Binary > Skeletonize
* Plugins > LPX > Lpx_LinesAngle
mode = map (可視化)
* Plugins > LPX > Lpx_LinesAngle
mode = eachSlice (定量)
実験圃場(水田)
60 cm 間隔
圃場のイネの各個体を毎週撮影し,
地上部の大きさ・形・色を経時的に
定量する実験系を確立する.
定量した形質をQTL解析に供する.
例: 圃場におけるイネの生長解析
撮像装置
実際に撮影された画像
カラーチャート
個体識別札
画像提供: 香川大学 農学部 杉田(小西)左江子 先生
画像解析上の課題
1. ウキクサのような浮遊物
2. 太陽光の直接反射
http://www.mathworks.com/matlabcentral/fileexchange/28790-colorspace-transformations
色空間
一般的なカラー画像では色彩の表現として,
RGB (発光時に用いる色表現,カメラに用いる色表現) や
CMYK (印刷に用いる色表現)
が用いられる.
一方,バイオイメージング分野では
単色からスペクトルまで
多様な色情報のデータが
扱われている.
(A) http://www.jiscdigitalmedia.ac.uk/guide/colour-theory-understanding-and-modelling-colour/
(B) http://w3.kcua.ac.jp/~fujiwara/infosci/colorspace/colorspace3.html
その他 http://en.wikipedia.org/ よりそれぞれ引用
CIE1976 L*a*b* (CIELAB) color space
L*: lightness, a* & b*: color-opponent space
perceptually uniform
RGB color space (A)
(B)
Additive primary colors:
Red, Green, Blue mimic the nonlinear response of the eye
RGB HSV YIQ CIE L*a*b* CIE XYZ
各種色空間への変換例
→ CIE a* 軸がイネ地上部の領域抽出に向く.
カラーパネル検出ならびに葉領域の抽出と細線化
原画像 CIELAB 色空間の a* 軸 a* が閾値以下の領域
葉領域画像 細線画像カラーパネル検出結果
カラーパネルの円の直径が既知(12.5 cm)
であるため,スケールバーとして利用し,
比率 r [cm / pixel] を求める.
画像や細線化画像で測定された pixel 単位
の値を cm に換算するのに用いる.
緑色の領域は a* 軸では小さな値となる.
手作業で個体中心付近に設定した円(青色
で示す)と連結した白領域のみ抽出し,
さらにモルフォロジカルフィルタ(close)
によって領域境界の平滑化を行なうことで
葉領域を得た.
白黒画像の細線化アルゴリズムを適用して
得た.
他に輪郭画像を形態計測の際には作成
しているが,ここでは省略している.
形態特徴の測定法 1/3
葉領域画像 area1: イネ地上部の面積(cm2).葉領域画像中の白画素数 × r2
perimeter4conn: イネ地上部領域の周長(cm).輪郭画像中の白画素数 × r
widthByAreaPeri4: 葉の幅に関する指標(cm).2 × area1 ÷ perimeter4conn
complexity: 形状の複雑度.perimeter4conn 2 ÷( 4 π × area1 )
拡大
輪郭画像葉領域画像
輪郭抽出
形態特徴の測定法 2/3
葉領域画像 skelLen: 葉の長さに関する指標(cm).細線画像中の白画素数 × r
widthByAreaSkelLen: 葉の幅に関する指標(cm).area1 ÷ skelLen
skelEnd: 葉の枚数に関する指標(個).細線画像中の端点の数 (赤い丸).
skelBranch: 葉の混み具合に関する指標(個).細線画像中の分岐点の数 (黄色い丸).
拡大
細線画像葉領域画像
細線化
端点
端点
分岐点
分岐点
形態特徴の測定法 3/3
widthBySkelDisttrfmMean: 葉の幅に関する指標(cm).以下の手続きによって求める値.
Step 1. 細線画像(左の画像)中のi 番目の白画素 Ai について( i は 1 から skelLen まで):
Step 1-1. 画素Aiに最も近い,輪郭画像(右の画像)中の白画素を探し,これを画素Bとする.
Step 1-2. 画素Aiと画素Biの距離(pixel)を求めて, di とする.
Step 2. di の平均値(i は 1 から skelLen まで) × 2 r を widthBySkelDisttrfmMean とする.
細線画像 輪郭画像
画素Ai 画素Bi
実習
- RGB 各信号 への分解:
Image > Color > Split Channels
- その他の色空間の座標へ:
Plugins > LPX > Lpx Color >
mode = RGB2...
もしくは
Plugins > Filters > Color Transformer
- 輝度を閾値とした2値化
Image > Adjust > Threshold
- 面積の測定
Analyze > Analyze Particles
- 細線化と線長の測定
Process > Binary > Skeletonize
Analyze > Analyze Particles
or KBI_Measure > blobMeasure...
feature=chain_codes_8_totalLength
- 端点抽出と計数
Plugin > LPX > Lpx_Filter2d >
filtersForBilevel__ > pixSpec__ > pick,,end
例2: ブドウ葉の病斑解析
シートフィード式スキャナ (ScanSnap) で撮影.
画像提供: 農研機構 果樹研究所 河野淳 様
http://www.scansnap.net/escaneres-by-fujitsu/scansnap/s1100/
拡大図
※スケール代わりの付箋紙にも注目.
回転
縮小 + CIE L* + ノイズ抑制 縮小 + CIE a* + ノイズ抑制
入力画像
入力画像
回転
縮小 + CIE L* + ノイズ抑制 縮小 + CIE a* + ノイズ抑制
拡大図
自動二値化 自動二値化
病斑領域の二値化
自動二値化だけで 常に 必要十分に 正しく 領域抽出するのは困難.
→ ユーザの目視による二値化基準の修正 +
二値化後の除去 (主に葉脈部を除くため円形度を閾値とした)
適切 (必要十分)
偽陰性(見逃し) あり
偽陽性(採り過ぎ)あり
葉領域 ならびに 病斑領域 の決定
葉領域
病斑領域 群葉領域
葉および病斑に関する定量
縮小率: 長さ比 1/shrink に縮小する.
葉領域のノイズ抑制 (to CIEL* 像).
葉領域の自動2値化アルゴリズム
病斑領域のノイズ抑制 (to CIEa* 像)
病斑領域の自動2値化アルゴリズム
葉領域の最小面積
Phase 1: 2値化による領域分割まで
Phase 2: 領域分割後のフィルタリング
病斑領域の最小円形度
object Ijp extends LpxPlugIn {
private val leafThrEffective = Seq('ijHuang, 'ijLi, 'ijMinimum, …
private val spotThrEffective = Seq('ijRenyiEntropy, 'ijYen, …
private val leafThrSyms =
leafThrEffective ++ (plg.threshold.Common.ijSymbols.toSet -- leaf…
}
private val spotThrSyms = {
spotThrEffective ++ (plg.threshold.Common.ijSymbols.toSet -- spot…
}
private val mode = arg("kaMode", Seq('measure, 'setParam))
private val sep1 = arg("-- phase1 --")
private val shrink = arg("shrink", 4)
private val leafDenoise = arg("leafDenoise", 2.0)
private val leafThr = arg("leafThr", leafThrSyms)
private val spotDenoise = arg("spotDenoise", 1.0)
private val spotThr = arg("spotThr", spotThrSyms)
private val genStk = arg("genStk", false)
private val sep2 = arg("-- phase2 --")
private val leafMinArea = arg("leafMinAreaInOrg", 500000d)
private val spotCircularity = arg("spotCircularity", 0.6)
private val sep3 = arg("----")
private val continuePlugIn = arg("continuePlugIn", true)
// R G B
private val colorLeaf = new java.awt.Color(128, 128, 128)
private val colorSpot = new java.awt.Color(255, 255, 255)
private val colorLeafId = new java.awt.Color( 0, 198, 255)
private val colorSpotId = new java.awt.Color( 0, 255, 0)
private val colorImageJForeground = new java.awt.Color(255, 255, 255)
private val fontLeaf = new java.awt.Font("Serif", java.…
private val fontSpot = new java.awt.Font("Serif", java.…
def config(argStr: String): Option[() => Any] = {
def rec() {
val imp = IJ.getImage
input(mode)
mode.getSym match {
case 'measure => measure(imp)
case 'setParam => {
if (setParam()) rec()
}
}
}
rec()
None
}
private def measure(imp: Imp) {
if (ImgC.is(imp)) {
phase1(imp)
} else {
phase2()
}
}
private def phase1(impOrg: Imp) {
def bandpass(ip: Ip, loSd: Double, hiSd: Double): Ip = {
new plg.band_pass.DiffOfGaussian(loSd, hiSd)(ip)
}
def bandpassMin0(ip: Ip, loSd: Double, hiSd: Double): Ip = {
plg.band_pass.Min0(bandpass(ip, loSd, hiSd))
}
def to8bit(ip: Ip): Ip = plg.filter2d.ToByteType.SliScale(ip)
def toThrStk(ip: Ip): Ist = new plg.filter2d.ToStkByThrFromByte(A…
def showAndSetCurSlice(ist: Ist, title: String, z: Int) {
val impShow = new Imp(WindowManager.makeUniqueName(title), ist)
impShow.setDisplayRange(0, 255, 7)
impShow.updateAndDraw
impShow.setSlice(z + 1)
impShow.show
}
require(ImgC.is(impOrg), "ImgC.is")
require(impOrg.getStackSize == 1, "getStackSize == 1")
require(shrink() >= 1, "shrink >= 1")
ij.gui.Toolbar.setForegroundColor(colorImageJForeground)
impOrg.setTitle(WindowManager.makeUniqueName("org"))
val ipOrg = impOrg.getProcessor.rotateRight
impOrg.setProcessor(ipOrg)
ipOrg.setInterpolationMethod(Ip.BILINEAR)
val ipShrink = ipOrg.resize((ipOrg.getWidth / shrink().toFloat).r…
val (ipCieL, ipCieA, ipCieB_notUsed) =
new Rgb2ColorSpace(false).procSli(ipShrink, 'CIELAB2_speedy)
val (numX, numY) = UtilImg.dim(ipCieL)
val bpHiMax = numX.min(numY)
// leaf: CIEL*
val ipLeaf = to8bit(bandpassMin0(plg.filter_pt.MathOpMultiply(-1)…
val thrLeaf = new IjThresholder(leafThr.getSym).getThr(ipLeaf).get()
if (genStk()) {
val istLeaf = toThrStk(ipLeaf)
showAndSetCurSlice(istLeaf, "leaf", thrLeaf)
} else {
val imp = UtilImg.show(ipLeaf, f"leaf_${thrLeaf}")
IJ.setThreshold(imp, thrLeaf, 255) }
// spot: CIEa*
val ipSpot = to8bit(bandpass(ipCieA, spotDenoise(), bpHiMax))
val thrSpot = new IjThresholder(spotThr.getSym).getThr(ipSpot).get()
if (genStk()) {
val istSpot = toThrStk(ipSpot)
showAndSetCurSlice(istSpot, "spot", thrSpot)
} else {
val imp = UtilImg.show(ipSpot, f"spot_${thrSpot}")
IJ.setThreshold(imp, thrSpot, 255)
}
}
// use leafMinArea(), spotCircularity()
private def phase2() {
def getIpOfTitle(title: String): Ip = {
val titles = UtilIj.getAllImageTitles()
val hits = titles.filter(_.startsWith(title))
LpxExc.assert(hits.size == 1, f"Image '${title}' is not …
val ip = WindowManager.getImage(hits.head).getProcessor
LpxExc.assert(Img8.isBinary(ip), f"Image '${title}' must be …
ip
}
def drawString(ipTgt: Ip, s: String, font: Font, color: Color, …
ipTgt.setColor(color)
ipTgt.setFont(font)
val width = ipTgt.getStringWidth(s)
ipTgt.drawString(s, x - width, y)
}
ij.gui.Toolbar.setForegroundColor(colorImageJForeground)
val ipLeaf = getIpOfTitle("leaf")
val ipSpot = getIpOfTitle("spot")
LpxExc.assert(UtilImg.sameDim(ipLeaf, ipSpot), "dimension mismatch")
val leafMinAreaInShrinked = (leafMinArea() / (shrink() * shrink()))…
val leafBlobs = {
PixGrp.filterOutSmall(PixGrp.getBlobs(ipLeaf), leafMinAreaInShr…
}
val spotBlobs = {
val ipSpotInLeaf = Img8.dupRet(ipSpot, false) { ipSpotInLeaf =>
for (i <- 0 until ipSpot.getPixelCount if ipLeaf.get(i) == 0) {
ipSpotInLeaf.set(i, 0)
}
}
PixGrp.getBlobs(ipSpotInLeaf).filter(_.getCircularity >=
spotCircularity()) }
UtilIj.writeln(f"#shrink;¥t${shrink()}")
UtilIj.writeln(f"# areaAdjustFactor;¥t${shrink() * shrink()}")
UtilIj.writeln(f"#leafDenoise;¥t${leafDenoise()}")
UtilIj.writeln(f"#leafThr;¥t${leafThr.getSym.name}")
UtilIj.writeln(f"#spotDenoise;¥t${spotDenoise()}")
UtilIj.writeln(f"#spotThr;¥t${spotThr.getSym.name}")
UtilIj.writeln(f"#leafMinAreaInOrg;¥t${leafMinArea()}")
UtilIj.writeln(f"# leafMinAreaInShrinked;¥t${leafMinAreaInShrinked}"
UtilIj.writeln(f"#spotCircularity;¥t${spotCircularity()}¥n")
for ((leafBlob, leafIdx) <- leafBlobs.zipWithIndex) {
for (polRoi <- leafBlob.toPolygonRoi(true, true)) {
plg.roi_util.Painter.drawByRoiInSitu(ipDebug, colorLeaf, polRoi)
val awtRectangle = polRoi.getFloatPolygon.getBounds
ipDebug.setColor(colorLeafId)
val x = awtRectangle.x
val y = awtRectangle.y + awtRectangle.height / 2
drawString(ipDebug, f"${leafIdx}", fontLeaf, colorLeafId, x, y)
}
val leafXySet = leafBlob.toXys.toSet
val assocBlobs = spotBlobs.filter { spotBlob =>
val (centroidX, centroidY) = spotBlob.getCentroid
leafXySet.contains((centroidX.round.toInt, centroidY.round.…
} sortBy(- _.size)
for ((blob, blobIdx) <- assocBlobs.zipWithIndex) {
blob.drawToIpByColor(ipDebug, colorSpot)
val x = blob.xsMin - 3
val y = (blob.ysMin + blob.ysMax) / 2 + 10
drawString(ipDebug, f"${blobIdx}", fontSpot, colorSpotId, x, y)
}
UtilIj.writeln(f"leafIdx;¥t$leafIdx")
UtilIj.writeln(f"leafArea;¥t${leafBlob.size * shrink() * shrink(…
UtilIj.writeln(f"spotNum;¥t${assocBlobs.size}")
val spotTotalArea = assocBlobs.map(_.size).sum
UtilIj.writeln(f"spotTotalArea;¥t${spotTotalArea * shrink() * shr…
for ((spotBlob, spotIdx) <- assocBlobs.zipWithIndex) {
UtilIj.writeln(f" spotArea;¥t${leafIdx}-${spotIdx};¥t" +
f"${spotBlob.size * shrink() * shrink()}")
}
UtilIj.writeln("")
}
null
}
private def setParam(): Boolean = {
input(sep1,
shrink, leafDenoise, leafThr, spotDenoise, spotThr, genStk,
sep2,
leafMinArea, spotCircularity,
sep3, continuePlugIn)
mode.setIdx(0)
continuePlugIn()
}
}

More Related Content

What's hot

画像認識の初歩、SIFT,SURF特徴量
画像認識の初歩、SIFT,SURF特徴量画像認識の初歩、SIFT,SURF特徴量
画像認識の初歩、SIFT,SURF特徴量takaya imai
 
Image J を用いた組織像の定量解析
Image J を用いた組織像の定量解析Image J を用いた組織像の定量解析
Image J を用いた組織像の定量解析
Atsuto ONODA
 
3次元レジストレーション(PCLデモとコード付き)
3次元レジストレーション(PCLデモとコード付き)3次元レジストレーション(PCLデモとコード付き)
3次元レジストレーション(PCLデモとコード付き)
Toru Tamaki
 
画像生成・生成モデル メタサーベイ
画像生成・生成モデル メタサーベイ画像生成・生成モデル メタサーベイ
画像生成・生成モデル メタサーベイ
cvpaper. challenge
 
R-CNNの原理とここ数年の流れ
R-CNNの原理とここ数年の流れR-CNNの原理とここ数年の流れ
R-CNNの原理とここ数年の流れ
Kazuki Motohashi
 
フーリエ変換を用いたテクスチャ解像度推定とその応用
フーリエ変換を用いたテクスチャ解像度推定とその応用フーリエ変換を用いたテクスチャ解像度推定とその応用
フーリエ変換を用いたテクスチャ解像度推定とその応用
Hajime Uchimura
 
初めてのグラフカット
初めてのグラフカット初めてのグラフカット
初めてのグラフカットTsubasa Hirakawa
 
Layer Normalization@NIPS+読み会・関西
Layer Normalization@NIPS+読み会・関西Layer Normalization@NIPS+読み会・関西
Layer Normalization@NIPS+読み会・関西
Keigo Nishida
 
マルチモーダル深層学習の研究動向
マルチモーダル深層学習の研究動向マルチモーダル深層学習の研究動向
マルチモーダル深層学習の研究動向
Koichiro Mori
 
三次元表現まとめ(深層学習を中心に)
三次元表現まとめ(深層学習を中心に)三次元表現まとめ(深層学習を中心に)
三次元表現まとめ(深層学習を中心に)
Tomohiro Motoda
 
SSII2014 チュートリアル資料
SSII2014 チュートリアル資料SSII2014 チュートリアル資料
SSII2014 チュートリアル資料Masayuki Tanaka
 
Sift特徴量について
Sift特徴量についてSift特徴量について
Sift特徴量について
la_flance
 
機械学習 / Deep Learning 大全 (1) 機械学習基礎編
機械学習 / Deep Learning 大全 (1) 機械学習基礎編機械学習 / Deep Learning 大全 (1) 機械学習基礎編
機械学習 / Deep Learning 大全 (1) 機械学習基礎編
Daiyu Hatakeyama
 
Rethinking and Beyond ImageNet
Rethinking and Beyond ImageNetRethinking and Beyond ImageNet
Rethinking and Beyond ImageNet
cvpaper. challenge
 
[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
Deep Learning JP
 
Deep Learningによる画像認識革命 ー歴史・最新理論から実践応用までー
Deep Learningによる画像認識革命 ー歴史・最新理論から実践応用までーDeep Learningによる画像認識革命 ー歴史・最新理論から実践応用までー
Deep Learningによる画像認識革命 ー歴史・最新理論から実践応用までー
nlab_utokyo
 
Kaggle RSNA Pneumonia Detection Challenge 解法紹介
Kaggle RSNA Pneumonia Detection Challenge 解法紹介Kaggle RSNA Pneumonia Detection Challenge 解法紹介
Kaggle RSNA Pneumonia Detection Challenge 解法紹介
理 秋山
 
自己教師学習(Self-Supervised Learning)
自己教師学習(Self-Supervised Learning)自己教師学習(Self-Supervised Learning)
自己教師学習(Self-Supervised Learning)
cvpaper. challenge
 
画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -
画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -
画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -MPRG_Chubu_University
 
ガイデットフィルタとその周辺
ガイデットフィルタとその周辺ガイデットフィルタとその周辺
ガイデットフィルタとその周辺Norishige Fukushima
 

What's hot (20)

画像認識の初歩、SIFT,SURF特徴量
画像認識の初歩、SIFT,SURF特徴量画像認識の初歩、SIFT,SURF特徴量
画像認識の初歩、SIFT,SURF特徴量
 
Image J を用いた組織像の定量解析
Image J を用いた組織像の定量解析Image J を用いた組織像の定量解析
Image J を用いた組織像の定量解析
 
3次元レジストレーション(PCLデモとコード付き)
3次元レジストレーション(PCLデモとコード付き)3次元レジストレーション(PCLデモとコード付き)
3次元レジストレーション(PCLデモとコード付き)
 
画像生成・生成モデル メタサーベイ
画像生成・生成モデル メタサーベイ画像生成・生成モデル メタサーベイ
画像生成・生成モデル メタサーベイ
 
R-CNNの原理とここ数年の流れ
R-CNNの原理とここ数年の流れR-CNNの原理とここ数年の流れ
R-CNNの原理とここ数年の流れ
 
フーリエ変換を用いたテクスチャ解像度推定とその応用
フーリエ変換を用いたテクスチャ解像度推定とその応用フーリエ変換を用いたテクスチャ解像度推定とその応用
フーリエ変換を用いたテクスチャ解像度推定とその応用
 
初めてのグラフカット
初めてのグラフカット初めてのグラフカット
初めてのグラフカット
 
Layer Normalization@NIPS+読み会・関西
Layer Normalization@NIPS+読み会・関西Layer Normalization@NIPS+読み会・関西
Layer Normalization@NIPS+読み会・関西
 
マルチモーダル深層学習の研究動向
マルチモーダル深層学習の研究動向マルチモーダル深層学習の研究動向
マルチモーダル深層学習の研究動向
 
三次元表現まとめ(深層学習を中心に)
三次元表現まとめ(深層学習を中心に)三次元表現まとめ(深層学習を中心に)
三次元表現まとめ(深層学習を中心に)
 
SSII2014 チュートリアル資料
SSII2014 チュートリアル資料SSII2014 チュートリアル資料
SSII2014 チュートリアル資料
 
Sift特徴量について
Sift特徴量についてSift特徴量について
Sift特徴量について
 
機械学習 / Deep Learning 大全 (1) 機械学習基礎編
機械学習 / Deep Learning 大全 (1) 機械学習基礎編機械学習 / Deep Learning 大全 (1) 機械学習基礎編
機械学習 / Deep Learning 大全 (1) 機械学習基礎編
 
Rethinking and Beyond ImageNet
Rethinking and Beyond ImageNetRethinking and Beyond ImageNet
Rethinking and Beyond ImageNet
 
[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
[DL輪読会]NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis
 
Deep Learningによる画像認識革命 ー歴史・最新理論から実践応用までー
Deep Learningによる画像認識革命 ー歴史・最新理論から実践応用までーDeep Learningによる画像認識革命 ー歴史・最新理論から実践応用までー
Deep Learningによる画像認識革命 ー歴史・最新理論から実践応用までー
 
Kaggle RSNA Pneumonia Detection Challenge 解法紹介
Kaggle RSNA Pneumonia Detection Challenge 解法紹介Kaggle RSNA Pneumonia Detection Challenge 解法紹介
Kaggle RSNA Pneumonia Detection Challenge 解法紹介
 
自己教師学習(Self-Supervised Learning)
自己教師学習(Self-Supervised Learning)自己教師学習(Self-Supervised Learning)
自己教師学習(Self-Supervised Learning)
 
画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -
画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -
画像局所特徴量と特定物体認識 - SIFTと最近のアプローチ -
 
ガイデットフィルタとその周辺
ガイデットフィルタとその周辺ガイデットフィルタとその周辺
ガイデットフィルタとその周辺
 

Similar to ImageJを使った画像解析実習〜数・形態・分布の解析〜

Kashiwa.R#1 画像解析とパターン認識における R の利用
Kashiwa.R#1 画像解析とパターン認識における R の利用Kashiwa.R#1 画像解析とパターン認識における R の利用
Kashiwa.R#1 画像解析とパターン認識における R の利用
nmaro
 
機械学習
機械学習機械学習
機械学習
ssusere8ae711
 
R -> Python
R -> PythonR -> Python
R -> Python
Kazufumi Ohkawa
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたblackenedgold
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
Shinichi Kozake
 
Feature Selection with R / in JP
Feature Selection with R / in JPFeature Selection with R / in JP
Feature Selection with R / in JP
Sercan Ahi
 
Python 機械学習プログラミング データ分析ライブラリー解説編
Python 機械学習プログラミング データ分析ライブラリー解説編Python 機械学習プログラミング データ分析ライブラリー解説編
Python 機械学習プログラミング データ分析ライブラリー解説編
Etsuji Nakai
 
[機械学習]文章のクラス分類
[機械学習]文章のクラス分類[機械学習]文章のクラス分類
[機械学習]文章のクラス分類
Tetsuya Hasegawa
 
20180728 halide-study
20180728 halide-study20180728 halide-study
20180728 halide-study
Fixstars Corporation
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
Kazuki Onishi
 
衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18Koichiro Mori
 
10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920 10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920
Nobuaki Oshiro
 
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
de:code 2017
 
Introduction to NumPy & SciPy
Introduction to NumPy & SciPyIntroduction to NumPy & SciPy
Introduction to NumPy & SciPy
Shiqiao Du
 
文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...
文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...
文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...
Toru Tamaki
 
論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...
論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...
論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...
Teppei Kurita
 
2013.12.26 prml勉強会 線形回帰モデル3.2~3.4
2013.12.26 prml勉強会 線形回帰モデル3.2~3.42013.12.26 prml勉強会 線形回帰モデル3.2~3.4
2013.12.26 prml勉強会 線形回帰モデル3.2~3.4
Takeshi Sakaki
 

Similar to ImageJを使った画像解析実習〜数・形態・分布の解析〜 (19)

Kashiwa.R#1 画像解析とパターン認識における R の利用
Kashiwa.R#1 画像解析とパターン認識における R の利用Kashiwa.R#1 画像解析とパターン認識における R の利用
Kashiwa.R#1 画像解析とパターン認識における R の利用
 
機械学習
機械学習機械学習
機械学習
 
R -> Python
R -> PythonR -> Python
R -> Python
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみた
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
Feature Selection with R / in JP
Feature Selection with R / in JPFeature Selection with R / in JP
Feature Selection with R / in JP
 
boost tour 1.48.0 all
boost tour 1.48.0 allboost tour 1.48.0 all
boost tour 1.48.0 all
 
Python 機械学習プログラミング データ分析ライブラリー解説編
Python 機械学習プログラミング データ分析ライブラリー解説編Python 機械学習プログラミング データ分析ライブラリー解説編
Python 機械学習プログラミング データ分析ライブラリー解説編
 
[機械学習]文章のクラス分類
[機械学習]文章のクラス分類[機械学習]文章のクラス分類
[機械学習]文章のクラス分類
 
20180728 halide-study
20180728 halide-study20180728 halide-study
20180728 halide-study
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
 
Rで学ぶロバスト推定
Rで学ぶロバスト推定Rで学ぶロバスト推定
Rで学ぶロバスト推定
 
衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18衛星芸術Pbl 2011 10_18
衛星芸術Pbl 2011 10_18
 
10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920 10分で分かるr言語入門ver2.9 14 0920
10分で分かるr言語入門ver2.9 14 0920
 
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
 
Introduction to NumPy & SciPy
Introduction to NumPy & SciPyIntroduction to NumPy & SciPy
Introduction to NumPy & SciPy
 
文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...
文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...
文献紹介:Deep Analysis of CNN-Based Spatio-Temporal Representations for Action Re...
 
論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...
論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...
論文解説:スマホカメラを用いたBRDFパラメータ取得技術(非DNN)「Two-Shot SVBRDF Capture for Stationary Mat...
 
2013.12.26 prml勉強会 線形回帰モデル3.2~3.4
2013.12.26 prml勉強会 線形回帰モデル3.2~3.42013.12.26 prml勉強会 線形回帰モデル3.2~3.4
2013.12.26 prml勉強会 線形回帰モデル3.2~3.4
 

ImageJを使った画像解析実習〜数・形態・分布の解析〜

  • 1. ImageJ を使った画像解析実習 数・形態・分布の解析 第194回農林交流センターワークショップ 「 植物科学・作物育種におけるフェノーム解析 - はじめて画像解析を行う研究者のための入門実習 - 」 2015-09-18 09:15-10:20 (実習75分) 実習主担当: 朽名 夏麿
  • 3. 例: アクチン繊維の配向解析 共焦点画像 バンドパスフィルタ による繊維等の強調 二値化像 細線化像 短径 / 長径 短径 長径 気孔開閉の指標 気孔に対する アクチン繊維の角度 アクチン繊維の配向の指標 気孔 θ 気孔 θ 気孔 この場合, 短径 / 長径=0.47 この場合, アクチン繊維の角度=54.3° 灰色: 気孔領域 黒色: アクチン繊維 シロイヌナズナ気孔 アクチン繊維
  • 4. バンドパスフィルタ Process > FFT > Bandpass Filter... 解析対象のおおよその大きさをもとに強調する処理. ノイズ,背景,シェーディングの影響を抑制する. 細胞表層微小管のプラス端 輝度プロファイル(左図の黄色い線)
  • 7. * stomata-actin.tif を開く. * Image > Stacks > Z Project... > Projection type = Max Intensity * Process > FFT > Bandpass Filter... Filter large... = 5 Filter small... = 1 Tolerance... = 0 * Image > Adjust > Threshold... > … > Apply * Process > Binary > Skeletonize * Plugins > LPX > Lpx_LinesAngle mode = map (可視化) * Plugins > LPX > Lpx_LinesAngle mode = eachSlice (定量)
  • 12. http://www.mathworks.com/matlabcentral/fileexchange/28790-colorspace-transformations 色空間 一般的なカラー画像では色彩の表現として, RGB (発光時に用いる色表現,カメラに用いる色表現) や CMYK (印刷に用いる色表現) が用いられる. 一方,バイオイメージング分野では 単色からスペクトルまで 多様な色情報のデータが 扱われている.
  • 13. (A) http://www.jiscdigitalmedia.ac.uk/guide/colour-theory-understanding-and-modelling-colour/ (B) http://w3.kcua.ac.jp/~fujiwara/infosci/colorspace/colorspace3.html その他 http://en.wikipedia.org/ よりそれぞれ引用 CIE1976 L*a*b* (CIELAB) color space L*: lightness, a* & b*: color-opponent space perceptually uniform RGB color space (A) (B) Additive primary colors: Red, Green, Blue mimic the nonlinear response of the eye
  • 14. RGB HSV YIQ CIE L*a*b* CIE XYZ 各種色空間への変換例 → CIE a* 軸がイネ地上部の領域抽出に向く.
  • 15. カラーパネル検出ならびに葉領域の抽出と細線化 原画像 CIELAB 色空間の a* 軸 a* が閾値以下の領域 葉領域画像 細線画像カラーパネル検出結果 カラーパネルの円の直径が既知(12.5 cm) であるため,スケールバーとして利用し, 比率 r [cm / pixel] を求める. 画像や細線化画像で測定された pixel 単位 の値を cm に換算するのに用いる. 緑色の領域は a* 軸では小さな値となる. 手作業で個体中心付近に設定した円(青色 で示す)と連結した白領域のみ抽出し, さらにモルフォロジカルフィルタ(close) によって領域境界の平滑化を行なうことで 葉領域を得た. 白黒画像の細線化アルゴリズムを適用して 得た. 他に輪郭画像を形態計測の際には作成 しているが,ここでは省略している.
  • 16. 形態特徴の測定法 1/3 葉領域画像 area1: イネ地上部の面積(cm2).葉領域画像中の白画素数 × r2 perimeter4conn: イネ地上部領域の周長(cm).輪郭画像中の白画素数 × r widthByAreaPeri4: 葉の幅に関する指標(cm).2 × area1 ÷ perimeter4conn complexity: 形状の複雑度.perimeter4conn 2 ÷( 4 π × area1 ) 拡大 輪郭画像葉領域画像 輪郭抽出
  • 17. 形態特徴の測定法 2/3 葉領域画像 skelLen: 葉の長さに関する指標(cm).細線画像中の白画素数 × r widthByAreaSkelLen: 葉の幅に関する指標(cm).area1 ÷ skelLen skelEnd: 葉の枚数に関する指標(個).細線画像中の端点の数 (赤い丸). skelBranch: 葉の混み具合に関する指標(個).細線画像中の分岐点の数 (黄色い丸). 拡大 細線画像葉領域画像 細線化 端点 端点 分岐点 分岐点
  • 18. 形態特徴の測定法 3/3 widthBySkelDisttrfmMean: 葉の幅に関する指標(cm).以下の手続きによって求める値. Step 1. 細線画像(左の画像)中のi 番目の白画素 Ai について( i は 1 から skelLen まで): Step 1-1. 画素Aiに最も近い,輪郭画像(右の画像)中の白画素を探し,これを画素Bとする. Step 1-2. 画素Aiと画素Biの距離(pixel)を求めて, di とする. Step 2. di の平均値(i は 1 から skelLen まで) × 2 r を widthBySkelDisttrfmMean とする. 細線画像 輪郭画像 画素Ai 画素Bi
  • 19. 実習 - RGB 各信号 への分解: Image > Color > Split Channels - その他の色空間の座標へ: Plugins > LPX > Lpx Color > mode = RGB2... もしくは Plugins > Filters > Color Transformer
  • 20. - 輝度を閾値とした2値化 Image > Adjust > Threshold - 面積の測定 Analyze > Analyze Particles - 細線化と線長の測定 Process > Binary > Skeletonize Analyze > Analyze Particles or KBI_Measure > blobMeasure... feature=chain_codes_8_totalLength - 端点抽出と計数 Plugin > LPX > Lpx_Filter2d > filtersForBilevel__ > pixSpec__ > pick,,end
  • 21. 例2: ブドウ葉の病斑解析 シートフィード式スキャナ (ScanSnap) で撮影. 画像提供: 農研機構 果樹研究所 河野淳 様 http://www.scansnap.net/escaneres-by-fujitsu/scansnap/s1100/
  • 23. ※スケール代わりの付箋紙にも注目. 回転 縮小 + CIE L* + ノイズ抑制 縮小 + CIE a* + ノイズ抑制 入力画像
  • 24. 入力画像 回転 縮小 + CIE L* + ノイズ抑制 縮小 + CIE a* + ノイズ抑制 拡大図
  • 26. 病斑領域の二値化 自動二値化だけで 常に 必要十分に 正しく 領域抽出するのは困難. → ユーザの目視による二値化基準の修正 + 二値化後の除去 (主に葉脈部を除くため円形度を閾値とした) 適切 (必要十分) 偽陰性(見逃し) あり 偽陽性(採り過ぎ)あり
  • 27. 葉領域 ならびに 病斑領域 の決定 葉領域 病斑領域 群葉領域
  • 29. 縮小率: 長さ比 1/shrink に縮小する. 葉領域のノイズ抑制 (to CIEL* 像). 葉領域の自動2値化アルゴリズム 病斑領域のノイズ抑制 (to CIEa* 像) 病斑領域の自動2値化アルゴリズム 葉領域の最小面積 Phase 1: 2値化による領域分割まで Phase 2: 領域分割後のフィルタリング 病斑領域の最小円形度
  • 30. object Ijp extends LpxPlugIn { private val leafThrEffective = Seq('ijHuang, 'ijLi, 'ijMinimum, … private val spotThrEffective = Seq('ijRenyiEntropy, 'ijYen, … private val leafThrSyms = leafThrEffective ++ (plg.threshold.Common.ijSymbols.toSet -- leaf… } private val spotThrSyms = { spotThrEffective ++ (plg.threshold.Common.ijSymbols.toSet -- spot… } private val mode = arg("kaMode", Seq('measure, 'setParam)) private val sep1 = arg("-- phase1 --") private val shrink = arg("shrink", 4) private val leafDenoise = arg("leafDenoise", 2.0) private val leafThr = arg("leafThr", leafThrSyms) private val spotDenoise = arg("spotDenoise", 1.0) private val spotThr = arg("spotThr", spotThrSyms) private val genStk = arg("genStk", false) private val sep2 = arg("-- phase2 --") private val leafMinArea = arg("leafMinAreaInOrg", 500000d) private val spotCircularity = arg("spotCircularity", 0.6) private val sep3 = arg("----") private val continuePlugIn = arg("continuePlugIn", true)
  • 31. // R G B private val colorLeaf = new java.awt.Color(128, 128, 128) private val colorSpot = new java.awt.Color(255, 255, 255) private val colorLeafId = new java.awt.Color( 0, 198, 255) private val colorSpotId = new java.awt.Color( 0, 255, 0) private val colorImageJForeground = new java.awt.Color(255, 255, 255) private val fontLeaf = new java.awt.Font("Serif", java.… private val fontSpot = new java.awt.Font("Serif", java.… def config(argStr: String): Option[() => Any] = { def rec() { val imp = IJ.getImage input(mode) mode.getSym match { case 'measure => measure(imp) case 'setParam => { if (setParam()) rec() } } } rec() None }
  • 32. private def measure(imp: Imp) { if (ImgC.is(imp)) { phase1(imp) } else { phase2() } } private def phase1(impOrg: Imp) { def bandpass(ip: Ip, loSd: Double, hiSd: Double): Ip = { new plg.band_pass.DiffOfGaussian(loSd, hiSd)(ip) } def bandpassMin0(ip: Ip, loSd: Double, hiSd: Double): Ip = { plg.band_pass.Min0(bandpass(ip, loSd, hiSd)) } def to8bit(ip: Ip): Ip = plg.filter2d.ToByteType.SliScale(ip) def toThrStk(ip: Ip): Ist = new plg.filter2d.ToStkByThrFromByte(A… def showAndSetCurSlice(ist: Ist, title: String, z: Int) { val impShow = new Imp(WindowManager.makeUniqueName(title), ist) impShow.setDisplayRange(0, 255, 7) impShow.updateAndDraw impShow.setSlice(z + 1) impShow.show }
  • 33. require(ImgC.is(impOrg), "ImgC.is") require(impOrg.getStackSize == 1, "getStackSize == 1") require(shrink() >= 1, "shrink >= 1") ij.gui.Toolbar.setForegroundColor(colorImageJForeground) impOrg.setTitle(WindowManager.makeUniqueName("org")) val ipOrg = impOrg.getProcessor.rotateRight impOrg.setProcessor(ipOrg) ipOrg.setInterpolationMethod(Ip.BILINEAR) val ipShrink = ipOrg.resize((ipOrg.getWidth / shrink().toFloat).r… val (ipCieL, ipCieA, ipCieB_notUsed) = new Rgb2ColorSpace(false).procSli(ipShrink, 'CIELAB2_speedy) val (numX, numY) = UtilImg.dim(ipCieL) val bpHiMax = numX.min(numY) // leaf: CIEL* val ipLeaf = to8bit(bandpassMin0(plg.filter_pt.MathOpMultiply(-1)… val thrLeaf = new IjThresholder(leafThr.getSym).getThr(ipLeaf).get() if (genStk()) { val istLeaf = toThrStk(ipLeaf) showAndSetCurSlice(istLeaf, "leaf", thrLeaf) } else { val imp = UtilImg.show(ipLeaf, f"leaf_${thrLeaf}") IJ.setThreshold(imp, thrLeaf, 255) }
  • 34. // spot: CIEa* val ipSpot = to8bit(bandpass(ipCieA, spotDenoise(), bpHiMax)) val thrSpot = new IjThresholder(spotThr.getSym).getThr(ipSpot).get() if (genStk()) { val istSpot = toThrStk(ipSpot) showAndSetCurSlice(istSpot, "spot", thrSpot) } else { val imp = UtilImg.show(ipSpot, f"spot_${thrSpot}") IJ.setThreshold(imp, thrSpot, 255) } } // use leafMinArea(), spotCircularity() private def phase2() { def getIpOfTitle(title: String): Ip = { val titles = UtilIj.getAllImageTitles() val hits = titles.filter(_.startsWith(title)) LpxExc.assert(hits.size == 1, f"Image '${title}' is not … val ip = WindowManager.getImage(hits.head).getProcessor LpxExc.assert(Img8.isBinary(ip), f"Image '${title}' must be … ip }
  • 35. def drawString(ipTgt: Ip, s: String, font: Font, color: Color, … ipTgt.setColor(color) ipTgt.setFont(font) val width = ipTgt.getStringWidth(s) ipTgt.drawString(s, x - width, y) } ij.gui.Toolbar.setForegroundColor(colorImageJForeground) val ipLeaf = getIpOfTitle("leaf") val ipSpot = getIpOfTitle("spot") LpxExc.assert(UtilImg.sameDim(ipLeaf, ipSpot), "dimension mismatch") val leafMinAreaInShrinked = (leafMinArea() / (shrink() * shrink()))… val leafBlobs = { PixGrp.filterOutSmall(PixGrp.getBlobs(ipLeaf), leafMinAreaInShr… } val spotBlobs = { val ipSpotInLeaf = Img8.dupRet(ipSpot, false) { ipSpotInLeaf => for (i <- 0 until ipSpot.getPixelCount if ipLeaf.get(i) == 0) { ipSpotInLeaf.set(i, 0) } } PixGrp.getBlobs(ipSpotInLeaf).filter(_.getCircularity >= spotCircularity()) }
  • 36. UtilIj.writeln(f"#shrink;¥t${shrink()}") UtilIj.writeln(f"# areaAdjustFactor;¥t${shrink() * shrink()}") UtilIj.writeln(f"#leafDenoise;¥t${leafDenoise()}") UtilIj.writeln(f"#leafThr;¥t${leafThr.getSym.name}") UtilIj.writeln(f"#spotDenoise;¥t${spotDenoise()}") UtilIj.writeln(f"#spotThr;¥t${spotThr.getSym.name}") UtilIj.writeln(f"#leafMinAreaInOrg;¥t${leafMinArea()}") UtilIj.writeln(f"# leafMinAreaInShrinked;¥t${leafMinAreaInShrinked}" UtilIj.writeln(f"#spotCircularity;¥t${spotCircularity()}¥n") for ((leafBlob, leafIdx) <- leafBlobs.zipWithIndex) { for (polRoi <- leafBlob.toPolygonRoi(true, true)) { plg.roi_util.Painter.drawByRoiInSitu(ipDebug, colorLeaf, polRoi) val awtRectangle = polRoi.getFloatPolygon.getBounds ipDebug.setColor(colorLeafId) val x = awtRectangle.x val y = awtRectangle.y + awtRectangle.height / 2 drawString(ipDebug, f"${leafIdx}", fontLeaf, colorLeafId, x, y) } val leafXySet = leafBlob.toXys.toSet val assocBlobs = spotBlobs.filter { spotBlob => val (centroidX, centroidY) = spotBlob.getCentroid leafXySet.contains((centroidX.round.toInt, centroidY.round.… } sortBy(- _.size)
  • 37. for ((blob, blobIdx) <- assocBlobs.zipWithIndex) { blob.drawToIpByColor(ipDebug, colorSpot) val x = blob.xsMin - 3 val y = (blob.ysMin + blob.ysMax) / 2 + 10 drawString(ipDebug, f"${blobIdx}", fontSpot, colorSpotId, x, y) } UtilIj.writeln(f"leafIdx;¥t$leafIdx") UtilIj.writeln(f"leafArea;¥t${leafBlob.size * shrink() * shrink(… UtilIj.writeln(f"spotNum;¥t${assocBlobs.size}") val spotTotalArea = assocBlobs.map(_.size).sum UtilIj.writeln(f"spotTotalArea;¥t${spotTotalArea * shrink() * shr… for ((spotBlob, spotIdx) <- assocBlobs.zipWithIndex) { UtilIj.writeln(f" spotArea;¥t${leafIdx}-${spotIdx};¥t" + f"${spotBlob.size * shrink() * shrink()}") } UtilIj.writeln("") } null }
  • 38. private def setParam(): Boolean = { input(sep1, shrink, leafDenoise, leafThr, spotDenoise, spotThr, genStk, sep2, leafMinArea, spotCircularity, sep3, continuePlugIn) mode.setIdx(0) continuePlugIn() } }