hikaku

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 14, 2022 License: MIT Imports: 8 Imported by: 1

README

Hikaku

Yet another tool for image comparison.

Original Changed

Changed
Changed[*]

比較 [ひかく]

en: hikaku

Verb
比較

to compare; to contras

Motivation

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 Example
tbd
tbd
tbd

Usage

Compare two images
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)
}
CompareByHistograms

Description
Idea is simple:

  1. Get histogram for Red, Green and Blue channels
  2. Normalize histograms
  3. Calculate Hellinger distance
  4. Summarize and make decision based on highlighted parts
Difference highlighting
Using mask

Imagine you need to find a difference between two images:

1.Original 2.Changed

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!

Changed

Using shapes

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
}

Changed

One square to rule them all!

More examples

Optimization

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)
}
Generated docs
// 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)

Cheers 🥂

[*] Original Gophers' images repo

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplyDiff

func ApplyDiff(golden, diff image.Image, transparency uint8) *image.RGBA

ApplyDiff applies diff as a mask with transparency It returns image with highlighted diff

func Compare

func Compare(golden, copper image.Image, params ComparisonParameters) (bool, float64)

Compare compares using both - CompareByHistograms and CompareByParams methods

func CompareByHistograms

func CompareByHistograms(golden, copper image.Image, params ComparisonParameters) (bool, float64)

CompareByHistograms compares two images by 3 histograms - Red, Green, Blue channels of pixels It returns the boolean result and the float64 difference between two images

func CompareByParams

func CompareByParams(golden, copper image.Image) bool

CompareByParams compares width and height of both images

func CompareHistogramsOnly

func CompareHistogramsOnly(params ComparisonParameters) (bool, float64)

CompareHistogramsOnly is kind of copy of CompareByHistograms, which uses only pre-calculated histograms, instead of images

func FindDiffMask

func FindDiffMask(golden, copper image.Image, params ContextParameters) *image.RGBA

FindDiffMask finds pixel-perfect difference between two images It returns mask of different pixels

func FindDiffShapesMask

func FindDiffShapesMask(golden, copper image.Image, params ContextParameters) *image.RGBA

FindDiffShapesMask finds shapes (rectangles) inside diff It returns mask of highlighted rectangles

func GetDiffShapes

func GetDiffShapes(golden, copper image.Image, params ContextParameters) map[int]Rect

GetDiffShapes finds shapes (rectangles) inside diff to avoid "too noisy" diff as a result

Types

type ComparisonParameters

type ComparisonParameters struct {
	Threshold                                float64
	BinsCount                                int
	NormalizedGoldHist, NormalizedCopperHist NormalizedHistogram
}

type ContextParameters

type ContextParameters struct {
	DiffPairs  []DiffPoint
	DiffShapes map[int]Rect
}

type DiffPoint

type DiffPoint struct {
	X, Y int
}

func GetDiffPairs

func GetDiffPairs(golden, copper image.Image) []DiffPoint

GetDiffPairs gets pairs of pixels, that are different in the both images It returns slice of pairs (x,y), representing pixel's coordinates Works with both Gray and RGBA images

func GetDiffPairsGrayscale

func GetDiffPairsGrayscale(golden, copper image.Image) []DiffPoint

GetDiffPairsGrayscale converts images to gray and gets pairs of pixels, that are different in the both images It returns slice of pairs (x,y), representing pixel's coordinates

type Histogram

type Histogram = [][3]int

type Mask

type Mask struct {
	// contains filtered or unexported fields
}

func (Mask) Draw

func (c Mask) Draw(targetImage image.Image, img image.Image, transparency uint8) *image.RGBA

Draw draws transparent image overlaying target image

type NormalizedHistogram

type NormalizedHistogram = [][3]float64

func PrepareHistogram

func PrepareHistogram(image image.Image, params ComparisonParameters) (normalizedHistogram NormalizedHistogram)

PrepareHistogram prepares histograms for 3 channels (r,g,b) and normalizes them It returns normalized histogram for 3 different channels

type Rect

type Rect struct {
	MinX, MinY, MaxX, MaxY int
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL