use image::{GrayImage, ImageFormat}; use imageproc::template_matching::MatchTemplateMethod; use lazy_static::lazy_static; lazy_static! { static ref REFERENCES: [GrayImage; 10] = { let parse = |data: &[u8]| { let png = image::load_from_memory_with_format(data, ImageFormat::Png).unwrap(); image::imageops::grayscale(&png) }; [ parse(include_bytes!("../data/0.png")), parse(include_bytes!("../data/1.png")), parse(include_bytes!("../data/2.png")), parse(include_bytes!("../data/3.png")), parse(include_bytes!("../data/4.png")), parse(include_bytes!("../data/5.png")), parse(include_bytes!("../data/6.png")), parse(include_bytes!("../data/7.png")), parse(include_bytes!("../data/8.png")), parse(include_bytes!("../data/9.png")), ] }; } fn x_matches(image: &GrayImage, template: &GrayImage) -> Vec { let match_values = imageproc::template_matching::match_template( image, template, MatchTemplateMethod::CrossCorrelationNormalized, ); match_values .enumerate_pixels() .filter(|(_x, _y, pix)| pix.0[0] > 0.95) .map(|(x, _y, _pix)| x) .collect() } pub fn ocr(image: &GrayImage) -> Option { let mut digit_x_positions: Vec<(u8, u32)> = (0..10) .flat_map(|i| { x_matches(image, &REFERENCES[i as usize]) .into_iter() .map(move |x| (i, x)) }) .collect(); digit_x_positions.sort_by_key(|&(_i, x)| x); let digits: String = digit_x_positions .into_iter() .map(|(i, _x)| format!("{}", i)) .collect(); dbg!(&digits); digits.parse().ok() }