Fix image facade to safely compile
This commit is contained in:
parent
d62de8524c
commit
a5204b865b
4 changed files with 212 additions and 46 deletions
92
Cargo.lock
generated
92
Cargo.lock
generated
|
@ -22,6 +22,15 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.8.0"
|
||||
|
@ -234,6 +243,21 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
||||
dependencies = [
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"time",
|
||||
"wasm-bindgen",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clang"
|
||||
version = "2.0.0"
|
||||
|
@ -283,6 +307,12 @@ dependencies = [
|
|||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.7"
|
||||
|
@ -527,7 +557,7 @@ checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -563,6 +593,29 @@ version = "0.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
|
@ -731,6 +784,16 @@ dependencies = [
|
|||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.15"
|
||||
|
@ -961,6 +1024,7 @@ name = "rust_ocr"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"chrono",
|
||||
"config",
|
||||
"derivative",
|
||||
"fern",
|
||||
|
@ -1136,6 +1200,17 @@ dependencies = [
|
|||
"syn 2.0.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
|
@ -1191,6 +1266,12 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
@ -1306,6 +1387,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
async-std = "1.12.0"
|
||||
chrono = "0.4.24"
|
||||
config = "0.13.3"
|
||||
derivative = "2.2.0"
|
||||
fern = "0.6.2"
|
||||
|
|
|
@ -1,47 +1,53 @@
|
|||
use std::sync::Arc;
|
||||
use std::{sync::Mutex, thread, collections::VecDeque};
|
||||
|
||||
use config::*;
|
||||
#[allow(unused_imports)]
|
||||
use opencv::imgcodecs::{IMWRITE_PNG_BILEVEL, IMREAD_UNCHANGED};
|
||||
use opencv::{videoio::{VideoCapture, VideoCaptureTrait, CAP_PROP_FOURCC,
|
||||
CAP_ANY, VideoWriter, CAP_PROP_FRAME_WIDTH,
|
||||
CAP_PROP_FRAME_HEIGHT},
|
||||
imgproc::{THRESH_BINARY, COLOR_BGR2GRAY,threshold,cvt_color},
|
||||
core::{bitwise_and,Mat},
|
||||
core::{bitwise_and,Rect_,Mat,MatTraitConst,no_array,Vector},
|
||||
highgui::{select_roi,imshow},
|
||||
imgcodecs::{imread,imwrite,imdecode}};
|
||||
#[allow(unused_imports)]
|
||||
use leptess::{leptonica::{pix_read,Pix},
|
||||
tesseract::TessApi};
|
||||
imgcodecs::{imwrite,imread}};
|
||||
use leptess::LepTess;
|
||||
|
||||
const FRAME_WIDTH:i32 = 800;
|
||||
const FRAME_HEIGHT:i32 = 600;
|
||||
const MJPG_FOURCC_CODE:i32 = VideoWriter::fourcc('m','j','p','g').unwrap();
|
||||
const CROP_X:&str = "crop x";
|
||||
const CROP_Y:&str = "crop y";
|
||||
const CROP_WIDTH:&str = "crop width";
|
||||
const CROP_HEIGHT:&str = "crop height";
|
||||
const THRESHOLD:&str = "threshold value";
|
||||
const COMPOSITE_FRAMES:u16 = 5;
|
||||
|
||||
pub struct Camera{
|
||||
settings: Config,
|
||||
camera: FrameGrabber,
|
||||
name: String,
|
||||
ocr: TessApi,
|
||||
ocr: LepTess,
|
||||
active: bool
|
||||
}
|
||||
|
||||
struct FrameGrabber{
|
||||
camera: VideoCapture,
|
||||
image_queue: Mutex<VecDeque<Mat>>,
|
||||
image_queue: Arc<Mutex<VecDeque<Mat>>>,
|
||||
}
|
||||
|
||||
impl FrameGrabber{
|
||||
fn new(camera:VideoCapture, composite_frames:i64) -> Self{
|
||||
let mut output = Self{
|
||||
camera,
|
||||
image_queue: Mutex::new(VecDeque::with_capacity(composite_frames as usize))
|
||||
fn new(mut camera:VideoCapture, composite_frames:u16) -> Self{
|
||||
let output = Self{
|
||||
image_queue: Arc::new(Mutex::new(VecDeque::with_capacity(composite_frames as usize)))
|
||||
};
|
||||
let image_queue = output.image_queue.clone();
|
||||
thread::spawn(move||{
|
||||
loop {
|
||||
let mut image = Mat::default();
|
||||
let result = output.camera.read(&mut image);
|
||||
let result = &camera.read(&mut image);
|
||||
match result{
|
||||
Ok(true) => {
|
||||
let mut image_queue = *output.image_queue.lock().unwrap();
|
||||
let mut converted_image = Mat::default();
|
||||
_ = cvt_color(&mut image, &mut converted_image, COLOR_BGR2GRAY, 0);
|
||||
let mut image_queue = image_queue.lock().unwrap();
|
||||
if image_queue.len() == image_queue.capacity(){
|
||||
image_queue.pop_back();
|
||||
}
|
||||
|
@ -54,60 +60,130 @@ impl FrameGrabber{
|
|||
return output;
|
||||
}
|
||||
|
||||
fn grab(&self, mut image:&Mat){
|
||||
let mut image_queue = *self.image_queue.lock().unwrap();
|
||||
image = &mut image_queue.pop_front().unwrap();
|
||||
fn grab(&self) -> Mat{
|
||||
let mut image_queue = self.image_queue.lock().unwrap();
|
||||
image_queue.pop_front().unwrap()
|
||||
}
|
||||
|
||||
fn burst(&self) -> Vec<Mat>{
|
||||
let mut image_queue = *self.image_queue.lock().unwrap();
|
||||
let image_queue = self.image_queue.lock().unwrap();
|
||||
return image_queue.clone().into();
|
||||
}
|
||||
|
||||
fn change_composite_frames(&self, composite_frames:u16){
|
||||
let mut image_queue = self.image_queue.lock().unwrap();
|
||||
image_queue.resize(composite_frames as usize, Default::default());
|
||||
}
|
||||
}
|
||||
|
||||
impl Camera{
|
||||
pub fn new(camera_name:String) -> Option<Self>{
|
||||
let defaults = Config::builder();
|
||||
defaults.set_default("crop x", 275);
|
||||
defaults.set_default("crop y", 200);
|
||||
defaults.set_default("crop width", 80);
|
||||
defaults.set_default("crop height", 50);
|
||||
defaults.set_default("threshold value", 50);
|
||||
defaults.set_default("composite frames", 5);
|
||||
defaults.set_default("active", true);
|
||||
let mut defaults = Config::builder();
|
||||
defaults = defaults.set_default(CROP_X, 275).unwrap();
|
||||
defaults = defaults.set_default(CROP_Y, 200).unwrap();
|
||||
defaults = defaults.set_default(CROP_WIDTH, 80).unwrap();
|
||||
defaults = defaults.set_default(CROP_HEIGHT, 50).unwrap();
|
||||
defaults = defaults.set_default(THRESHOLD, 50).unwrap();
|
||||
let default = defaults.build().unwrap();
|
||||
|
||||
let settings = Config::builder().add_source(default).build().unwrap();
|
||||
|
||||
let mut camera = VideoCapture::from_file(&camera_name, CAP_ANY).unwrap();
|
||||
camera.set(CAP_PROP_FOURCC, MJPG_FOURCC_CODE as f64);
|
||||
camera.set(CAP_PROP_FRAME_WIDTH, FRAME_WIDTH as f64);
|
||||
camera.set(CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT as f64);
|
||||
if let result = camera.open_file(&camera_name, CAP_ANY){
|
||||
match result {
|
||||
Ok(_) => {},
|
||||
Err(error) => return None
|
||||
}
|
||||
_ = camera.set(CAP_PROP_FOURCC, VideoWriter::fourcc('m','j','p','g').unwrap() as f64);
|
||||
_ = camera.set(CAP_PROP_FRAME_WIDTH, FRAME_WIDTH as f64);
|
||||
_ = camera.set(CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT as f64);
|
||||
match camera.open_file(&camera_name, CAP_ANY) {
|
||||
Ok(_) => {},
|
||||
Err(_) => return None
|
||||
};
|
||||
let frame_grabber = FrameGrabber::new(camera, settings.get_int("composite frames").unwrap_or(1));
|
||||
let frame_grabber = FrameGrabber::new(camera, COMPOSITE_FRAMES);
|
||||
|
||||
let name = camera_name.split('-').last().unwrap().to_string();
|
||||
|
||||
let ocr = TessApi::new(Some("tessdata"), "Pro6_temp_test").unwrap();
|
||||
let ocr = LepTess::new(Some("tessdata"), "Pro6_temp_test").unwrap();
|
||||
|
||||
Some(Self{
|
||||
settings,
|
||||
camera: frame_grabber,
|
||||
name,
|
||||
ocr,
|
||||
active: true,
|
||||
})
|
||||
}
|
||||
|
||||
fn take_picture(&mut self) -> Mat{
|
||||
let mut image = Mat::default();
|
||||
self.camera.grab(&mut image);
|
||||
let mut output = Mat::default();
|
||||
cvt_color(&mut image, &mut output, COLOR_BGR2GRAY, 0);
|
||||
return output;
|
||||
pub fn show_image(&self){
|
||||
_ = imshow("Test image", &imread(&self.complete_process(),IMREAD_UNCHANGED).unwrap());
|
||||
}
|
||||
|
||||
fn complete_process(&self) -> String{
|
||||
let images = self.camera.burst();
|
||||
let mut final_image = images[0].clone();
|
||||
for mut image in images{
|
||||
image = self.crop(image);
|
||||
image = self.threshold(image);
|
||||
_ = bitwise_and(&final_image.clone(), &image, &mut final_image, &no_array());
|
||||
}
|
||||
return self.save(final_image).unwrap_or("".to_string());
|
||||
}
|
||||
|
||||
fn crop(&self,image:Mat) -> Mat{
|
||||
let x = self.settings.get_int(&CROP_X).unwrap();
|
||||
let y = self.settings.get_int(&CROP_Y).unwrap();
|
||||
let width = self.settings.get_int(&CROP_WIDTH).unwrap();
|
||||
let height = self.settings.get_int(&CROP_HEIGHT).unwrap();
|
||||
let roi = Rect_::new(x as i32, y as i32, width as i32, height as i32);
|
||||
return image.apply_1(roi).unwrap();
|
||||
}
|
||||
|
||||
fn threshold(&self,image:Mat) -> Mat{
|
||||
let mut output = image.clone();
|
||||
let threshold_value = self.settings.get_int(&THRESHOLD).unwrap();
|
||||
_ = threshold(&image,&mut output, threshold_value as f64, 255 as f64 ,THRESH_BINARY);
|
||||
return Mat::default();
|
||||
}
|
||||
|
||||
fn save(&self,image:Mat) -> Result<String,opencv::Error>{
|
||||
let mut write_parameters:Vector<i32> = Vector::new();
|
||||
write_parameters.push(IMWRITE_PNG_BILEVEL);
|
||||
let mut filename:String = String::new();
|
||||
filename.push_str(&chrono::Local::now().to_rfc3339().to_string());
|
||||
filename.push_str(&self.name);
|
||||
match imwrite(&filename, &image, &write_parameters){
|
||||
Ok(_) => Ok(filename),
|
||||
Err(error) => Err(error)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_crop(&mut self) -> Result<(),opencv::Error>{
|
||||
match select_roi(&self.camera.grab(), false, false){
|
||||
Err(error) => { return Err(error); }
|
||||
Ok(rect) => {
|
||||
let mut new_settings = Config::builder().add_source(self.settings.clone());
|
||||
new_settings = new_settings.set_override(CROP_X, rect.x).unwrap();
|
||||
new_settings = new_settings.set_override(CROP_Y, rect.y).unwrap();
|
||||
new_settings = new_settings.set_override(CROP_WIDTH, rect.width).unwrap();
|
||||
new_settings = new_settings.set_override(CROP_HEIGHT, rect.height).unwrap();
|
||||
self.settings = new_settings.build().unwrap();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_threshold(&mut self, thresh:u16){
|
||||
let new_settings = Config::builder().add_source(self.settings.clone()).set_override(THRESHOLD, thresh);
|
||||
self.settings = new_settings.expect("Bad config settings!").build().unwrap();
|
||||
}
|
||||
|
||||
pub fn set_composite_frames(&self, composite_frames:u16){
|
||||
self.camera.change_composite_frames(composite_frames);
|
||||
}
|
||||
|
||||
pub fn deactivate(&mut self){ self.active = false; }
|
||||
pub fn activate(&mut self) { self.active = true; }
|
||||
pub fn is_active(&self) -> bool { self.active }
|
||||
|
||||
pub fn parse_image(&mut self, file_location:String) -> f64{
|
||||
_ = self.ocr.set_image(file_location);
|
||||
return str::parse(&self.ocr.get_utf8_text().unwrap()).unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
pub mod config_facade;
|
||||
pub mod gpio_facade;
|
||||
pub mod image_facade;
|
||||
pub mod output_facade;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue