在go image包中,我没有看到任何可用于比较两张图片的方法?是否可以像ImageMagick一样进行图像比较?
答案 0 :(得分:5)
如果您正在尝试比较两个图像,只需将其煮沸为一个数字,以下内容将起作用。这在(例如)遗传算法中非常有用,在遗传算法中,您希望比较一组候选者并选择与参考图像差异最小的候选者:
image.At(x,y).RGBA()
)这个数字可以让您大致了解图像的差异。
如果您知道这两个图像都是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
}
答案 1 :(得分:2)
尝试https://github.com/vitali-fedulov/images。我写 此程序包可以找到几乎重复的内容。有一个具有相同算法的实时网络演示,因此您可以了解该软件包如何满足您的需求。
答案 2 :(得分:1)
受到乔治回答的启发。 下面的功能并不是很快,但是它可以让您直观地评估图像的差异。
func ImgCompare(img1, img2 image.Image) (int64, image.Image, error) {
bounds1 := img1.Bounds()
bounds2 := img2.Bounds()
if bounds1 != bounds2 {
return math.MaxInt64, nil, fmt.Errorf("image bounds not equal: %+v, %+v", img1.Bounds(), img2.Bounds())
}
accumError := int64(0)
resultImg := image.NewRGBA(image.Rect(
bounds1.Min.X,
bounds1.Min.Y,
bounds1.Max.X,
bounds1.Max.Y,
))
draw.Draw(resultImg, resultImg.Bounds(), img1, image.Point{0, 0}, draw.Src)
for x := bounds1.Min.X; x < bounds1.Max.X; x++ {
for y := bounds1.Min.Y; y < bounds1.Max.Y; y++ {
r1, g1, b1, a1 := img1.At(x, y).RGBA()
r2, g2, b2, a2 := img2.At(x, y).RGBA()
diff := int64(sqDiffUInt32(r1, r2))
diff += int64(sqDiffUInt32(g1, g2))
diff += int64(sqDiffUInt32(b1, b2))
diff += int64(sqDiffUInt32(a1, a2))
if diff > 0 {
accumError += diff
resultImg.Set(
bounds1.Min.X+x,
bounds1.Min.Y+y,
color.RGBA{R: 255, A: 255})
}
}
}
return int64(math.Sqrt(float64(accumError))), resultImg, nil
}
func sqDiffUInt32(x, y uint32) uint64 {
d := uint64(x) - uint64(y)
return d * d
}
答案 3 :(得分:1)
这里有两个当前的答案,图像需要大小相同,否则比较失败。这里的第三个答案使用 vitali-fedulov/images,它没有任何方法来获取
两个图像之间的差异,只有 Similar
函数返回 bool
确定两个图像是否相似。此外,如果图像大小不同,answer at 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)
}