固定しきい値処理
ある一定の値より上か、下かと言った話。
ソースコード
func StaticThreshold(th uint32) icom.EffectFunc {
return func(img image.Image, x, y int) color.RGBA64 {
r, _, _, a := img.At(x, y).RGBA()
val := ex.ColorWidth
if r < th {
val = 0
}
return color.RGBA64{uint16(val), uint16(val), uint16(val), uint16(a)}
}
}
もはや説明は不要ですね、これくらい分かりやすいと良いです。
## 出力結果
こうやって光の当たり方がおかしいとこういう感じになるよ、ってな具合。
元画像
処理画像
可変しきい値処理
以下の手順で画素の値を決定する、と理解した。
- ある一点に対し、任意に範囲を指定し、その範囲の画素の平均をとる
- 平均に対して、前回の判定が明るい側なら任意の値を減算する
- 平均に対して、前回の判定が暗い側なら任意の値を加算する。
- その平均とある一点のどちらが明るいかで0or明るさ最大かを決める。
ソースコード
がとにかくややこしかった、おそらく整理する術はあるけど、ほっとこう。
最新販の本にはましなソースコードがあるのだろけ?
func VariableThreshold(size, width int, isBlack bool) icom.EffectFunc {
data := VariableData{-1, 0}
return func(img image.Image, x, y int) color.RGBA64 {
// y軸が変わったら初期化するだけ
createGrayBase(&data, y, isBlack)
point := img.Bounds().Size()
//平均を取る画素の範囲を作成する
y1, y2 := getVariableRange(y, point.Y, size)
x1, x2 := getVariableRange(x, point.X, size)
ave := getAverage(img, x1, x2, y1, y2)
var th int
// 前回の変化した種類によって基準値を変化させる。
if data.grayBase == ex.ColorWidth {
th = ave - width
} else {
th = ave + width
}
//平均値より明るいか?
r, _, _, a := img.At(x, y).RGBA()
v := uint16(0)
if r >= uint32(th) {
v = ex.ColorWidth
}
data.grayBase = int(v)
return color.RGBA64{v, v, v, uint16(a)}
}
- 関数名createじゃなくてinit
- getVariableRangeも含めてgetAverage
- 大きく3セクションに分けるべきだったかなと思う。
という反省が出てきた。
中の関数について解説しても良いけど、論理を知るべきだと思うのでソースコードよりも図を描いてあげたいところですね。
getVariableRangeの中身
平均を取るための範囲を取得します。DRY?何それ?
func getVariableRange(pos, max, siz int) (int, int) {
var v1, v2 int
// 最初から現在値+規定値の半分だけ
if pos < siz/2 {
// pos-siz/2最初突破の場合
v1 = 0
v2 = pos + siz/2
} else if (max - 1 - pos) < siz/2 {
// pos〜最大オーバーの場合
v1 = pos - siz/2
v2 = max - 1
} else {
// 大体ここ
v1 = pos - siz/2
v2 = pos + siz/2
}
return v1, v2
}
出力結果
はい、文字が読めますね、おめでとうございます。
やっぱ、こういうのは習った方が早そうですけど、OpenCVあるから面倒なんでやらんだろうな。