为了账号安全,请及时绑定邮箱和手机立即绑定

如何用go比较图像?

如何用go比较图像?

Go
红糖糍粑 2021-11-08 16:49:08
在 go图像包中,我没有看到任何可用于比较两个图像的方法?是否可以在类似于 ImageMagick 的 go 中进行图像比较?
查看完整描述

3 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

如果您尝试比较两个图像并且只需要将其归结为一个数字,则以下方法将起作用。这在(例如)遗传算法中很有用,您希望比较一组候选对象并选择与参考图像差异最小的一个:

  1. 访问每一个像素,将它分解为它的部分:R,G,B,A(在去:image.At(x,y).RGBA()

  2. 从参考图像中相应的像素值中减去 RGBA 值。

  3. 将差异平方,将它们相加。

  4. 取总和的平方根。

这个数字会让您大致了解图像的差异程度。

如果你知道这两个图像都是image.RGBA(或者你可以转换它们)的实例,那么你可以做更快的事情:直接从RGBA.Pix. 这就是我在这里所做的,它大约比img.At(x,y).RGBA()每个像素对快 10 倍:

func FastCompare(img1, img2 *image.RGBA) (int64, error) {

    if img1.Bounds() != img2.Bounds() {

        return 0, fmt.Errorf("image bounds not equal: %+v, %+v", img1.Bounds(), img2.Bounds())

    }


    accumError := int64(0)


    for i := 0; i < len(img1.Pix); i++ {

        accumError += int64(sqDiffUInt8(img1.Pix[i], img2.Pix[i]))

    }


    return int64(math.Sqrt(float64(accumError))), nil

}


func sqDiffUInt8(x, y uint8) uint64 {   

    d := uint64(x) - uint64(y)

    return d * d

}


查看完整回答
反对 回复 2021-11-08
?
HUX布斯

TA贡献1876条经验 获得超6个赞

试试https://github.com/vitali-fedulov/images。我写这个包是为了能够找到接近的重复项。有一个使用相同算法的实时网络演示,因此您可以了解该软件包如何满足您的需求。


查看完整回答
反对 回复 2021-11-08
?
千万里不及你

TA贡献1784条经验 获得超9个赞

对于这里的两个当前答案,图像需要具有相同的大小,否则比较失败。这里的第三个答案使用Vitali-fedulov/images,它没有任何方法来获取两个图像之间的差异,只有一个Similar返回bool确定两个图像是否相似的函数。此外,如果图像大小不同,Rosetta Code的答案也会失败。


所以如果我要实现我自己的解决方案,首先我需要缩小更大的图像。为此,我找到了x/image/draw和nfnt/resize,但我想也许我可以找到一些东西,用一块石头杀死两只鸟。为此,我确实找到了一些可以根据需要缩放图像的软件包,对每个图像进行散列,并获得散列的差异。这是corona10/goimagehash:


package main


import (

   "github.com/corona10/goimagehash"

   "image/jpeg"

   "os"

)


func hash(name string) (*goimagehash.ImageHash, error) {

   f, err := os.Open(name)

   if err != nil {

      return nil, err

   }

   defer f.Close()

   i, err := jpeg.Decode(f)

   if err != nil {

      return nil, err

   }

   return goimagehash.AverageHash(i)

}

例子:


package main


func main() {

   a, err := hash("mb.jpg")

   if err != nil {

      panic(err)

   }

   b, err := hash("hqdefault.jpg")

   if err != nil {

      panic(err)

   }

   d, err := a.Distance(b)

   if err != nil {

      panic(err)

   }

   println(d)

}


查看完整回答
反对 回复 2021-11-08
  • 3 回答
  • 0 关注
  • 257 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信