亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

img.At() 或 rgba.Pix() 是否更快/更好地從 Golang image.Image

img.At() 或 rgba.Pix() 是否更快/更好地從 Golang image.Image

Go
侃侃無極 2022-10-24 15:22:31
閱讀Get a pixel array from from golang image.Image的答案,我看到有兩種像素 RGBA 檢索方法,分別是 viaimg.At()和rgba.Pix()。哪個更好用?應該始終使用一個,還是在某些情況下應該使用一個而不是另一個,反之亦然?
查看完整描述

1 回答

?
慕標5832272

TA貢獻1966條經驗 獲得超4個贊

如果您的程序將在需要大多數(如果不是全部)像素數據的情況下進行計算,則rgba.Pix()性能明顯優于img.At(). 如果您只需要圖像中單個或幾個像素的像素數據,請使用img.At()(這種情況下計算rgba.Pix()先決條件的開銷太大)。

以下是各種測試負載的結果,每個負載的持續時間平均超過 10 個樣本。

方法1x11000x6673840x21601000x667 + 計算1000x667 僅 5x5 訪問
img.At()195ns30.211071ms294.885396ms853.345043ms42.431微秒
rgba.Pix()719ns7.786029ms77.700552ms836.480063ms6.791461毫秒

我們可以看到微小的 1x1 圖像和我們將 for 循環限制為上限 5 的圖像如何使用img.At()結果更快的執行時間。但是,對于獲取每個像素的用例,rgba.Pix()會產生更好的性能。img.At()我們對每個像素進行的計算越多,這種性能改進就越不明顯,因為總時間增加,與之間的差異rgba.Pix()變得不那么明顯,如上表中的“ 1000x667 + 計算”所示。

這是使用的測試代碼:

func main() {

    resp, err := http.Get("IMAGE URL GOES HERE")

    if err != nil {

        panic(err)

    }

    defer resp.Body.Close()


    img, _, err := image.Decode(resp.Body)

    if err != nil {

        panic(err)

    }


    var start time.Time

    var duration time.Duration

    samples := 10

    var sum time.Duration


    fmt.Println("Samples: ", samples)

    sum = time.Duration(0)

    for i := 0; i < samples; i++ {

        start = time.Now()

        usingAt(img)

        duration = time.Since(start)

        sum += duration

    }

    fmt.Println("*** At avg: ", sum/time.Duration(samples))


    sum = time.Duration(0)

    for i := 0; i < samples; i++ {

        start = time.Now()

        usingPix(img)

        duration = time.Since(start)

        sum += duration

    }

    fmt.Println("*** Pix avg: ", sum/time.Duration(samples))

}


func usingAt(img image.Image) {

    bounds := img.Bounds()

    width, height := bounds.Max.X, bounds.Max.Y


    for y := 0; y < height; y++ {

        for x := 0; x < width; x++ {

            r, g, b, _ := img.At(x, y).RGBA()

            _ = uint8(r >> 8)

            _ = uint8(g >> 8)

            _ = uint8(b >> 8)

        }

    }

}


func usingPix(img image.Image, targetColor colorful.Color) {

    bounds := img.Bounds()

    width, height := bounds.Max.X, bounds.Max.Y


    rgba := image.NewRGBA(bounds)

    draw.Draw(rgba, bounds, img, bounds.Min, draw.Src)

    for y := 0; y < height; y++ {

        for x := 0; x < width; x++ {

            index := (y*width + x) * 4

            pix := rgba.Pix[index : index+4]

            _ = pix[0]

            _ = pix[1]

            _ = pix[2]

        }

    }

}

1000x667 僅 5x5 訪問height用 5和5替換了widthfor 循環中的 and,限制了訪問的像素數。


1000x667 + 計算實際上是通過將每個像素與目標顏色的顏色距離與go-colorful的 DE2000 計算進行比較來使用 RGB 值。


查看完整回答
反對 回復 2022-10-24
  • 1 回答
  • 0 關注
  • 111 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號