ここから本文です
ベランダ菜園とWindows用アプリ作成とExcel用アプリ(アドイン)作成

書庫全体表示

記事検索
検索
いちごにカビ生える
イメージ 1
イメージ 2
すぐ隣りにあるものは平気だったりするから、運だねえ
ナメクジ被害はナメトールが効いたのかこの1週間ではなかった

イメージ 3
これは収穫できるかなと思って

イメージ 4
裏側を確認したら、腐ったような感じになっていた
黒マルチに接触していたのが良くなかったかも

いつもの
イメージ 5
イメージ 6
茶色く腐ってしなびるのは毎年出てくる

イメージ 7
イメージ 8
ヘタのところが茶色く枯れていたり

5/8の収穫
イメージ 9
1年放置プランターから
いまいち

イメージ 10
イメージ 11
ヘタとの境目のところが腐っている

イメージ 12
秋に移植したプランターから
こっちもいまいち

イメージ 13
12個中3個が水に沈んだ
普通はどっちなんだろう
沈んだものは密度が高いせいか歯ごたえのある食感、硬め
味の差異はないかなあ

イメージ 14
全体的にイマイチな味だった

5/10の収穫
イメージ 15
1年放置プランターから3つ

イメージ 16
またヘタのところが腐ったようになっている


イメージ 17
秋に移植したプランターからも3つ

イメージ 18
こちらはそこそこ良い


今日、2019/05/12
イメージ 19
放置度が一番高いプランターは成長が遅かったけど

イメージ 20
この辺はようやく収穫できそう

イメージ 21
一度枯れかけた鉢
なんとかいちごっぽさを保っている

種から2年目の鉢
イメージ 22
摘蕾しなかったせいもあって小さい実がたくさん

カラスの被害なし
イメージ 23
今年は不作で実が目立たないせいかな


トマト(レッドオーレ)
イメージ 24
硫安で追肥した

イメージ 25
普通ならこの大きさだと、まだ最初のふたばが残っているはずなんだけど
双葉どころかその上の本葉までも黄色く枯れかけている

イメージ 26
水かけてこんな感じで

3日後の今日
イメージ 27
あんまり変わっていないと思っていたけど
写真で見比べてみたらぜんぜん違うねえ

イメージ 28
だいぶ良くなったけどまだいろいろ足りていないはず
種まきから2ヶ月以上経ったけど普通なら花が咲き始める


山芋のむかご
イメージ 29
ほぼ同じ条件なのに1ヶ月も差が出た
これで6個中5個発芽

残り1個
イメージ 30
このプランターはすぐ苔が生える
晴れの日が続くと枯れた苔がカチカチに固まるから
それを突き崩していたら発芽していない1個が出てきた
緑の棒の先がそれ
このあと土をかけて水もかけておいた


数年放置の山芋からのツル
イメージ 31
脇芽も伸びてきた
手前の2本がそれだけど

イメージ 32
イメージ 33
葉っぱが出ているところから伸びてきていて20本以上ある

脇芽じゃないツルの方
イメージ 34
斜めや横に張ったビニール紐には巻きついてくれないので

イメージ 35
山芋のツル巻き職人の朝は早い(お昼近い)


イメージ 36
芋の先端を地上に出したのも結構伸びてきた

大きめの芋2つ植えたプランター
イメージ 37
やっと発芽した
むかごやら小さな芋からの発芽は100個近くになりそう

イメージ 38
植え付けた位置とツルの太さからこれのハズ
埋め直した芋以外ではこれで全部発芽したかな

むかごから2年目のプランター
イメージ 39
前回埋め直した3つは変化なし

イメージ 40
発芽している3つは順調につるが伸びている


スイートバジル
イメージ 41
少しづつ大きくなっているけどトマトと同様に肥料が足りてない

にんにく(遠州極早生)
イメージ 42
左は収穫してもいいかなあくらいになってきた

イメージ 43
むかごからのものはにんにくの芽(トウ)が出ないので倒れてきた

イメージ 44
イメージ 45
むかごも大きくなって色がついてきた

マツバウンランとオオマツバウンラン
イメージ 46
だいぶ枯れたので

イメージ 47
終了
ここにトマトを植えようかなあ

イメージ 48
よく見たらいちごが発芽していたけど
今日見たらすっかり枯れてしまっていた

いちごの採種
イメージ 49
2年くらい前からあちこちでいちごが発芽してくるので
自分でも試してみようかと


関連記事
前回、2019/5/5
いちご初収穫、山芋を埋め直した、山芋の芽と根は芋のどこから出てくるのか ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15949192.html


次回、2019/05/19
にんにくの収穫1回め、山芋のツルが折れてちぎれる風速 ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15959271.html


画像のエッジ抽出、ラプラシアンフィルタ、ラプラシアンオペレータ

ラプラシアンフィルタでエッジ抽出した結果
イメージ 1
色の境界、輪郭を白で表現する感じ

元の画像
イメージ 2


この前のガウスぼかしと同じようにカーネル(マスク、オペレータ)があって
イメージ 3
この2つがよく使われるみたい、左が上下左右の4近傍、右が斜めも入れた8近傍


中心の注目ピクセルと、その周りとの輝度差が大きいほど、結果も大きく(白く)なってエッジ(輪郭)になって、差が全くなければプラスマイナス0(黒)


イメージ 4
8近傍のほうがより強く表現される
最大差
中心輝度が0で周りが255のとき
4近傍だと、255*4-0*4=1020
8近傍だと、255*8-0*8=2040
輝度の最大は255だからそれ以上でも切り捨てになるけど、8近傍のほうがちょっとした差でも大きな差になって現れてくるってことかな


8近傍のとき上下左右の重みを増して2にしてみると
イメージ 5
さらに強くなった



差を絶対値で取ると
イメージ 6
二重線みたいになる

輝度差でエッジを表現するなら、-100も100も同じ100差なんだから絶対値で計算すればいいのかと思ったら、そうでもないようで場合によりけりみたい



エクセル方眼紙で確認
イメージ 7
左が元の画像で、右2つがエッジ抽出
元画像は黒(0)と白(255)の間に中間の灰色(128)が1ピクセルあるけど
普通に離れて見た場合は灰色は見えなくて黒と白が隣接しているように見えるはず


イメージ 8
輝度にマイナスはないから-127は0(黒)に置き換えられるので

イメージ 9
エッジとして出てくる線は1本

絶対値でみると
イメージ 10
線が2本になる

正確さでいったら絶対値で取ったほうかなあ
白と灰色とのエッジと、灰色と黒のエッジの2つが出てきたほうが自然だと思う
でも実際の画像で見ると絶対値の方はブレたように見えるから不自然なんだよねえ



イメージ 11
白背景に黒の1ピクセル幅のライン

イメージ 12
これも絶対値じゃない方は1ピクセル幅で太さが変わっていないから自然に見える
絶対値だと2ピクセル幅になって不自然な印象



イメージ 13
黒背景に白の1ピクセル幅のライン

イメージ 14
今度は逆に絶対値じゃないほうが2重線になって不自然



5x5のカーネル
イメージ 15
ググって見つかったカーネルを試してみた
どれもエッジって感じがしないかなあ、これなら3x3のカーネルのほうがいいと思った、使いみちによるのかも

画像のぼかし処理にはザラザラしたノイズを抑える効果もあるけど、輪郭(エッジ)もぼやけてしまう
今回のエッジ抽出を使ってエッジ以外をぼかし処理すれば、エッジを残したままノイズだけを抑えた画像ができるかも


イメージ 18
見た目的にきれいなエッジが欲しい時は絶対値じゃないほうだなあ
でもエッジを残してのぼかしは絶対値の方だと思うんだよねえ



エクセル方眼紙でいろいろ試してみた
左が元の画像、右に並んでいるのが3x3カーネルでいろいろ
クリック注意
大きな画像2511x7521ピクセル
イメージ 17





参照したところ

convolution - When should the sum of all elements of a gaussian kernel be zero? -Signal Processing Stack Exchange
https://dsp.stackexchange.com/questions/8501/when-should-the-sum-of-all-elements-of-a-gaussian-kernel-be-zero

・空間フィルタ2 ラプラシアンフィルタ: 虹色の旋律
http://nijikarasu.cocolog-nifty.com/blog/2014/07/2-4d2e.html

画像処理・実習 第五回: 空間フィルタ (特徴抽出,ラプラシアン,鮮鋭化) 東海大学 情報理工学部情報メディア学科 濱本和彦. - ppt download
https://slidesplayer.net/slide/11007913/

微分フィルタで画像のエッジ抽出 - Qiita
https://qiita.com/shim0mura/items/5d3cbef873f2dd81d82c

エッジ検出・エッジ強調・ぼかし: koujinz blog
http://koujinz.cocolog-nifty.com/blog/2009/05/post-200b.html

【画像処理】ラプラシアンフィルタの原理・特徴・計算式 | アルゴリズム雑記
https://algorithm.joho.info/image-processing/laplacian-filter/


微分ってなんやねん、セブンイレブンかよ




ラプラシアンフィルタ、上下左右の4近傍

/// <summary>
/// エッジ抽出、注目ピクセル*4-上下左右、PixelFormats.Gray8専用
/// </summary>
/// <param name="pixels">画像の輝度値配列</param>
/// <param name="width">横ピクセル数</param>
/// <param name="height">縦ピクセル数</param>
/// <param name="absolute">trueなら絶対値で計算</param>
/// <returns></returns>
private (byte[] pixels, BitmapSource bitmap) Filterラプラシアン(byte[] pixels, int width, int height, bool absolute = false)
{
byte[] filtered = new byte[pixels.Length];//処理後の輝度値用
int stride = width;//一行のbyte数、Gray8は1ピクセルあたりのbyte数は1byteなのでwidthとおなじになる

for (int y = 1; y < height - 1; y++)
{
for (int x = 1; x < width - 1; x++)
{
int p = x + y * stride;//注目ピクセルの位置
int total = 0;
total += pixels[p - stride];//上のピクセル
total += pixels[p - 1];//左
total += pixels[p + 1];//右
total += pixels[p + stride];//下
total -= pixels[p] * 4;//上下左右 - 注目ピクセル*4
if (absolute)
{
total = Math.Abs(total);//絶対値で計算
}
//0〜255の間に収める
total = total < 0 ? 0 : total > 255 ? 255 : total;
filtered[p] = (byte)total;
}
}
return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}

基本はこのまえのガウスぼかしと全く同じ、外周の1ピクセルは0で埋めるのも同じ
違うのはカーネルの数値だけだから、輝度にかける数値が違うだけ



8近傍

private (byte[] pixels, BitmapSource bitmap) Filterラプラシアン8近傍(byte[] pixels, int width, int height, bool absolute = false)
{
byte[] filtered = new byte[pixels.Length];//処理後の輝度値用
int stride = width;//一行のbyte数、Gray8は1ピクセルあたりのbyte数は1byteなのでwidthとおなじになる
int total;
int begin = stride + 1;
int end = pixels.Length - stride - 1;
for (int i = begin; i < end; i++)
{
total = 0;
total += pixels[i - stride - 1];//注目ピクセルの左上
total += pixels[i - stride]; //上
total += pixels[i - stride + 1];//右上
total += pixels[i - 1]; //左
total += pixels[i + 1]; //右
total += pixels[i + stride - 1];//左下
total += pixels[i + stride]; //した
total += pixels[i + stride + 1];//右下
total -= pixels[i] * 8;
if (absolute) total = Math.Abs(total);

total = total < 0 ? 0 : total > 255 ? 255 : total;
filtered[i] = (byte)total;
}

return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}


forを1個減らしてみた、こっちのほうが速いはずだけど誤差程度



5x5のカーネル、中心が-24でそれ以外は1の固定

private (byte[] pixels, BitmapSource bitmap) Filterラプラシアン5x5近傍(byte[] pixels, int width, int height, bool absolute = false)
{
//1, 1,  1, 1, 1
//1, 1,  1, 1, 1
//1, 1,-24, 1, 1
//1, 1,  1, 1, 1
//1, 1,  1, 1, 1
byte[] filtered = new byte[pixels.Length];//処理後の輝度値用
int stride = width;//一行のbyte数、Gray8は1ピクセルあたりのbyte数は1byteなのでwidthとおなじになる
int total;
int diff1 = -stride * 2 - 2;
int diff2 = -stride - 2;
int diff3 = -2;
int diff4 = stride - 2;
int diff5 = stride * 2 - 2;

for (int y = 2; y < height - 2; y++)
{
for (int x = 2; x < width - 2; x++)
{
int p = y * stride + x;
total = 0;
for (int z = 0; z < 5; z++)
{
total += pixels[p + diff1 + z];
total += pixels[p + diff2 + z];
total += pixels[p + diff3 + z];
total += pixels[p + diff4 + z];
total += pixels[p + diff5 + z];
}
total -= pixels[p];
total -= pixels[p] * 24;
if (absolute) total = Math.Abs(total);

total = total < 0 ? 0 : total > 255 ? 255 : total;
filtered[p] = (byte)total;
}
}
return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}

forをできるだけ使いたくないけど5x5だと参照ピクセルが25個もあってさすがに長くなるから一番内側の5個以外はforで





5x5のカーネル、汎用版
カーネルの数値はint[5,5]の配列で指定

private (byte[] pixels, BitmapSource bitmap) Filterラプラシアン5x5近傍2(int[,] weight, byte[] pixels, int width, int height, bool absolute = false)
{
byte[] filtered = new byte[pixels.Length];//処理後の輝度値用
int stride = width;//一行のbyte数、Gray8は1ピクセルあたりのbyte数は1byteなのでwidthとおなじになる
int total;

for (int y = 2; y < height - 2; y++)
{
for (int x = 2; x < width - 2; x++)
{
int p = y * stride + x;
total = 0;
for (int i = 0; i < 5; i++)
{
int pp = p + stride * (i - 2);
for (int j = 0; j < 5; j++)
{
total += pixels[pp + (j - 2)] * weight[i, j];
}
}
if (absolute) total = Math.Abs(total);

total = total < 0 ? 0 : total > 255 ? 255 : total;
filtered[p] = (byte)total;
}
}
return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}

さっきの固定だったカーネルを指定できるようにしたもの
ここは素直にforを使って書いた
これを使っているところは

private void Button_Click_11(object sender, RoutedEventArgs e)
{
if (MyPixels == null) { return; }
int[,] weight = {
{ -1, -4, -7, -4, -1 },
{ -4,  0,  8,  0, -4 },
{ -7,  8, 32,  8, -7 },
{ -4,  0,  8,  0, -4 },
{ -1, -4, -7, -4, -1 } };

(byte[] pixels, BitmapSource bitmap) = Filterラプラシアン5x5近傍2(
weight,
MyPixels,
MyBitmapOrigin.PixelWidth,
MyBitmapOrigin.PixelHeight,
(bool)CheckBoxAbsolute.IsChecked);
MyImage.Source = bitmap;
MyPixels = pixels;
}




画像の読み込み

/// <summary>
/// 画像ファイルからbitmapと、そのbyte配列を取得、ピクセルフォーマットを指定したものに変換
/// </summary>
/// <param name="filePath">画像ファイルのフルパス</param>
/// <param name="pixelFormat">PixelFormatsを指定</param>
/// <param name="dpiX">96が基本、指定なしなら元画像と同じにする</param>
/// <param name="dpiY">96が基本、指定なしなら元画像と同じにする</param>
/// <returns></returns>
private (byte[] array, BitmapSource source) MakeBitmapSourceAndByteArray(string filePath, PixelFormat pixelFormat, double dpiX = 0, double dpiY = 0)
{
byte[] pixels = null;
BitmapSource source = null;
try
{
using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
var bf = BitmapFrame.Create(fs);

var convertedBitmap = new FormatConvertedBitmap(bf, pixelFormat, null, 0);
int w = convertedBitmap.PixelWidth;
int h = convertedBitmap.PixelHeight;
int stride = (w * pixelFormat.BitsPerPixel + 7) / 8;
pixels = new byte[h * stride];
convertedBitmap.CopyPixels(pixels, stride, 0);
//dpi指定がなければ元の画像と同じdpiにする
if (dpiX == 0) { dpiX = bf.DpiX; }
if (dpiY == 0) { dpiY = bf.DpiY; }
//dpiを指定してBitmapSource作成
source = BitmapSource.Create(
w, h, dpiX, dpiY,
convertedBitmap.Format,
convertedBitmap.Palette, pixels, stride);
};
}
catch (Exception)
{
}
return (pixels, source);
}

いつもの


//画像ファイルドロップ時の処理
private void MainWindow_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop) == false) { return; }
string[] filePath = (string[])e.Data.GetData(DataFormats.FileDrop);
var (pixels, bitmap) = MakeBitmapSourceAndByteArray(filePath[0], PixelFormats.Gray8, 96, 96);

if (bitmap == null)
{
MessageBox.Show("画像ファイルじゃないみたい");
}
else
{
MyPixels = pixels;
MyPixelsOrigin = pixels;
MyBitmapOrigin = bitmap;
MyImage.Source = bitmap;
MyImageOrigin.Source = bitmap;
ImageFileFullPath = filePath[0];
}
}



ギットハブ
アプリダウンロード先
イメージ 16
画像ファイルドロップで表示、ボタンで変換、表示画像クリックで元の画像と切り替え



関連記事
2019/4/22
画像のぼかし処理、注目ピクセルとその上下左右の平均値に変換 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15938990.html


前回、2019/4/30は10日前
ガウス関数からカーネル作成、標準偏差とカーネルサイズ、グレースケール画像のぼかし処理 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15945699.html


次、2019/05/22は2週間後
画像にノイズ付加するアプリ、一様分布乱数から正規分布乱数生成、エクセルのNORMINV関数で正規乱数 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15961286.html


2019/05/29
メディアンフィルタで画像のノイズ除去試してみた、WPF、C# ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15965377.html



ナメクジに食べられたいちご、おととい
イメージ 2
イメージ 1
4/28〜5/1の3日間の雨でナメクジが出てきたみたい

イメージ 20
もう少しで収穫だったのに、雨のタイミングが良くなかった
1つカビまみれになっていたのも取り除いた

イメージ 3
一番大きなこれは無事だったのは運が良かった

ナメトール
イメージ 4
ナメクジ退治

イメージ 5
期限が切れてから2年
去年は効き目があった

イメージ 6
いちごの根元付近にばらまいた

いちご初収穫は昨日、2019/05/04
イメージ 7
赤くなった

イメージ 8
幅3センチ
毎年最初に収穫したものが一番大きいサイズになる

今までで一番美味しかった
イメージ 9
毎年味が薄いとか言っていたけど
これはそんなことなかった
原因は運が良かったのが一番だけどそれ以外だと
肥料を入れなかったのがあるかも
いつもは8-8-8の化成肥料やようりんを入れていたけど
化成肥料は去年尽きたので一回も入れていない


去年秋の植え替えの様子
イメージ 10
今回収穫した株は、この放置されたいちごから

イメージ 11
移植したものだった

イメージ 12
去年秋こうだったのが

今日、2019/05/05
イメージ 13
右上の株が初収穫になった株

まとめると
イメージ 14
プランターから飛び出たランナーの株は花は咲かず
ランナーの先の方、順番だと5,6番目以降くらいの株は1年目では実がつかない
元株⌒子株1⌒子株2⌒子株3⌒子株4⌒子株5⌒子株6⌒子株7
収穫できた株はたぶん3,4番目くらいの子株のはず

種から2年目
イメージ 15
植え替えしたときはアブラムシで枯れる寸前だったけど
花も咲いて実もついている

植え替えしなかった種から2年目
イメージ 16
こちらは花が咲かなかった株もある
なのでいちごは同じ株を使うにしても、植え替えしたほうがいいのかも?
でもめんどくさいんだよなあ

イメージ 17
花がつかなかった株からはランナーが伸びてきた

数年間放置されたプランターいちご
イメージ 18
ここは開花が遅かったのでまだチラホラ咲いている
株も小さいから実も小さい
肥料を入れないにしても数年かそれ以上全く入れないとこうなるのかも
だとすると肥料の調節が難しい

約1年放置した結果
イメージ 19
2株移植して1株枯れて、残った1株からここまで増える
プランターから飛び出たランナーは枯れてしまったから
場所さえあればもっと増えていた


にんにく(遠州極早生)
イメージ 21
葉っぱが枯れてきた
去年の収穫は5/17、にんにくの芽は去年のほうが5日早かった
ってことは今年は5/22くらいかな

イメージ 22
むかごも大きくなって外に飛び出てきた



山芋むかご2つ目発芽
イメージ 23
左の3つは約3週間前に発芽していたので
残りは発芽しないと思っていた

数年植えたままの山芋のツル
イメージ 24
イメージ 32
やっと雨がやんで見に行ったら
放置プランターに刺さった支柱に巻き付いていた


山芋のツルをビニール紐に巻き付かせる
イメージ 25
余っている支柱がないのでビニール紐をベランダ菜園に張って
それに巻きつけるようにしてみた

イメージ 26
一端をプランターに

イメージ 27
張った紐は登ったり降りたりになってしまった
ツルは上に伸びようとするから
多分手動で巻き付けていくことになるかな

2日後の2019/05/05
イメージ 28
やっぱり巻き付いてくれない

イメージ 29
手動で巻き付けてあげて長さを測ったら
1.6メートル、先週は1メートルだった

むかごから2年目の山芋
イメージ 30
ツルの伸び方が鈍い

イメージ 31
先端を地上に出して植えたのもはなかなか伸びない

先端を地中に埋めた山芋
イメージ 33
こちらは20〜70センチ位伸びている

たくさん発芽するむかご
イメージ 35
去年落ちたむかごや取り残した芋からの発芽

どんなふうに根が生えているのか
イメージ 36
これを引き抜いてみる

イメージ 37
縦長の芋が出てきた
この形はむかごじゃなくて去年むかごから成長した芋のはず

イメージ 38
相変わらず携帯電話のカメラの調子が悪くてピンぼけだけど
根が出てきている場所は芽が出てきているところと同じなのがわかる

別の芋
イメージ 39
これも芽と根が同じ場所から伸びている
むかごじゃなくて去年むかごから成長した芋かも

むかご
イメージ 40
小さいのでむかごの可能性が高いこれは
芽と同じ場所から伸びている根もあるけど
それより別の場所から生えている根のほうが多い

山芋の発根場所は
芋なら芽と同じ場所で
むかごなら芽と違う場所からもたくさん生えるのかも

だったらむかごから2年目のは芋だから
根が生える部分が地上に出ているのは良くないはず
だから土に埋めたものと差が出たんだろう

埋め直すことにした
イメージ 34
掘り出して横に寝かせて全体を土に埋め直した

イメージ 41
多分間に合うと思うけどどうかなあ

イメージ 42
鉢植えは4個のうち3個を埋め直した
1つはこのままだとどうなるか見たいのでそのまま

イメージ 43
ここも6つのうち地上に出していた3つを埋め直した


トマト(レッドオーレ)
イメージ 44
肥料が足りていない感じがする

スイートバジル
イメージ 45
こちらも元気がいまいち

シマヘビ?
イメージ 49
手前にあるゴミ箱の蓋を閉じたあとに気がついた
蓋は向こう側に倒れるように開く
閉じるときには蓋の下側(蛇側)に手を持っていくから
手と蛇の距離は5センチ以下だったかも

イメージ 50
蛇を見るのは何年ぶりだろう
咬まれなくてよかったわ


ミツバチ
イメージ 46
全く動かないからなんだろうと思ったら死んでいた

イメージ 47
こちらは木の塀をぐるぐる歩いていた

イメージ 48
何かを調査している感じ
前にも見たことあるけどなんだろうねえ



関連記事
次回、2019/05/12
例年通り腐るいちご、山芋のツルから脇芽(脇ツル)伸びる ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15954343.html

先週は2019/4/28
3週間目のにんにくの芽、食べたら硬かった、山芋のつる伸びる、昨日の強風 ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15943743.html


去年、2018/10/28
にんにく発芽、むかご山芋疑惑で植え付け、いちご移植 ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15730282.html




画像のぼかし処理で使うカーネルをガウス関数から作成してガウスぼかし

標準偏差の指定とぼかし具合
カーネルサイズは3x3で標準偏差を0.1、0.5、1.0
イメージ 1
標準偏差=0.1だと全くぼやけない、0.5でほんの少しぼやけたかなくらいで、1.0だとぼやけたのがはっきりわかる


標準偏差を1.5と2.0、5.0で比較
イメージ 2
どれも大差ない感じ


1次のガウス関数で標準偏差と距離によるカーネルの数値(重み)の変化
イメージ 3
縦が距離、横が標準偏差を0.5から0.5刻みのとき
中心(距離0)を100%としたときの重み


カーネルサイズ3x3で使う範囲
イメージ 4
数値は中心(0)ピクセルに対する影響度みたいなものだから
0.5では14%なので中心(0)の輝度はほとんど変化しないので、ぼやけ方が小さい
1.0では61%と急に高くなり、1.5で80%、そこからは変化が少ない
だからさっきの画像の比較でも1.5と5.0も同じように見えたのかも
これだと2以上を指定する意味は薄いねえ、逆に0.5から1.0は細かく分けたい


カーネルサイズ5x5で使う範囲だと
イメージ 5
外側の-2と2は標準偏差2と3の間で、変化量は19あるから意味あるかも



0.1から1.5を0.1刻み
イメージ 6
サイズ3x3でも0.3以下は全くぼやけないみたい
ぼやけ具合の調整を標準偏差でする場合、カーネルサイズ3x3なら、0.5から1.4までを0.1刻みで10段階の指定が良さそう



カーネルサイズとぼやけ具合
イメージ 7
5x5以上は違いが感じられない

カーネル 3x3 5x5 7x7 9x9
距離 0, 1, 2, 3, 4
影響 100, 61, 14, 1, 0

5x5と9x9だと14%の差があるけど、この程度だと違いがわからない



標準偏差=2.0
イメージ 8
3x3と5x5はかなり差があるけど
それ以上は差は出ているけど小さいかな
んーでも5x5と9x9を比較すると結構差がある感じもする

カーネル 3x3 5x5 7x7 9x9
距離 0, 1, 2, 3, 4
影響 100, 88, 61, 32, 14



処理時間
10年目のパソコンで、横x縦ピクセル数=2048x1536の画像を処理するとき
カーネルサイズ 時間
3x3 0.1秒
5x5 1秒
7x7 2秒
9x9 3.5秒
体感だとこんなだった、3x3ならリアルタイムでも行けるかなあってくらい



よりぼかしたいときはカーネルサイズを大きくするより
小さなサイズで処理を繰り返したほうが速い
イメージ 9
カーネルサイズ3x3で5回処理したほうが
速いし、よりぼやける

イメージ 10
輝度補正あり
見比べれば違うのがわかるくらいの差
元画像は
イメージ 11
これ

色(輝度)の補正あり
カーネルサイズ 時間
3x3 3秒
5x5 8秒
7x7 14秒
9x9 23秒
かなり時間かかる
この場合もよりぼかすときはカーネルサイズを大きくするより、小さなサイズで処理を繰り返したほうが速そう




デザイン画面
イメージ 12


MainWindow.xaml.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace _20190427_ガウス関数
{
public partial class MainWindow : Window
{
string ImageFileFullPath;//ファイルパス、画像保存時に使う
BitmapSource MyBitmapOrigin;//元画像、リセット用
byte[] MyPixelsOrigin;//元画像、リセット用
byte[] MyPixels;//処理後画像

public MainWindow()
{
InitializeComponent();

this.Drop += MainWindow_Drop;
this.AllowDrop = true;

}


/// <summary>
/// ガウスぼかし用のカーネル作成
/// </summary>
/// <param name="stdev">標準偏差(standard deviation)、0より大きい数値を指定
/// 0.1〜3くらい、大きくするとよりぼやける、</param>
/// <param name="size">Kernelサイズ、3以上の奇数を指定、3か5が適当</param>
/// <returns></returns>
private (double[,] kernel, double div) Makeガウシアンカーネル(double stdev, int size)
{
//1次のガウス関数の配列作成
double variance = stdev * stdev;//分散
double f = 1 / Math.Sqrt(2 * Math.PI * variance);//expの前
int length = size / 2;//0からの距離
double[] temp = new double[size];
//確率密度関数(ガウス関数)
for (int i = 0; i < size; i++)
{
var f2 = -(Math.Pow(i - length, 2) / (2 * variance));//expの指数
var f3 = f * Math.Pow(Math.E, f2);//ガウス関数
temp[i] = f3;
}

//1次*1次から2次のガウス関数作成
double[,] kernel = new double[size, size];
double div = 0;//割るときに使う総和
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
kernel[i, j] = temp[i] * temp[j];
div += kernel[i, j];
}
}

return (kernel, div);
}



/// <summary>
/// Kernelサイズ3x3専用、PixelFormats.Gray8専用
/// </summary>
/// <param name="stdev">標準偏差</param>
/// <param name="size">カーネルのサイズ</param>
/// <param name="pixels">ピクセルの輝度の配列</param>
/// <param name="width">画像の横ピクセル数</param>
/// <param name="height">画像の縦ピクセル数</param>
/// <returns></returns>
private (byte[] pixels, BitmapSource bitmap) Filterガウシアンフィルタ3x3(
double stdev, int size, byte[] pixels, int width, int height)
{
//カーネル作成とその合計値を取得
(double[,] kernel, double div) = Makeガウシアンカーネル(stdev, size);
byte[] filtered = new byte[pixels.Length];//処理結果用
int stride = width;//一行のbyte数
//上下左右1ラインは処理しない(めんどくさい)
for (int y = 1; y < height - 1; y++)
{
for (int x = 1; x < width - 1; x++)
{
//Kernelサイズ範囲のピクセルに重みをかけた合計の平均値を新しい値にする
double total = 0;
for (int i = 0; i < 3; i++)
{
int p = x + ((y + i - 1) * stride);//注目ピクセルの位置
for (int j = 0; j < 3; j++)
{
total += pixels[p + j - 1] * kernel[i, j];
}
}

int average = (int)(total / div);
filtered[x + y * stride] = (byte)average;
}
}

return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}

  
private (byte[] pixels, BitmapSource bitmap) Filterガウシアンフィルタ2サイズ指定(
double stdev, int size, byte[] pixels, int width, int height)
{
//カーネル作成とその合計値を取得
(double[,] kernel, double div) = Makeガウシアンカーネル(stdev, size);

byte[] filtered = new byte[pixels.Length];//処理結果用
int stride = width;//一行のbyte数
//Kernelの範囲外になるピクセルは処理しない(めんどくさい)
int range = kernel.GetLength(0) / 2;//範囲外ピクセルのライン数
for (int y = range; y < height - range; y++)
{
for (int x = range; x < width - range; x++)
{
//Kernelサイズ範囲のピクセルに重みをかけた合計の平均値を新しい値にする
double total = 0;
for (int i = 0; i < size; i++)
{
int p = x + ((y + i - range) * stride);//注目ピクセルの位置
for (int j = 0; j < size; j++)
{
total += pixels[p + j - range] * kernel[i, j];
}
}
int average = (int)(total / div);
filtered[x + y * stride] = (byte)average;
}
}
return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}

   

//補正あり
private (byte[] pixels, BitmapSource bitmap) Filterガウシアンフィルタサイズ指定色補正あり(
double stdev, int size, byte[] pixels, int width, int height)
{
//カーネル作成とその合計値を取得
(double[,] kernel, double div) = Makeガウシアンカーネル(stdev, size);

byte[] filtered = new byte[pixels.Length];//処理結果用
int stride = width;//一行のbyte数
//Kernelの範囲外になるピクセルは処理しない(めんどくさい)
int range = kernel.GetLength(0) / 2;//範囲外ピクセルのライン数
for (int y = range; y < height - range; y++)
{
for (int x = range; x < width - range; x++)
{
//Kernelサイズ範囲のピクセルに重みをかけた合計の平均値を新しい値にする
double total = 0;
for (int i = 0; i < size; i++)
{
int p = x + ((y + i - range) * stride);//注目ピクセルの位置
for (int j = 0; j < size; j++)
{
total += Math.Pow(pixels[p + j - range], 2.0) * kernel[i, j];
}
}
int average = (int)Math.Sqrt(total / div);
filtered[x + y * stride] = (byte)average;
}
}
return (filtered, BitmapSource.Create(
width, height, 96, 96, PixelFormats.Gray8, null, filtered, width));
}



#region その他

//画像ファイルドロップ時の処理
private void MainWindow_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop) == false) { return; }
string[] filePath = (string[])e.Data.GetData(DataFormats.FileDrop);
var (pixels, bitmap) = MakeBitmapSourceAndByteArray(filePath[0], PixelFormats.Gray8, 96, 96);

if (bitmap == null)
{
MessageBox.Show("画像ファイルじゃないみたい");
}
else
{
MyPixels = pixels;
MyPixelsOrigin = pixels;
MyBitmapOrigin = bitmap;
MyImage.Source = bitmap;
MyImageOrigin.Source = bitmap;
ImageFileFullPath = filePath[0];
}
}


//画像の保存
private void SaveImage(BitmapSource source)
{
var saveFileDialog = new Microsoft.Win32.SaveFileDialog();
saveFileDialog.Filter = "*.png|*.png|*.bmp|*.bmp|*.tiff|*.tiff";
saveFileDialog.AddExtension = true;
saveFileDialog.FileName = System.IO.Path.GetFileNameWithoutExtension(ImageFileFullPath) + "_";
saveFileDialog.InitialDirectory = System.IO.Path.GetDirectoryName(ImageFileFullPath);
if (saveFileDialog.ShowDialog() == true)
{
BitmapEncoder encoder = new BmpBitmapEncoder();
if (saveFileDialog.FilterIndex == 1)
{
encoder = new PngBitmapEncoder();
}
else if (saveFileDialog.FilterIndex == 2)
{
encoder = new BmpBitmapEncoder();
}
else if (saveFileDialog.FilterIndex == 3)
{
encoder = new TiffBitmapEncoder();
}
encoder.Frames.Add(BitmapFrame.Create(source));

using (var fs = new System.IO.FileStream(saveFileDialog.FileName, System.IO.FileMode.Create, System.IO.FileAccess.Write))
{
encoder.Save(fs);
}
}
}


/// <summary>
/// 画像ファイルからbitmapと、そのbyte配列を取得、ピクセルフォーマットを指定したものに変換
/// </summary>
/// <param name="filePath">画像ファイルのフルパス</param>
/// <param name="pixelFormat">PixelFormatsを指定</param>
/// <param name="dpiX">96が基本、指定なしなら元画像と同じにする</param>
/// <param name="dpiY">96が基本、指定なしなら元画像と同じにする</param>
/// <returns></returns>
private (byte[] array, BitmapSource source) MakeBitmapSourceAndByteArray(string filePath, PixelFormat pixelFormat, double dpiX = 0, double dpiY = 0)
{
byte[] pixels = null;
BitmapSource source = null;
try
{
using (System.IO.FileStream fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
var bf = BitmapFrame.Create(fs);

var convertedBitmap = new FormatConvertedBitmap(bf, pixelFormat, null, 0);
int w = convertedBitmap.PixelWidth;
int h = convertedBitmap.PixelHeight;
int stride = (w * pixelFormat.BitsPerPixel + 7) / 8;
pixels = new byte[h * stride];
convertedBitmap.CopyPixels(pixels, stride, 0);
//dpi指定がなければ元の画像と同じdpiにする
if (dpiX == 0) { dpiX = bf.DpiX; }
if (dpiY == 0) { dpiY = bf.DpiY; }
//dpiを指定してBitmapSource作成
source = BitmapSource.Create(
w, h, dpiX, dpiY,
convertedBitmap.Format,
convertedBitmap.Palette, pixels, stride);
};
}
catch (Exception)
{
}
return (pixels, source);
}

//画像クリックで元画像と処理後画像の切り替え
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
int aa = Panel.GetZIndex(MyImage);
Panel.SetZIndex(MyImageOrigin, aa + 1);
}

private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
int aa = Panel.GetZIndex(MyImage);
Panel.SetZIndex(MyImageOrigin, aa - 1);
}

//表示画像リセット
private void Button_Click_2(object sender, RoutedEventArgs e)
{
MyImage.Source = MyBitmapOrigin;
MyPixels = MyPixelsOrigin;
}

//画像保存
private void Button_Click_3(object sender, RoutedEventArgs e)
{
if (MyImage.Source == null) { return; }
//BitmapSource source = (BitmapSource)MyImage.Source;
//SaveImage(new FormatConvertedBitmap(source, PixelFormats.Indexed4, new BitmapPalette(source, 16), 0));
//SaveImage(new FormatConvertedBitmap(source, PixelFormats.Indexed4, null, 0));
SaveImage((BitmapSource)MyImage.Source);
}

#endregion

//ぼかしフィルタ処理
private void Button_Click(object sender, RoutedEventArgs e)
{
if (MyPixels == null) { return; }
(byte[] pixels, BitmapSource bitmap) = Filterガウシアンフィルタ3x3(
Slider標準偏差.Value,
3,
MyPixels,
MyBitmapOrigin.PixelWidth,
MyBitmapOrigin.PixelHeight);
MyImage.Source = bitmap;
MyPixels = pixels;
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (MyPixels == null) { return; }
(byte[] pixels, BitmapSource bitmap) = Filterガウシアンフィルタ2サイズ指定(
Slider標準偏差.Value,
(int)SliderKernelサイズ.Value,
MyPixels,
MyBitmapOrigin.PixelWidth,
MyBitmapOrigin.PixelHeight);
MyImage.Source = bitmap;
MyPixels = pixels;
}



private void Button_Click_7(object sender, RoutedEventArgs e)
{
if (MyPixels == null) { return; }
(byte[] pixels, BitmapSource bitmap) = Filterガウシアンフィルタサイズ指定色補正あり(
Slider標準偏差.Value,
(int)SliderKernelサイズ.Value,
MyPixels,
MyBitmapOrigin.PixelWidth,
MyBitmapOrigin.PixelHeight);
MyImage.Source = bitmap;
MyPixels = pixels;

}
}
}

色が薄い文字のところはぼかし処理と関係ない


ガウス関数を使ってカーネル作成
ガウス関数(1次元)
イメージ 14
ガウスぼかしには平均の値は0でいいのでこれで

標準偏差とカーネルサイズを指定してカーネル作成
イメージ 13
標準偏差σの2乗σ^2は分散varianceの意味、73行目
74行目の変数fにはガウス関数のexpの前の分数の部分
変数f2にはexpの指数(右側のカッコの中)部分、80行目
自然対数の底はMathクラスにあった!81行目のMath.Eがそれ
イメージ 15
候補にはExpもある
81行目、変数f3にはガウス関数での結果、これは1次元になる
ガウス関数の2次は1次*1次なのでf3同士を掛け算が92行目
93行目のdivはカーネルの中の数値の合計

今思ったけど最初から2次のガウス関数を使ったほうがスッキリ書けたかも?
イメージ 16
2次のガウス関数



標準偏差=1の3x3カーネルの中
イメージ 17
1以下の小さな数値ばかりが入っているけど、このまま使う

エクセルのNORMDIST関数で計算したとき
イメージ 18
これと同じ値になっている
これを端の最小値が1になるようにして、さらに四捨五入すると
イメージ 19
こうなるけど、ここまでする必要がなかったのでそのまま使う


カーネルの値を使ってぼかし処理
イメージ 20
カーネルサイズ3x3専用、サイズ指定があるけど3x3専用
このあたりは普通のカーネルを使って処理した前回と全く同じかな
整数に整えたカーネルでも、今回のように小数点のままでも処理自体は同じ


カーネルサイズ指定できる版
イメージ 21
これが本命になるかと思ったけど、カーネルサイズは3x3と5x5があれば十分な感じだからねえ


輝度補正あり版
イメージ 22
平方根の計算が重いと思うんだけど、なんかいい方法ないかしら




いまいちなぼかし
イメージ 23
標準偏差=5.0と大きくするとブレたようなぼかしになる



イメージ 24
REN FONT / タイポグラフィクス蓮=オリジナルフォントのダウンロードサイト
https://renfont.com/index.html
今回のフォントは、ところどころに隙間があるのがおもしろい「和音 Joyo R」でした





ギットハブ


アプリダウンロード(ギットハブ)
ウィンドウに画像ファイルドロップで画像表示、画像クリックで元の画像との切り替え





関連記事
前回2019/4/27は3日前
エクセルで2次のガウス関数(確率密度関数)、正規分布関数のNORMDIST ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15943071.html

前々回2019/4/27も3日前
エクセルで1次のガウス関数(確率密度関数)、正規分布関数のNORMDIST ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15942730.html


2019/4/25は5日前
画像のぼかし処理、8近傍平均とガウスぼかし、グレースケールで処理 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15941552.html

次、2019/05/10は10日後
画像のエッジ抽出、ラプラシアンフィルタ ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15953028.html

2019/05/22
画像にノイズ付加するアプリ、一様分布乱数から正規分布乱数生成、エクセルのNORMINV関数で正規乱数 ( ソフトウェア ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15961286.html



にんにくの芽収穫
2019/4/22
イメージ 1
芽が出てきたのが3/31だから約3週間
去年は3/26に出てきて、収穫は2週間後の4/8だった


イメージ 2
残したにんにくの芽の数は6個

イメージ 3
一番太いのでも2〜4ミリと細い
去年より細いと思ったけど確認したら同じくらいだった

イメージ 4
左のプランターからは13本

イメージ 5
右のプランターからは17本

イメージ 6
合計30本
3週間伸ばしたから長さだけはある

イメージ 7
むかごの少し下部分から上は硬いので取り除いて

イメージ 8
食べる部分
包丁で切っていても硬さが伝わってきて不安になる

イメージ 9
かなり火を通したけど柔らかくならない
スパゲッティ、鶏むね肉、キャベツ、ナス、きゅうり、コメ

イメージ 10
火にかけた時間が長かったせいか香りが飛んでしまった
外側は多少硬かったけど中は柔らかく
にんにくっぽいしっとりした感じで美味しかった
にんにくの芽の収穫は出てきてから2週間くらいが良さそう

イメージ 11
今日の様子
先に芽が出た左の方はσから∩になって曲がりがゆるくなってきた

イメージ 12
むかごの大きさ、約1センチ

トマト(レッドオーレ)
イメージ 14
ようやく大きくなってきた

スイートバジルといちご
イメージ 15
こっちも大きくなってきた
昨日と今日は寒いけどそれまでは暖かかったからねえ


マツバウンラン、オオマツバウンラン
イメージ 37
花よりも実のほうが目立つようになってきた

イメージ 38



山芋
イメージ 13
6個植えたプランター、残りの3つ芽が出てこない
意外に発芽率良くないのかなあ

むかご2年目
イメージ 16
6個植えたうち先週1つだけ芽が出て
1週間で30センチ伸びた

むかごからの発芽
イメージ 17
イメージ 18
50個くらい

地表に見えているむかご
イメージ 24
イメージ 25
目につくのだけでも20個くらいあるけどまだ発芽せず

むかごから2年目
イメージ 19
芋の先端から芽が伸びてきた
こんなふうに伸びてくるんだねえ
生え際に白い膨らみがいくつかあるのは根なのかも?
普通なら土に埋まっている部分だから、その確率高そう
だとしたらこのままだと良くないかなあ

別のむかごから2年目芋
イメージ 20
イメージ 21
膨らんできた

数年植えっぱなしの山芋
イメージ 22
1週間で20センチから1メートル近くまで伸びていた
結構大きい芋が埋まっているのかも

生え際
イメージ 23
近くから同じくらいの太さのツルも出てきた
同じ芋から2本出ているのか別の芋なのか
それとはまた別に右下から細いつるも出てきた
これはむかごから2年目のツルの太さに似ている



いちご
イメージ 26
開花のピークは過ぎた感じ

イメージ 27
小さい

イメージ 28
例年並みなのはこの株だけ

発芽していたいちごを新たに発見
イメージ 34
この先端が3つに分かれた形の本葉がいちごの目印
この辺の土は雑草の除去作業で引っ掻き回したところだから
これは最近発芽したってことなのかなあ
そうだとしたら

イメージ 35
これとか

イメージ 36
この辺のも去年秋じゃなくて、今年に発芽したのかも?


昨日の強風で
イメージ 29
実がついている柄の部分が折れ曲がる

イメージ 30
葉っぱ同士が擦れて黒くなる
左下から右に伸びている葉柄は根元付近で折れ曲がっている
今年はいちごの葉っぱが小さいからこの程度だけど
いつもは何枚かの葉っぱが、ちぎれ飛んでしまう

どれくらいの風だったのか
気象庁 Japan Meteorological Agency
http://www.jma.go.jp/jma/index.html
イメージ 31
風速11m/s
実際これくらいだったいいんだけどねえ


海の安全情報(沿岸域情報提供システム)
https://www6.kaiho.mlit.go.jp/
イメージ 32
こちらだと29m/s
海と目と鼻の先くらいのところで測定しているのかも

お天気.com
https://hp.otenki.com/
イメージ 33
こちらは予想で20m/s

ベランダ菜園での体感風速は15〜20m/s
海に近いと風が強いみたい
それも線形、リニアじゃなくて曲線なのかも
最近流行りのガウス関数だと標準偏差が低めな感じ

ベランダ菜園から海岸までは1kmくらい
気象庁のは海岸から10kmくらい離れているから
大きな差が出るのかも

でもこれが夏になると逆転して
こっちが0m/sのとき気象庁では2m/sとかになる



関連記事
次回、2019/05/05
いちご初収穫、山芋を埋め直した、山芋の芽と根は芋のどこから出てくるのか ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15949192.html


前回、2019/4/21は先週
山芋と山芋のむかご発芽、いちごの摘蕾 ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15938145.html


去年の同じ時期
にんにくの芽収穫、今年はマツバウンランが少ない ( ガーデニング ) - 午後わてんのブログ - Yahoo!ブログ
https://blogs.yahoo.co.jp/gogowaten/15451067.html



本文はここまでですこのページの先頭へ
みんなの更新記事