Go语言如何识别图片的主要色值

最近有一个需求,根据图片的主要色值自动设置页面的背景色。我们的服务端是go语言写的,自然先评估一下是否能用go实现这个需求。

avatar_cover Alex Xiang
2021-07-01 248阅读

最近有一个需求,根据图片的主要色值自动设置页面的背景色。我们的服务端是go语言写的,自然先评估一下是否能用go实现这个需求。找了几个方案,其中github.com/cenkalti/dominantcolor的方案最为简单,也最合适。

先看看简单的例子

package main

import (
    "bytes"
    "fmt"
    "image"
    "image/jpeg"
    "io"
    "io/ioutil"
    "net/http"

    "github.com/cenkalti/dominantcolor"
)

func GetImageByUrl(url string) (img image.Image, err error) {
    res, err := http.Get(url)
    if err != nil {
        return
    }

    defer func(body io.ReadCloser) {
        _ = body.Close()
    }(res.Body)

    data, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return
    }

    reader := bytes.NewReader(data)
    img, err = jpeg.Decode(reader)

    return
}

func FindDomiantColor(url string) (c string, err error) {
    img, err := GetImageByUrl(url)
    if err != nil {
        return
    }

    return dominantcolor.Hex(dominantcolor.Find(img)), nil
}

func main() {
    fmt.Println(FindDomiantColor("https://n.sinaimg.cn/news/transform/310/w710h400/20220701/8cd8-e663ace484b6d8dcc548a18691e30c0a.jpg"))
}

这个例子打开一个网络图片,然后获取其主要的颜色,输出是#544F4C,可以看一下背景的效果图:

{{ image640(path="/wp-content/uploads/2022/07/image.png") }}

可以看出背景还是比较匹配的。不过对于某些有多个色块的图片,是拿不到单一的颜色的,例如下面这个例子:

{{ image640(path="/wp-content/uploads/2022/07/image-1.png") }}

当然,如果只能选一种颜色,并且是自动的,那确实没有太简单的办法。不过如果可以让用户干预,其实还是可以有办法的,因为dominantcolor是可以输出多个颜色的。我们来看一下官方的演示程序:

{{ image640(path="/wp-content/uploads/2022/07/image-2.png") }}

这个程序也是go写的,基于dominantcolor和fyne.io,有兴趣的可以试试,也很简单:

go install github.com/stuartmscott/dominantcolor
$GOPATH/dominantcolor

{{ image640(path="/wp-content/uploads/2022/07/image-3.png") }}

上面是运行的界面,可以选一张本地的图片,计算6个使用最多的颜色块。windows下也可以运行,只不过因为需要gl库,看上去依赖gcc编译,所以没有尝试。上图是在wsl下运行的,现在windows的wsl已经支持图形界面的程序运行,还是挺方便的,就是性能看上去一般般。

从代码库的文档看,这个库用的是K聚类算法计算RGBA颜色空间的聚类,源自Chromium的源码:

Filter blog posts by tag go
rust (4)   wagtail (4)   zola (4)   kaggle (3)   vscode (3)   deepseek (2)   gemma (2)   go (2)   winui (2)   wsl (2)