我正在使用 go-opencv 从我的内置网络摄像头获取帧。从相机获取图像所需的时间约为 50 毫秒。编码 PNG 的时间约为 300 毫秒。编码 JPEG 的速度快了 3 倍,但仍然非常慢。
为什么这个运行这么慢?
注意:我已经针对 NodeJS 编写了类似的代码,在同一台机器上执行,并且使用额外的图像处理达到 30fps 绝对没有问题。对我来说,这消除了等式中的硬件问题。
我的代码如下所示:
import (
"fmt"
"image/png"
"github.com/lazywei/go-opencv/opencv"
)
camera := opencv.NewCameraCapture(0)
if camera == nil {
panic("Unable to open camera.")
}
defer camera.Release()
for {
if camera.GrabFrame() {
img := camera.RetrieveFrame(1)
if img != nil {
frame := img.ToImage()
buffer := new(bytes.Buffer)
png.Encode(buffer, frame)
} else {
fmt.Println("Unable to capture frame")
}
}
}
Run Code Online (Sandbox Code Playgroud)
禁用压缩将我机器上的编码性能提高了一个数量级。如果您不想在标准库之外寻找 png 包,这可能是一个开始。
我还尝试了 BufferPool(Go 1.9 中的新功能),但与带有 nil BufferPool 的编码器相比,它并没有什么不同。也许我做错了。不幸的是,这些文档非常简洁。
package main
import (
"bytes"
"image"
"image/png"
"os"
"testing"
)
func BenchmarkPNG_Encode(b *testing.B) {
img, buf := loadImage(b)
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf.Reset()
png.Encode(buf, img)
}
}
func BenchmarkPNG_Encoder(b *testing.B) {
img, buf := loadImage(b)
enc := &png.Encoder{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf.Reset()
enc.Encode(buf, img)
}
}
func BenchmarkPNG_Encoder_NoCompression(b *testing.B) {
img, buf := loadImage(b)
enc := &png.Encoder{
CompressionLevel: png.NoCompression,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
buf.Reset()
enc.Encode(buf, img)
}
}
func loadImage(b *testing.B) (image.Image, *bytes.Buffer) {
// foo.png PNG 1920x1053 1920x1053+0+0 8-bit sRGB 251KB 0.000u 0:00.000
f, err := os.Open("foo.png")
if err != nil {
b.Fatal(err)
}
img, err := png.Decode(f)
if err != nil {
b.Fatal(err)
}
f.Close()
buf := &bytes.Buffer{}
// grow the buffer once
(&png.Encoder{CompressionLevel: png.NoCompression}).Encode(buf, img)
return img, buf
}
Run Code Online (Sandbox Code Playgroud)
同样,这是在我的机器上使用大约 1920x1080 像素的图像——随机截图;不知道这与照片会有多大不同。天啊。
$ go test -v -bench . -benchmem
goos: linux
goarch: amd64
BenchmarkPNG_Encode-8 10 119289121 ns/op 884964 B/op 38 allocs/op
BenchmarkPNG_Encoder-8 10 118001658 ns/op 884932 B/op 37 allocs/op
BenchmarkPNG_Encoder_NoCompression-8 100 13050664 ns/op 807156 B/op 212 allocs/op
Run Code Online (Sandbox Code Playgroud)
有趣的是,与压缩相比,没有压缩会导致更多的分配。