cleaning, rename, add loops

master
Ondřej Hruška 1 year 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",
]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bird-detector"
version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
"clap",
"env_logger",
"image",
"log",
]
[[package]]
name = "bitflags"
version = "2.4.1"
@ -318,17 +336,6 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "krmdet"
version = "0.1.0"
dependencies = [
"chrono",
"clap",
"env_logger",
"image",
"log",
]
[[package]]
name = "libc"
version = "0.2.150"

@ -1,5 +1,5 @@
[package]
name = "krmdet"
name = "bird-detector"
version = "0.1.0"
edition = "2021"
@ -12,3 +12,4 @@ clap = "4.4.7"
log = "0.4.20"
env_logger = "0.10.0"
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::path::PathBuf;
use std::time::Duration;
use anyhow::Context;
use chrono::{NaiveDateTime, Utc};
use image::{GenericImageView, Pixel};
use log::{debug, error, info};
fn main() {
open_and_reduce_img();
}
/// 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";
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;
const THUMB_H : usize = 8;
/// Image cropping config: crop width
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() {
env_logger::init_from_env("LOGGING");
/// 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;
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 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> {

Loading…
Cancel
Save