Skip to content

Instantly share code, notes, and snippets.

@athurg
Created October 31, 2017 03:25
Show Gist options
  • Save athurg/d59d6c8fa379f39ab7c2afc697def048 to your computer and use it in GitHub Desktop.
Save athurg/d59d6c8fa379f39ab7c2afc697def048 to your computer and use it in GitHub Desktop.
Golang版本的图像二值化分析范例
package main
import(
"fmt"
"os"
"image"
"image/jpeg"
"image/draw"
)
func main(){
for i:=1; i<=5; i++ {
fromFile := fmt.Sprintf("%d.jpg", i)
toFile := fmt.Sprintf("gray_%d.jpg", i)
convertJpegToGray(fromFile, toFile)
}
}
func createGrayImageFromJpegFile(file string) (image.Image, error) {
f, err := os.Open(file)
if err!=nil {
return nil, err
}
defer f.Close()
colorImage, err := jpeg.Decode(f)
if err!=nil {
return nil, err
}
grayImage := image.NewGray(colorImage.Bounds())
draw.Draw(grayImage, colorImage.Bounds(), colorImage, colorImage.Bounds().Min, draw.Src)
return grayImage,nil
}
func convertJpegToGray(fromFile,toFile string) error {
grayImage, err := createGrayImageFromJpegFile(fromFile)
if err !=nil {
return err
}
w, err := os.Create(toFile)
if err!=nil {
return err
}
defer w.Close()
return jpeg.Encode(w, grayImage, nil) //保存文件
//统计
//width := size.Dx()
//height := size.Dy()
//zft := make([]int, 256)//用于保存每个像素的数量,注意这里用了int类型,在某些图像上可能会溢出。
//var idx int
//for i := 0; i < width; i++ {
// for j := 0; j < height; j++ {
// idx = i*height + j
// zft[pic.Pix[idx]]++ //image对像有一个Pix属性,它是一个slice,里面保存的是所有像素的数据。
// }
//}
//灰度化结果
//fz := uint8(GetOSTUThreshold(zft))
//for fz := uint8(0); fz<255; fz++ {
//do(pic, fz)
//}
}
//二值化
func toValued(oriPic *image.Gray, fz uint8) {
pic := new(image.Gray)
pic.Stride = oriPic.Stride
pic.Rect = oriPic.Rect
pic.Pix = make([]uint8, len(oriPic.Pix))
copy(pic.Pix, oriPic.Pix)
zeroCount := 0
for i := 0; i < len(pic.Pix); i++ {
//以下是内外区间法,像素差5以内算同一像素
if (pic.Pix[i] - fz) > 5 {
pic.Pix[i] = 255
} else {
zeroCount += 1
pic.Pix[i] = 0
}
//以下是区间法,大于fz为白,否则为黑
//if pic.Pix[i] > fz {
// pic.Pix[i] = 255
//} else {
// pic.Pix[i] = 0
//}
}
//只保留白色为1%~2%的图像
r := float32(zeroCount)/float32(len(pic.Pix))
if r > 0.02 || r < 0.01 {
return
}
w, _ := os.Create(fmt.Sprintf("result/black_white%03d_%.0f.jpg", fz, 100 * float32(zeroCount)/float32(len(pic.Pix))))
defer w.Close()
jpeg.Encode(w, pic, nil)
}
//直方图获取二值化中间值
func GetOSTUThreshold(HistGram []int) int {
var Y, Amount int
var PixelBack, PixelFore, PixelIntegralBack, PixelIntegralFore, PixelIntegral int
var OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma float64 // 类间方差;
var MinValue, MaxValue int
var Threshold int = 0
for MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++ {
}
for MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue-- {
}
if MaxValue == MinValue {
return MaxValue // 图像中只有一个颜色
}
if MinValue+1 == MaxValue {
return MinValue // 图像中只有二个颜色
}
for Y = MinValue; Y <= MaxValue; Y++ {
Amount += HistGram[Y] // 像素总数
}
PixelIntegral = 0
for Y = MinValue; Y <= MaxValue; Y++ {
PixelIntegral += HistGram[Y] * Y
}
SigmaB = -1
for Y = MinValue; Y < MaxValue; Y++ {
PixelBack = PixelBack + HistGram[Y]
PixelFore = Amount - PixelBack
OmegaBack = float64(PixelBack) / float64(Amount)
OmegaFore = float64(PixelFore) / float64(Amount)
PixelIntegralBack += HistGram[Y] * Y
PixelIntegralFore = PixelIntegral - PixelIntegralBack
MicroBack = float64(PixelIntegralBack) / float64(PixelBack)
MicroFore = float64(PixelIntegralFore) / float64(PixelFore)
Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore)
if Sigma > SigmaB {
SigmaB = Sigma
Threshold = Y
}
}
return Threshold
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment