Yet another tool for image comparison.
Verb
比較
to compare; to contras
Hikaku was created for my projects, focused on generating images. I really want to compare generated images or screenshots quickly and reliably.
I'll mention examples below:
Repository | Purpose |
---|---|
golden-image | Image-based snapshot testing |
tbd | |
tbd |
To install hikaku
, simply use go get
:
$> go get github.com/opa-oz/hikaku
package main
import (
"github.com/opa-oz/hikaku"
"image"
)
func compareMyImages(first, second image.Image) {
// compare width and height of images
isBoundsEqual := hikaku.CompareByParams(first, second)
// build histogram using 16 buckets
compParams := hikaku.ComparisonParameters{BinsCount: 16, Threshold: 0.2}
isImagesEqual, diff := hikaku.CompareByHistograms(first, second, compParams)
// mix of previous two methods
// 1. Checks width and height
// 2. Compare by histograms
isImagesEqual, diff := hikaku.Compare(first, second, compParams)
}
Description
Idea is simple:
- Get histogram for Red, Green and Blue channels
- Normalize histograms
- Calculate Hellinger distance
- Summarize and make decision based on highlighted parts
Imagine you need to find a difference between two images:
Just run the code:
package main
import (
"github.com/opa-oz/hikaku"
"image"
)
func getDifference(first, second image.Image) *image.Image {
diffMask := hikaku.FindDiffMask(first, second, hikaku.ContextParameters{})
straightForwardDiff := hikaku.ApplyDiff(second, diffMask, 128)
return straightForwardDiff
}
Voila! Here is the difference, conveniently highlighted in red!
Sometimes images with highlighted diff can be noisy. Let's fix it a little bit, combining pixels into bigger groups:
func getDifference(first, second image.Image) *image.Image {
diffShapes := hikaku.FindDiffShapesMask(first, second, hikaku.ContextParameters{})
shapesForwardDiff := hikaku.ApplyDiff(second, diffShapes, 128)
return straightForwardDiff
}
One square to rule them all!
If you need to compare huge amount of images, you may want to pre-calculate histograms.
package main
import (
"github.com/opa-oz/hikaku"
"image"
)
func main(original, slightlyChanged, completelyDifferent image.Image) {
compParams := hikaku.ComparisonParameters{BinsCount: 16}
originalHist := hikaku.PrepareHistogram(original, compParams)
slightlyChangedHist := hikaku.PrepareHistogram(slightlyChanged, compParams)
completelyDifferentHist := hikaku.PrepareHistogram(completelyDifferent, compParams)
// 1st vs 2nd
isImagesEqual, diff := hikaku.CompareHistogramsOnly(originalHist, slightlyChangedHist, compParams)
// 1st vs 3rd
isImagesEqual, diff = hikaku.CompareHistogramsOnly(originalHist, completelyDifferentHist, compParams)
// 2nd vs 3rd
isImagesEqual, diff = hikaku.CompareHistogramsOnly(slightlyChangedHist, completelyDifferentHist, compParams)
var unexpectedFourth image.Image
// pass first image's histogram
compParams.NormalizedGoldHist = originalHist
// Yep, you still need to pass `original` image, but it will use pre-calculated histogram for this
// while still calculate histogram for 4th image on demand
isImagesEqual, diff = hikaku.CompareByHistograms(original, unexpectedFourth, compParams)
}
// Types
type Histogram = [][3]int
type NormalizedHistogram = [][3]float64
// Structs
type ComparisonParameters struct{ ... }
type ContextParameters struct{ ... }
type DiffPoint struct{ ... }
type Mask struct{ ... }
type Rect struct{ ... }
// Comparison
func Compare(golden, copper image.Image, params ComparisonParameters) (bool, float64)
func CompareByHistograms(golden, copper image.Image, params ComparisonParameters) (bool, float64)
func CompareHistogramsOnly(params ComparisonParameters) (bool, float64)
func CompareByParams(golden, copper image.Image) bool
// Overlay generation
func FindDiffMask(golden, copper image.Image, params ContextParameters) *image.RGBA
func FindDiffShapesMask(golden, copper image.Image, params ContextParameters) *image.RGBA
func ApplyDiff(golden, diff image.Image, transparency uint8) *image.RGBA
// Utils for optimization
func GetDiffShapes(golden, copper image.Image, params ContextParameters) map[int]Rect
func GetDiffPairs(golden, copper image.Image) []DiffPoint
func GetDiffPairsGrayscale(golden, copper image.Image) []DiffPoint
func PrepareHistogram(image image.Image, params ComparisonParameters) (normalizedHistogram NormalizedHistogram)