This repository has been archived by the owner on Dec 4, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 62
/
image.go
143 lines (129 loc) · 3.79 KB
/
image.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package qanswer
import (
"fmt"
"image"
"image/draw"
"sync"
"github.com/ngaut/log"
"github.com/silenceper/qanswer/config"
"github.com/silenceper/qanswer/proto"
"github.com/silenceper/qanswer/util"
)
func saveImage(png image.Image, cfg *config.Config) error {
go func() {
screenshotPath := fmt.Sprintf("%sscreenshot.png", proto.ImagePath)
err := util.SavePNG(screenshotPath, png)
if err != nil {
log.Errorf("保存截图失败,%v", err)
}
log.Debugf("保存完整截图成功,%s", screenshotPath)
}()
//裁剪图片
questionImg, answerImg, err := cutImage(png, cfg)
if err != nil {
return fmt.Errorf("截图失败,%v", err)
}
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
pic := thresholdingImage(questionImg)
err = util.SavePNG(proto.QuestionImage, pic)
if err != nil {
log.Errorf("保存question截图失败,%v", err)
}
log.Debugf("保存question截图成功")
}()
go func() {
defer wg.Done()
pic := thresholdingImage(answerImg)
err = util.SavePNG(proto.AnswerImage, pic)
if err != nil {
log.Errorf("保存answer截图失败,%v", err)
}
log.Debugf("保存answer截图成功")
}()
wg.Wait()
return nil
}
//裁剪图片
func cutImage(src image.Image, cfg *config.Config) (questionImg image.Image, answerImg image.Image, err error) {
questionImg, err = util.CutImage(src, cfg.QuestionX, cfg.QuestionY, cfg.QuestionW, cfg.QuestionH)
// questionImg, err = util.CutImage(src, 30, 250, 660, 135)
if err != nil {
return
}
answerImg, err = util.CutImage(src, cfg.AnswerX, cfg.AnswerY, cfg.AnswerW, cfg.AnswerH)
// answerImg, err = util.CutImage(src, 30, 420, 690, 430)
if err != nil {
return
}
return
}
//二值化图片
func thresholdingImage(img image.Image) image.Image {
size := img.Bounds()
pic := image.NewGray(size)
draw.Draw(pic, size, img, size.Min, draw.Src)
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 := getOSTUThreshold(zft)
for i := 0; i < len(pic.Pix); i++ {
if int(pic.Pix[i]) > fz {
pic.Pix[i] = 255
} else {
pic.Pix[i] = 0
}
}
return pic
}
//getOSTUThreshold OSTU大律法 计算阀值
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
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
}