4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

golangで画像の2値化を実施する

Posted at

固定しきい値処理

ある一定の値より上か、下かと言った話。

ソースコード

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)}
	}
}

もはや説明は不要ですね、これくらい分かりやすいと良いです。
## 出力結果
こうやって光の当たり方がおかしいとこういう感じになるよ、ってな具合。

元画像

test2.jpg

処理画像

test_static_th.png

可変しきい値処理

以下の手順で画素の値を決定する、と理解した。

  • ある一点に対し、任意に範囲を指定し、その範囲の画素の平均をとる
  • 平均に対して、前回の判定が明るい側なら任意の値を減算する
  • 平均に対して、前回の判定が暗い側なら任意の値を加算する。
  • その平均とある一点のどちらが明るいかで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あるから面倒なんでやらんだろうな。
test_vari_th.png

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?