images4

package module
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Apr 1, 2024 License: MIT Imports: 8 Imported by: 6

README

Find similar images with Go (LATEST VERSION)

Resized and near duplicate image comparison. No dependencies. For search in very large image sets use imagehash2 as a fast pre-filtering step.

Demo: similar pictures search and clustering (pure in-browser JS app served from).

Major (semantic) versions have their own repositories and are mutually incompatible:

Major version Repository Comment
4 images4 - this recommended; fast hash prefiltering (re)moved to imagehash2
3 images3 good, but less optimized
1, 2 images good, legacy code

Go doc - for full code documentation.

Example of comparing 2 images

package main

import (
	"fmt"
	"github.com/vitali-fedulov/images4"
)

func main() {

	// Opening and decoding images. Silently discarding errors.
	img1, _ := images4.Open("1.jpg")
	img2, _ := images4.Open("2.jpg")

	// Icons are compact hash-like image representations.
	icon1 := images4.Icon(img1)
	icon2 := images4.Icon(img2)

	// Comparison. Images are not used directly.
	// Use func CustomSimilar for different precision.
	if images4.Similar(icon1, icon2) {
		fmt.Println("Images are similar")
	} else {
		fmt.Println("Not similar")
	}

}

Main functions

  • Open decodes JPEG, PNG and GIF. But other types can be opened with third-party decoders, because the input to func 'Icon' is Golang image.Image. Example fork (not mine) expanded with support of WEBP images.

  • Icon produces an image hash-like struct called "icon", which will be used for comparision. Side note: name "hash" is reserved for true hash tables in related package for faster comparison imagehash2.

  • Similar gives a verdict whether 2 images are similar with well-tested default thresholds. Rotations and mirrors are not taken in account.

  • CustomSimilar is like 'Similar' above, but allows modifying the default thresholds by multiplication coefficients. When the coefficients equal 1.0, those two functions are equivalent. When the coefficients are less than 1.0, the comparison is more precise, down to 0.0 for identical images.

Advanced functions

  • Similar90270 is a superset of 'Similar' by additional comparison to images rotated ±90°. Such rotations are relatively common, even by accident when taking pictures on mobile phones.

  • CustomSimilar90270 is a custom func for rotations as above with 'CustomSimilar'.

  • EucMetric is an alternative to 'CustomSimilar' when you need to know metric values, for example to sort by similarity. Example (not mine) of custom similarity function.

  • PropMetric is as above for image proportions.

  • DefaultThresholds prints default thresholds used in func 'Similar' and 'Similar90270', as a starting point for selecting thresholds on 'EucMetric' and 'PropMetric'.

  • Rotate90 turns an icon 90° clockwise. This is useful for developing custom similarity function for rotated images with 'EucMetric' and 'PropMetric'. With the function you can also compare to images rotated 180° (by applying 'Rotate90' twice).

  • ResizeByNearest is an image resizing function useful for fast identification of identical images and development of custom distance metrics not involving any of the above comparison functions.

Algorithm

Images are resampled and resized to squares of fixed size called "icons". Euclidean distance between the icons is used to give the similarity verdict. Also image proportions are used to avoid matching images of distinct shape.

Detailed explanation, also as a PDF.

Speed and precision

To considerably accelerate comparison in large image collections (thousands and more), use hash-table pre-filtering with package imagehash2.

To considerably accelerate image decoding you can generate icons for embedded image thumbnails. Specifically, many JPEG images contain EXIF thumbnails. Packages to read thumbnails: 1 and 2. A note of caution: in rare cases there could be issues with thumbnails not matching image content. EXIF standard specification: 1 and 2.

An alternative method to increase precision instead of func 'CustomSimilar' is to generate icons for image sub-regions and compare those icons.

Documentation

Index

Constants

View Source
const (

	// Image resolution of the icon is very small
	// (11x11 pixels), therefore original image details
	// are lost in downsampling, except when source images
	// have very low resolution (e.g. favicons or simple
	// logos). This is useful from the privacy perspective
	// if you are to use generated icons in a large searchable
	// database.
	IconSize = 11 // Exported to be used in package imagehash.

)

Variables

This section is empty.

Functions

func CustomSimilar added in v1.3.0

func CustomSimilar(iconA, iconB IconT, coeff CustomCoefficients) bool

CustomSimilar is like Similar, except it allows changing default thresholds by multiplying them. The practically useful range of the coefficients is [0, 1.0), but can be equal or larger than 1 if necessary. All coefficients set to 0 correspond to identical images, for example an image file copy. All coefficients equal to 1 make func CustomSimilar equivalent to func Similar.

func CustomSimilar90270 added in v1.3.0

func CustomSimilar90270(iconA, iconB IconT, coeff CustomCoefficients) bool

Similar90270 works like Similar, but also considers rotations of ±90°. Those are rotations users might reasonably often do.

func DefaultThresholds added in v1.2.0

func DefaultThresholds()

Print default thresholds for func Similar.

func EucMetric

func EucMetric(iconA, iconB IconT) (m1, m2, m3 float64)

EucMetric returns Euclidean distances between 2 icons. These are 3 metrics corresponding to each color channel. Distances are squared, not to waste CPU on square root calculations. Note: color channels of icons are YCbCr (not RGB).

func Get added in v1.1.0

func Get(icon IconT, size int, p image.Point) (c1, c2, c3 float64)

Get reads pixel values in an icon at a point. c1, c2, c3 are color values for each channel (RGB for example). Exported to be used in package imagehash.

func Open

func Open(path string) (img image.Image, err error)

Open opens and decodes an image file for a given path.

func PropMetric

func PropMetric(iconA, iconB IconT) (m float64)

PropMetric gives image proportion similarity metric for image A and B. The smaller the metric the more similar are images by their x-y size.

func ResizeByNearest added in v1.3.0

func ResizeByNearest(
	src image.Image, dstSize image.Point) (
	dst image.RGBA, srcSize image.Point)

ResizeByNearest resizes an image to the destination size with the nearest neighbour method. It also returns the source image size.

func SaveToJPG

func SaveToJPG(img *image.RGBA, path string, quality int)

SaveToJPG encodes and saves image.RGBA to a file.

func SaveToPNG

func SaveToPNG(img *image.RGBA, path string)

SaveToPNG encodes and saves image.RGBA to a file.

func Set added in v1.1.0

func Set(icon IconT, size int, p image.Point, c1, c2, c3 float64)

Set places pixel values in an icon at a point. c1, c2, c3 are color values for each channel (RGB for example). Size is icon size. Exported to be used in package imagehash.

func Similar

func Similar(iconA, iconB IconT) bool

Similar returns similarity verdict based on Euclidean and proportion similarity.

func Similar90270 added in v1.2.0

func Similar90270(iconA, iconB IconT) bool

Similar90270 works like Similar, but also considers rotations of ±90°. Those are rotations users might reasonably often do.

Types

type CustomCoefficients added in v1.3.0

type CustomCoefficients struct {
	Y    float64 // Luma (grayscale information).
	Cb   float64 // Chrominance b (color information).
	Cr   float64 // Chrominance r (color information).
	Prop float64 // Proportion tolerance (how similar are image borders).
}

Threshold multiplication coefficients for func CustomSimilar. When all values equal 1.0 func CustomSimilar is equivalent to func Similar. By setting those values less than 1, similarity comparison becomes stricter (more precise). Values larger than 1 will generalize more and show more false positives. When uncertain, setting all coefficients to 1.0 is the safe starting point.

type IconT

type IconT struct {
	Pixels  []uint16    // Visual signature.
	ImgSize image.Point // Original image size.
}

Icon has square shape. Its pixels are uint16 values in 3 channels. uint16 is intentional to preserve color relationships from the full-size image. It is a 255- premultiplied color value in [0, 255] range.

func EmptyIcon

func EmptyIcon() (icon IconT)

EmptyIcon is an icon constructor in case you need an icon with nil values, for example for convenient error handling. Then you can use icon.Pixels == nil condition.

func Icon

func Icon(img image.Image) IconT

Icon generates a normalized image signature ("icon"). Generated icons can then be stored in a database and used for comparison. Icon is the recommended function, vs less robust func IconNN.

func IconNN

func IconNN(img image.Image) IconT

IconNN generates a NON-normalized image signature (icon). Icons made with IconNN can be used instead of icons made with func Icon, but mostly for experimental purposes, allowing better understand how the algorithm works, or performing less agressive customized normalization. Not for general use.

func Rotate90 added in v1.2.0

func Rotate90(icon IconT) IconT

Rotate rotates an icon by 90 degrees clockwise.

func (IconT) ToRGBA

func (icon IconT) ToRGBA(size int) *image.RGBA

ToRGBA transforms a sized icon to image.RGBA. This is an auxiliary function to visually evaluate an icon.

Jump to

Keyboard shortcuts

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