cleaning, rename, add loops
This commit is contained in:
+71
-27
@@ -1,29 +1,68 @@
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use anyhow::Context;
|
||||
|
||||
use chrono::{NaiveDateTime, Utc};
|
||||
use image::{GenericImageView, Pixel};
|
||||
use log::{debug, error, info};
|
||||
|
||||
/// Folder the camera images are uploaded to
|
||||
const FOLDER_WITH_NEW_IMAGES: &str = "/dev/shm/camera";
|
||||
|
||||
/// File created in the uploads directory when the upload finishes.
|
||||
const COMMIT_FILENAME : &str = "commit";
|
||||
|
||||
/// Folder where the cropped bird pics are saved
|
||||
const FOLDER_WITH_BIRD_IMAGES: &str = "/backup/krmitko";
|
||||
|
||||
/// Image cropping config: left top X
|
||||
const CROP_X : u32 = 1872;
|
||||
|
||||
/// Image cropping config: left top Y
|
||||
const CROP_Y : u32 = 1329;
|
||||
|
||||
/// Image cropping config: crop width
|
||||
const CROP_W : u32 = 1000;
|
||||
|
||||
/// Image cropping config: crop height
|
||||
const CROP_H : u32 = 750;
|
||||
|
||||
/// Thumbnail width, used for bird detection (together with height creates the kernel size)
|
||||
/// This is a compromise between sensitivity and susceptibility to false positives.
|
||||
const THUMB_W: usize = 12;
|
||||
|
||||
/// Thumbnail height
|
||||
const THUMB_H: usize = 8;
|
||||
|
||||
/// Threshold for bird detection.
|
||||
/// Bird is detected if the sum of deviations from a median value in a picture exceeds this threshold.
|
||||
const THRESHOLD_DEVIATION: u32 = 500;
|
||||
|
||||
fn main() {
|
||||
open_and_reduce_img();
|
||||
env_logger::init();
|
||||
|
||||
let commit_file = PathBuf::from(FOLDER_WITH_NEW_IMAGES).join(COMMIT_FILENAME);
|
||||
|
||||
loop {
|
||||
if !commit_file.exists() {
|
||||
debug!("No commit file, wait.");
|
||||
std::thread::sleep(Duration::from_secs(10));
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Err(e) = process_camera_pics() {
|
||||
error!("Error processing pics: {e}");
|
||||
}
|
||||
|
||||
let _ = std::fs::remove_dir_all(FOLDER_WITH_NEW_IMAGES);
|
||||
}
|
||||
}
|
||||
|
||||
fn process_camera_pics() -> anyhow::Result<()> {
|
||||
info!("Processing camera pics");
|
||||
|
||||
const FOLDER_WITH_IMAGES : &str = "../2/";
|
||||
|
||||
const FOLDER_OUTPUT : &str = "birds";
|
||||
|
||||
const THUMB_W : usize = 12;
|
||||
const THUMB_H : usize = 8;
|
||||
|
||||
const THRESHOLD_DEVIATION : u32 = 500;
|
||||
|
||||
fn open_and_reduce_img() {
|
||||
env_logger::init_from_env("LOGGING");
|
||||
|
||||
info!("Bird finder starts");
|
||||
|
||||
let paths = std::fs::read_dir(FOLDER_WITH_IMAGES).unwrap();
|
||||
let paths = std::fs::read_dir(FOLDER_WITH_NEW_IMAGES).context("Read folder with images")?;
|
||||
|
||||
let mut crops = vec![];
|
||||
let mut thumbs = vec![];
|
||||
@@ -33,16 +72,20 @@ fn open_and_reduce_img() {
|
||||
for dir_entry in paths {
|
||||
let Ok(dir_entry) = dir_entry else { continue; };
|
||||
let Ok(meta) = dir_entry.metadata() else { continue; };
|
||||
if !meta.is_file() {
|
||||
if !meta.is_file() || !dir_entry.file_name().to_string_lossy().ends_with(".jpg") {
|
||||
continue;
|
||||
}
|
||||
|
||||
timestamps.push(meta.ctime());
|
||||
|
||||
debug!("{}", dir_entry.path().display());
|
||||
|
||||
let img = image::open(dir_entry.path()).unwrap();
|
||||
let crop = img.crop_imm(1872, 1329, 1000, 750);
|
||||
let Ok(img) = image::open(dir_entry.path()) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// File loaded fine, assume it's OK
|
||||
timestamps.push(meta.ctime());
|
||||
|
||||
let crop = img.crop_imm(CROP_X, CROP_Y, CROP_W, CROP_H);
|
||||
let thumb = crop.thumbnail(THUMB_W as u32, THUMB_H as u32);
|
||||
|
||||
crops.push(crop);
|
||||
@@ -86,12 +129,15 @@ fn open_and_reduce_img() {
|
||||
if deviation > THRESHOLD_DEVIATION {
|
||||
info!("LIKELY BIRD!!!! in picture #{thumb_num}");
|
||||
|
||||
let datetime = parse_unix_ts(timestamps[thumb_num]).format("%Y-%m-%d_%H-%M-%S");
|
||||
let path = format!("{}/{}.jpg", FOLDER_OUTPUT, datetime);
|
||||
let datetime_str = parse_unix_ts(timestamps[thumb_num]).format("%Y-%m-%d_%H-%M-%S");
|
||||
let path = format!("{}/{}.jpg", FOLDER_WITH_BIRD_IMAGES, datetime_str);
|
||||
let mut pb = PathBuf::from(path);
|
||||
|
||||
// Ensure we do not overwrite a file if there are multiple in the same second!
|
||||
// This adds -2, -3 etc. to the file name
|
||||
let mut cnt = 2;
|
||||
while pb.exists() {
|
||||
pb.set_file_name(format!("{}-{cnt}.jpg", datetime));
|
||||
pb.set_file_name(format!("{}-{cnt}.jpg", datetime_str));
|
||||
cnt += 1;
|
||||
}
|
||||
|
||||
@@ -101,9 +147,7 @@ fn open_and_reduce_img() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// crop.save(format!("{}/{}", FOLDER_OUTPUT, dir_entry.file_name().to_string_lossy())).unwrap();
|
||||
// thumb.save(format!("{}/th-{}", FOLDER_OUTPUT, dir_entry.file_name().to_string_lossy())).unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_unix_ts(ts: i64) -> chrono::DateTime<Utc> {
|
||||
|
||||
Reference in New Issue
Block a user