supper/src/ocr.rs

88 lines
2.4 KiB
Rust
Raw Normal View History

2022-05-22 18:03:47 +00:00
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
2022-05-21 18:12:10 +00:00
use anyhow::Result;
use image::RgbImage;
use serde::{Deserialize, Serialize};
2022-05-22 18:03:47 +00:00
use crate::{
config::{Config, LearnedConfig},
image_processing::{extract_region, filter_to_white, hash_image, Region},
};
2022-05-21 18:12:10 +00:00
#[derive(Serialize, Deserialize, Debug)]
pub struct OcrRegion {
pub confidence: f64,
pub value: String,
}
#[derive(Serialize, Deserialize, Debug)]
struct OcrResult {
regions: Vec<OcrRegion>,
error: Option<String>,
}
2022-05-22 18:03:47 +00:00
async fn run_ocr(image: &RgbImage, url: &str) -> Result<Option<String>> {
2022-05-21 18:12:10 +00:00
let client = reqwest::Client::new();
let response = client
2022-05-22 18:03:47 +00:00
.post(url)
.body(crate::image_processing::to_png_bytes(image))
2022-05-21 18:12:10 +00:00
.send()
.await?;
if !response.status().is_success() {
2022-05-22 18:03:47 +00:00
eprintln!("failed to run OCR query");
2022-05-21 18:12:10 +00:00
anyhow::bail!("failed to run OCR query")
}
let result: OcrResult = response.json().await?;
2022-05-22 18:03:47 +00:00
let result = if result.regions.is_empty() {
None
} else {
let mut buffer = String::new();
for r in &result.regions {
buffer += &r.value;
}
Some(buffer)
};
Ok(result)
2022-05-21 18:12:10 +00:00
}
2022-05-22 18:03:47 +00:00
#[tokio::main(flavor = "current_thread")]
pub async fn ocr_all_regions(
image: &RgbImage,
config: Arc<Config>,
learned: Arc<LearnedConfig>,
) -> HashMap<String, Option<String>> {
2022-05-21 18:12:10 +00:00
let results = Arc::new(Mutex::new(HashMap::new()));
let mut handles = Vec::new();
2022-05-22 18:03:47 +00:00
for region in &config.ocr_regions {
2022-05-21 18:12:10 +00:00
let filtered_image = extract_region(image, region);
let region = region.clone();
let results = results.clone();
2022-05-22 18:03:47 +00:00
let config = config.clone();
let learned = learned.clone();
2022-05-21 18:12:10 +00:00
handles.push(tokio::spawn(async move {
let mut image = filtered_image;
2022-05-22 17:19:13 +00:00
filter_to_white(&mut image);
2022-05-22 18:03:47 +00:00
let hash = hash_image(&image);
let value = if let Some(learned_value) = learned.learned_images.get(&hash) {
Some(learned_value.clone())
} else {
run_ocr(&image, &config.ocr_server_endpoint)
.await
.unwrap_or(None)
2022-05-21 18:12:10 +00:00
};
results.lock().unwrap().insert(region.name, value);
}));
}
for handle in handles {
handle.await.expect("failed to join task in OCR");
}
let results = results.lock().unwrap().clone();
results
2022-05-22 18:03:47 +00:00
}