#find #position #processing #match #graphics #subimage

find-subimage

A rust crate to find a subimage within a larger image

13 releases

0.1.12 Dec 30, 2021
0.1.11 Dec 30, 2021

#418 in Images

37 downloads per month

MIT OR Apache-2…

33KB
514 lines

Find Subimage

github crates.io docs.rs build status

This crate provides basic functionality to find likely positions of a subimage within a larger image by calculating an image distance. It has a naive scalar implementation in rust, and a simd implementation that selects the best implementation based on cpu features at runtime in rust using the simdeez crate. It also provides an implementation which uses OpenCV's (A C++ library) matchTemplate function using the opencv-rust crate through an optional off-by-default feature. It can also optionally convert images to grayscale before applying the algorithms.

Here's a simple example showing how to use the API:

use find_subimage::{Image, SubImageFinderState};
// Make a dummy 128x128 black image with a red dot at (50, 0)
let (w, h) = (128, 128);
let mut rgb_image = vec![0u8; w * h * 3];
rgb_image[50 * 3] = 250;
// Make a dummy 32x32 black image
// with a red dot at (0, 0)
let (sub_w, sub_h) = (32, 32);
let mut rgb_subimage = vec![0u8; sub_w * sub_h * 3];
rgb_subimage[0] = 250;

let mut finder = SubImageFinderState::new();
// These are (x, y, distance) where x and y are the position within the larger image
// and distance is the distance value, where a smaller distance means a more precise match
let positions: &[(usize, usize, f32)] =
    finder.find_subimage_positions((&rgb_image, w, h), (&rgb_subimage, sub_w, sub_h), 3);
let max: Option<&(usize, usize, f32)> = positions
    .iter()
    .min_by(|(_, _, dist), (_, _, dist2)| dist.partial_cmp(dist2).unwrap());
println!("The subimage was found at position {:?}", &max);
assert_eq!(Some((50, 0)), max.map(|max| (max.0, max.1)));
// find_subimage_positions actually returns the results sorted by distance already,
// so we can skip finding the minimum
assert_eq!(Some((50, 0)), positions.get(0).map(|max| (max.0, max.1)));

Additional documentation can be found in the generated rustdoc docs hosted on docs.rs.

Here's an example of what can be done using this crate:

Our search image:

Ferris

Our subimage:

A crop of ferris' eyes

The best match:

Ferris again but with a red rectangle over their eyes

Licensing

The code in this repository is available under any of the following licenses, at your choice: MIT OR Apache-2.0 OR BSL-1.0 OR MPL-2.0 OR Zlib OR Unlicense

This crate optionally depends on opencv. You can find it's license here (3-clause BSD or Apache 2 depending on the version). The rust bindings are licensed as MIT.

It also optionally depends on simdeez which is licensed as MIT.

Running tests

I recommend running the tests in release mode.

Dependencies

~0.5–1MB
~16K SLoC