ssa

Форк
0
/
mp4.go 
370 строк · 9.5 Кб
1
package goroi
2

3
import (
4
	"fmt"
5
	"image"
6
	"image/color"
7
	"image/draw"
8
	"math"
9
	"os"
10
	"os/exec"
11
	"sort"
12

13
	"github.com/anthonynsimon/bild/adjust"
14
	"github.com/cheggaaa/pb"
15
	pigo "github.com/esimov/pigo/core"
16
)
17

18
type Frame struct {
19
	FileName string
20
	Dets     []pigo.Detection
21
}
22

23
func ExtractRGB(Path, FileName string) (R, G, B []float64, Err error) {
24

25
	MakeDir(Path + "in/")
26
	fmt.Println((Path + "in/"))
27
	fmt.Println((Path + FileName))
28
	c := exec.Command(
29
		// ffmpeg -an -y -threads 0 -i in.mp4 -vf "select=not(mod(n\,1))" -vsync vfr in/%4d.png
30
		"ffmpeg", "-an", "-y", "-threads", "0", "-i", Path+FileName, "-vf", `select=not(mod(n\,1))`, "-vsync", "vfr", Path+"in/%4d.png",
31
		//"ffmpeg", "-i", Path+FileName, "-r", "15", Path+"in/%4d.png",
32
	) // "P1LC1-edited2.mp4" "P1LC1-edited.avi" "face.mp4"
33
	c.Stderr = os.Stderr
34
	c.Run()
35
	entries, err := os.ReadDir(Path + "in/")
36
	if err != nil {
37
		return nil, nil, nil, fmt.Errorf("os.ReadDir: %v", err)
38
	}
39
	p, err := NewPigs("cascade/facefinder")
40
	if err != nil {
41
		return nil, nil, nil, fmt.Errorf("NewPigs: %v", err)
42
	}
43

44
	// Выделяем память под слайсы R G B
45
	R = make([]float64, len(entries))
46
	G = make([]float64, len(entries))
47
	B = make([]float64, len(entries))
48

49
	Bar := pb.StartNew(len(entries))
50
	Bar.Prefix(Path + "in/")
51
	for ientries := range entries {
52
		FilePathIn := Path + "in/" + entries[ientries].Name()
53

54
		r, g, b, ErrCoord := p.Coords2(FilePathIn)
55
		if ErrCoord != nil {
56
			fmt.Printf("p.Coords: %v for image [%d/%d] for file %v\n", ErrCoord, ientries, len(entries), entries[ientries].Name())
57
		}
58

59
		R[ientries] = r
60
		G[ientries] = g
61
		B[ientries] = b
62

63
		Bar.Increment()
64
		//break
65
	}
66
	Bar.Finish()
67

68
	return R, G, B, nil
69
}
70

71
func (p *Pigs) Coords(FilePathName string) (R float64, G float64, B float64, Err error) {
72
	Dets := p.getCoords(FilePathName)
73
	sort.Slice(Dets, func(i, j int) bool { // Сортировка по вероятности
74
		return Dets[i].Q > Dets[j].Q
75
	})
76

77
	var Ruint32, Guint32, Buint32 uint32
78
	var sizes uint32
79
	if len(Dets) > 0 {
80
		src, Err := getImageFromFilePath(FilePathName)
81
		if Err != nil {
82
			return 0.0, 0.0, 0.0, fmt.Errorf("getImageFromFilePath: %v", Err)
83
		}
84
		pix := Dets[0].Scale / 2
85
		yStart, yEnd := Dets[0].Row-pix, Dets[0].Row+pix
86
		xStart, xEnd := Dets[0].Col-pix, Dets[0].Col+pix
87

88
		for y := yStart; y < yEnd; y++ {
89
			for x := xStart; x < xEnd; x++ {
90
				rgb := src.At(x, y)
91
				r, g, b, _ := rgb.RGBA()
92
				_, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
93
				hsvH, _, _ := RGB2HSV(float64(r), float64(g), float64(b))
94
				if cb >= 98 && cb <= 142 &&
95
					cr >= 135 && cr <= 177 &&
96
					hsvH >= 0.01 && hsvH <= 0.1 {
97
					Ruint32 += (r >> 8)
98
					Guint32 += (g >> 8)
99
					Buint32 += (b >> 8)
100
				}
101
			}
102
		}
103
		sizes = uint32((yEnd - yStart) * (xEnd - xStart))
104
	}
105

106
	R = float64(Ruint32) / float64(sizes)
107
	G = float64(Guint32) / float64(sizes)
108
	B = float64(Buint32) / float64(sizes)
109
	return R, G, B, nil
110
}
111

112
func getImageFromFilePath(filePath string) (draw.Image, error) {
113

114
	// read file
115
	f, err := os.Open(filePath)
116
	if err != nil {
117
		return nil, err
118
	}
119
	defer f.Close()
120

121
	// convert as image.Image
122
	orig, _, err := image.Decode(f)
123

124
	// convert as usable image
125
	b := orig.Bounds()
126
	img := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
127
	draw.Draw(img, img.Bounds(), orig, b.Min, draw.Src)
128

129
	return img, err
130
}
131

132
// Рассчёт процентилей
133
func illumgray(img image.Image, percentiles int) (float64, float64, float64) {
134
	Rectangle := img.Bounds()
135
	width := Rectangle.Max.X - Rectangle.Min.X
136
	height := Rectangle.Max.Y - Rectangle.Min.Y
137
	// fmt.Printf("\n%+v, (%d;%d)\n", Rectangle, width, height)
138
	// R := make([]uint32, height*width)
139
	// G := make([]uint32, height*width)
140
	// B := make([]uint32, height*width)
141
	R := make([]uint32, 0, height*width+1)
142
	G := make([]uint32, 0, height*width+1)
143
	B := make([]uint32, 0, height*width+1)
144
	for y := 0; y < height; y++ {
145
		for x := 0; x < width; x++ {
146
			r, g, b, _ := img.At(x, y).RGBA()
147
			// R[y*height+width] = r
148
			// G[y*height+width] = g
149
			// B[y*height+width] = b
150
			R = append(G, r)
151
			G = append(G, g)
152
			B = append(G, b)
153
		}
154
	}
155
	R = sortAndREmDub(R)
156
	G = sortAndREmDub(G)
157
	B = sortAndREmDub(B)
158

159
	return float64(len(R) / (height * width)),
160
		float64(len(G) / (height * width)),
161
		float64(len(B) / (height * width))
162
}
163

164
func sortAndREmDub(arr []uint32) []uint32 {
165
	sort.Slice(arr, func(i, j int) bool {
166
		return arr[i] < arr[j]
167
	})
168
	j := 1
169
	for i := 1; i < len(arr); i++ {
170
		if arr[i] != arr[i-1] {
171
			arr[j] = arr[i]
172
			j++
173
		}
174
	}
175
	return arr[:j]
176
}
177

178
func (p *Pigs) Coords2(FilePathName string) (R float64, G float64, B float64, Err error) {
179

180
	Dets := p.getCoords(FilePathName)
181
	sort.Slice(Dets, func(i, j int) bool { // Сортировка по вероятности
182
		return Dets[i].Q > Dets[j].Q
183
	})
184

185
	if len(Dets) > 0 {
186
		f, ErrOpen := os.Open(FilePathName)
187
		if ErrOpen != nil {
188
			return 0.0, 0.0, 0.0, fmt.Errorf("os.Open: picture: %v", ErrOpen)
189
		}
190
		defer f.Close()
191

192
		img, _, ErrDecode := image.Decode(f)
193
		if ErrDecode != nil {
194
			return 0.0, 0.0, 0.0, fmt.Errorf("image.Decode: picture: %v", ErrDecode)
195
		}
196

197
		// fmt.Println(img.Bounds().Max.X - img.Bounds().Min.X)
198
		// fmt.Println(img.Bounds().Max.Y - img.Bounds().Min.Y)
199

200
		// fmt.Println(img.Bounds().Min.X, img.Bounds().Max.X)
201
		// fmt.Println(img.Bounds().Min.Y, img.Bounds().Max.Y)
202

203
		pix := Dets[0].Scale / 2
204
		// yStart, yEnd := Dets[0].Row-pix, Dets[0].Row+pix
205
		// xStart, xEnd := Dets[0].Col-pix, Dets[0].Col+pix
206

207
		// face_image := img.(interface {
208
		// 	SubImage(r image.Rectangle) image.Image
209
		// }).SubImage(image.Rect(Dets[0].Col-pix, Dets[0].Row-pix,
210
		// 	Dets[0].Col+pix, Dets[0].Row+pix))
211

212
		// // гамма и прочее
213
		// Rgray, Ggray, Bgray := illumgray(face_image, 10)
214
		// fmt.Println(Rgray, Ggray, Bgray)
215

216
		// Видео-коменсация
217
		img = adjust.Gamma(img, 2.2)
218

219
		var count int
220
		for y := Dets[0].Row - pix; y < Dets[0].Row+pix; y++ {
221
			// fmt.Println(y)
222
			for x := Dets[0].Col - pix; x < Dets[0].Col+pix; x++ {
223
				// for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ {
224
				// 	// fmt.Println(y)
225
				// 	for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ {
226
				rgb := img.At(x, y)
227
				r, g, b, _ := rgb.RGBA()
228

229
				// fmt.Println(uint8(r>>8), uint8(g>>8), uint8(b>>8))
230
				// _, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
231
				// _, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
232

233
				// _, cb, cr := ycbcr(r, g, b)
234

235
				// hsvH, _, _ := RGB2HSV(float64(r), float64(g), float64(b))
236
				// h, _, _ := RGBAToHSV(r, g, b, math.MaxInt32)
237

238
				// fmt.Println(r, g, b, "--", cb, cr, h, "=", cr>>8, cr>>16)
239

240
				// h, _, _ := RGBAToHSV(r, g, b, math.MaxUint32)
241

242
				_, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
243
				h, _, _ := RGB2HSV(float64(r), float64(g), float64(b))
244

245
				if cb >= (98) && cb <= (142) &&
246
					cr >= (135) && cr <= (177) &&
247
					h >= 0.01 && h <= 0.1 {
248
					R += float64(r >> 8)
249
					G += float64(g >> 8)
250
					B += float64(b >> 8)
251
					count++
252
				}
253
			}
254
		}
255

256
		// for y := yStart; y < yEnd; y++ {
257
		// 	for x := xStart; x < xEnd; x++ {
258
		// 		rgb := src.At(x, y)
259
		// 		r, g, b, _ := rgb.RGBA()
260
		// 		_, cb, cr := color.RGBToYCbCr(uint8(r>>8), uint8(g>>8), uint8(b>>8))
261
		// 		hsvH, _, _ := RGB2HSV(float64(r), float64(g), float64(b))
262
		// 		if cb >= 98 && cb <= 142 &&
263
		// 			cr >= 135 && cr <= 177 &&
264
		// 			hsvH >= 0.01 && hsvH <= 0.1 {
265
		// 			Ruint32 += (r >> 8)
266
		// 			Guint32 += (g >> 8)
267
		// 			Buint32 += (b >> 8)
268
		// 		}
269
		// 	}
270
		// }
271
		// output_file, _ := os.Create("tests/output.jpeg")
272
		// jpeg.Encode(output_file, face_image, nil)
273

274
		// sizes := float64((yEnd - yStart) * (xEnd - xStart))
275
		count64 := float64(count)
276
		return R / count64, G / count64, B / count64, nil
277
	}
278

279
	return 0.0, 0.0, 0.0, nil
280
}
281

282
func ycbcr(r, g, b uint32) (uint32, uint32, uint32) {
283
	y := (19595*r + 38470*g + 7471*b + 1<<15) >> 16
284

285
	// The bit twiddling below is equivalent to
286
	//
287
	// cb := (-11056*r - 21712*g + 32768*b + 257<<15) >> 16
288
	// if cb < 0 {
289
	//     cb = 0
290
	// } else if cb > 0xff {
291
	//     cb = ^int32(0)
292
	// }
293
	//
294
	// but uses fewer branches and is faster.
295
	// Note that the uint8 type conversion in the return
296
	// statement will convert ^int32(0) to 0xff.
297
	// The code below to compute cr uses a similar pattern.
298
	//
299
	// Note that -11056 - 21712 + 32768 equals 0.
300
	cb := 32768*b - 11056*r - 21712*g + 257<<15
301
	if cb&0xff000000 == 0 {
302
		cb >>= 16
303
	} else {
304
		cb = ^(cb >> 31)
305
	}
306

307
	// Note that 32768 - 27440 - 5328 equals 0.
308
	cr := 32768*r - 27440*g - 5328*b + 257<<15
309
	if cr&0xff000000 == 0 {
310
		cr >>= 16
311
	} else {
312
		cr = ^(cr >> 31)
313
	}
314
	return y, cb, cr
315
}
316

317
func RGBAToHSV(rValue, gValue, bValue, aValue uint32) (h, s, v float64) {
318

319
	// The RGBA color components are scaled by the Alpha value, as per:
320
	// https://golang.org/src/image/color/color.go?s=2394:2435#L21
321
	// Since we need RGB values in the [0-1] range, we need to divide
322
	// them by A, making sure it's not 0.
323
	if aValue == 0 {
324
		return h, s, v
325
	}
326

327
	a := float64(aValue)
328
	r := float64(rValue) / a
329
	g := float64(gValue) / a
330
	b := float64(bValue) / a
331

332
	maxValue := math.Max(r, math.Max(g, b))
333

334
	// They're all 0s
335
	if maxValue == 0 {
336
		return 0, 0, 0
337
	}
338

339
	minValue := math.Min(r, math.Min(g, b))
340
	delta := maxValue - minValue
341

342
	// Greyscale, only V can be != 0
343
	if delta == 0 {
344
		return 0, 0, math.Round(maxValue * 100)
345
	}
346

347
	//hue
348
	switch maxValue {
349
	case r:
350
		h = 60 * ((g - b) / delta)
351
	case g:
352
		h = 60 * (((b - r) / delta) + 2)
353
	case b:
354
		h = 60 * (((r - g) / delta) + 4)
355
	}
356

357
	if h < 0 {
358
		h += 360
359
	}
360

361
	h = math.Round(h)
362

363
	//saturation
364
	s = math.Round(100 * delta / maxValue)
365

366
	//value
367
	v = math.Round(maxValue * 100)
368
	return h, s, v
369

370
}
371

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.