cleaning, rename, add loops

master
Ondřej Hruška 6 months ago
parent 66d1b14f85
commit 233223bee4
  1. 29
      Cargo.lock
  2. 3
      Cargo.toml
  3. 2
      birds/.gitignore
  4. 90
      src/main.rs

29
Cargo.lock generated

@ -74,12 +74,30 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bird-detector"
version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
"clap",
"env_logger",
"image",
"log",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.4.1" version = "2.4.1"
@ -318,17 +336,6 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "krmdet"
version = "0.1.0"
dependencies = [
"chrono",
"clap",
"env_logger",
"image",
"log",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.150" version = "0.2.150"

@ -1,5 +1,5 @@
[package] [package]
name = "krmdet" name = "bird-detector"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
@ -12,3 +12,4 @@ clap = "4.4.7"
log = "0.4.20" log = "0.4.20"
env_logger = "0.10.0" env_logger = "0.10.0"
chrono = "0.4.31" chrono = "0.4.31"
anyhow = "1.0.75"

2
birds/.gitignore vendored

@ -1,2 +0,0 @@
*
!.gitignore

@ -1,29 +1,68 @@
use std::os::unix::fs::MetadataExt; use std::os::unix::fs::MetadataExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration;
use anyhow::Context;
use chrono::{NaiveDateTime, Utc}; use chrono::{NaiveDateTime, Utc};
use image::{GenericImageView, Pixel}; use image::{GenericImageView, Pixel};
use log::{debug, error, info}; use log::{debug, error, info};
fn main() { /// Folder the camera images are uploaded to
open_and_reduce_img(); 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";
const FOLDER_WITH_IMAGES : &str = "../2/"; /// Image cropping config: left top X
const CROP_X : u32 = 1872;
const FOLDER_OUTPUT : &str = "birds"; /// Image cropping config: left top Y
const CROP_Y : u32 = 1329;
const THUMB_W : usize = 12; /// Image cropping config: crop width
const THUMB_H : usize = 8; const CROP_W : u32 = 1000;
const THRESHOLD_DEVIATION : u32 = 500; /// Image cropping config: crop height
const CROP_H : u32 = 750;
fn open_and_reduce_img() { /// Thumbnail width, used for bird detection (together with height creates the kernel size)
env_logger::init_from_env("LOGGING"); /// This is a compromise between sensitivity and susceptibility to false positives.
const THUMB_W: usize = 12;
info!("Bird finder starts"); /// 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() {
env_logger::init();
let paths = std::fs::read_dir(FOLDER_WITH_IMAGES).unwrap(); 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");
let paths = std::fs::read_dir(FOLDER_WITH_NEW_IMAGES).context("Read folder with images")?;
let mut crops = vec![]; let mut crops = vec![];
let mut thumbs = vec![]; let mut thumbs = vec![];
@ -33,16 +72,20 @@ fn open_and_reduce_img() {
for dir_entry in paths { for dir_entry in paths {
let Ok(dir_entry) = dir_entry else { continue; }; let Ok(dir_entry) = dir_entry else { continue; };
let Ok(meta) = dir_entry.metadata() 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; continue;
} }
timestamps.push(meta.ctime());
debug!("{}", dir_entry.path().display()); debug!("{}", dir_entry.path().display());
let img = image::open(dir_entry.path()).unwrap(); let Ok(img) = image::open(dir_entry.path()) else {
let crop = img.crop_imm(1872, 1329, 1000, 750); 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); let thumb = crop.thumbnail(THUMB_W as u32, THUMB_H as u32);
crops.push(crop); crops.push(crop);
@ -86,12 +129,15 @@ fn open_and_reduce_img() {
if deviation > THRESHOLD_DEVIATION { if deviation > THRESHOLD_DEVIATION {
info!("LIKELY BIRD!!!! in picture #{thumb_num}"); info!("LIKELY BIRD!!!! in picture #{thumb_num}");
let datetime = parse_unix_ts(timestamps[thumb_num]).format("%Y-%m-%d_%H-%M-%S"); let datetime_str = parse_unix_ts(timestamps[thumb_num]).format("%Y-%m-%d_%H-%M-%S");
let path = format!("{}/{}.jpg", FOLDER_OUTPUT, datetime); let path = format!("{}/{}.jpg", FOLDER_WITH_BIRD_IMAGES, datetime_str);
let mut pb = PathBuf::from(path); 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; let mut cnt = 2;
while pb.exists() { while pb.exists() {
pb.set_file_name(format!("{}-{cnt}.jpg", datetime)); pb.set_file_name(format!("{}-{cnt}.jpg", datetime_str));
cnt += 1; cnt += 1;
} }
@ -101,9 +147,7 @@ fn open_and_reduce_img() {
} }
} }
Ok(())
// 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();
} }
fn parse_unix_ts(ts: i64) -> chrono::DateTime<Utc> { fn parse_unix_ts(ts: i64) -> chrono::DateTime<Utc> {

Loading…
Cancel
Save