阅读Get a Pixel array from from golang image.Image 的答案,我发现有两种像素 RGBA 检索方法,viaimg.At()和rgba.Pix()。
使用哪个更好?是否应该始终使用其中一种,或者是否存在应使用其中一种而不是另一种的情况,反之亦然?
如果您的程序将在需要大多数(如果不是全部)像素数据的情况下进行计算,那么其rgba.Pix()性能将显着优于img.At(). 如果您只需要图像中单个或几个像素的像素数据,请使用img.At()(在这种情况下计算先决条件的开销rgba.Pix()太高)。
以下是各种测试负载的结果,每个负载的持续时间是 10 个样本的平均值。
\n| 方法 | 1x1 | 1000x667 | 3840x2160 | 1000x667 + 计算 | 1000x667 仅 5x5 访问 |
|---|---|---|---|---|---|
img.At() | 195纳秒 | 30.211071毫秒 | 294.885396毫秒 | 853.345043毫秒 | 42.431 \xce\xbcs |
rgba.Pix() | 719纳秒 | 7.786029毫秒 | 77.700552毫秒 | 836.480063毫秒 | 6.791461毫秒 |
我们可以看到如何对于微小的 1x1 图像以及我们将 for 循环限制为上限 5 的图像,从而使用img.At()更快的执行时间。但是,对于获取每个像素的用例,rgba.Pix()会带来更好的性能。我们对每个像素进行的计算越多,这种性能改进就越不明显,因为总时间增加,并且img.At()和之间的差异rgba.Pix()变得不那么明显,如“ 1000x667 + 计算”中所示不那么明显,如上表中的
这是使用的测试代码:
\nfunc main() {\n resp, err := http.Get("IMAGE URL GOES HERE")\n if err != nil {\n panic(err)\n }\n defer resp.Body.Close()\n\n img, _, err := image.Decode(resp.Body)\n if err != nil {\n panic(err)\n }\n\n var start time.Time\n var duration time.Duration\n samples := 10\n var sum time.Duration\n\n fmt.Println("Samples: ", samples)\n sum = time.Duration(0)\n for i := 0; i < samples; i++ {\n start = time.Now()\n usingAt(img)\n duration = time.Since(start)\n sum += duration\n }\n fmt.Println("*** At avg: ", sum/time.Duration(samples))\n\n sum = time.Duration(0)\n for i := 0; i < samples; i++ {\n start = time.Now()\n usingPix(img)\n duration = time.Since(start)\n sum += duration\n }\n fmt.Println("*** Pix avg: ", sum/time.Duration(samples))\n}\n\nfunc usingAt(img image.Image) {\n bounds := img.Bounds()\n width, height := bounds.Max.X, bounds.Max.Y\n\n for y := 0; y < height; y++ {\n for x := 0; x < width; x++ {\n r, g, b, _ := img.At(x, y).RGBA()\n _ = uint8(r >> 8)\n _ = uint8(g >> 8)\n _ = uint8(b >> 8)\n }\n }\n}\n\nfunc usingPix(img image.Image, targetColor colorful.Color) {\n bounds := img.Bounds()\n width, height := bounds.Max.X, bounds.Max.Y\n\n rgba := image.NewRGBA(bounds)\n draw.Draw(rgba, bounds, img, bounds.Min, draw.Src)\n for y := 0; y < height; y++ {\n for x := 0; x < width; x++ {\n index := (y*width + x) * 4\n pix := rgba.Pix[index : index+4]\n _ = pix[0]\n _ = pix[1]\n _ = pix[2]\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n1000x667仅访问5x5,height将for循环中的and替换width为5和5,限制了访问的像素数量。
1000x667+计算实际上使用了RGB值,通过将每个像素与目标颜色的颜色距离与go-colorful的DE2000计算进行比较。
\n