使用Go进行PNG编码很慢

时间:2017-09-26 23:19:20

标签: opencv go

我使用go-opencv从我内置的摄像头中获取帧。从相机获取图像所需的时间约为50毫秒。编码PNG的时间约为300毫秒。编码JPEG的速度提高了3倍,但速度仍然非常慢。

为什么这么慢?

注意的: 我已经针对NodeJS编写了类似的代码,在同一台机器上执行,并且完全没有问题达到30fps w /额外的图像处理。对我来说,这可以从等式中消除硬件问题。

我的代码如下所示:

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

}

2 个答案:

答案 0 :(得分:4)

禁用压缩可在我的计算机上将编码性能提高一个数量级。如果您不想在标准库之外查找png包,那么这可能是一个开始。

我也尝试了the 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
}

同样,这是在我的机器上,大约有1920x1080像素的图像 - 随机截图;不知道这与照片有多大差别。 YMMV。

$ 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

有趣的是,没有压缩会导致分配比压缩更多。

答案 1 :(得分:0)

  

为什么这么慢?

测量! Go有很好的分析工具,例如进入go test

最有可能的是纯粹的PNG编码器,&#34;未经优化的&#34;走。如果这对您来说不够快,您可能需要考虑提供更快的PNG编码器。