mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-03-31 09:43:43 -04:00
add a preliminary schema for object detection (#30)
This commit is contained in:
parent
00991733f2
commit
c6fe1b66a1
37
db/raw.rs
37
db/raw.rs
@ -226,8 +226,8 @@ pub(crate) fn insert_recording(tx: &rusqlite::Transaction, o: &db::Open, id: Com
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tranfers the given recording range from the `recording` and `recording_playback` tables to the
|
/// Transfers the given recording range from the `recording` and associated tables to the `garbage`
|
||||||
/// `garbage` table. `sample_file_dir_id` is assumed to be correct.
|
/// table. `sample_file_dir_id` is assumed to be correct.
|
||||||
///
|
///
|
||||||
/// Returns the number of recordings which were deleted.
|
/// Returns the number of recordings which were deleted.
|
||||||
pub(crate) fn delete_recordings(tx: &rusqlite::Transaction, sample_file_dir_id: i32,
|
pub(crate) fn delete_recordings(tx: &rusqlite::Transaction, sample_file_dir_id: i32,
|
||||||
@ -244,19 +244,25 @@ pub(crate) fn delete_recordings(tx: &rusqlite::Transaction, sample_file_dir_id:
|
|||||||
:start <= composite_id and
|
:start <= composite_id and
|
||||||
composite_id < :end
|
composite_id < :end
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut del1 = tx.prepare_cached(r#"
|
let mut del_playback = tx.prepare_cached(r#"
|
||||||
delete from recording_playback
|
delete from recording_playback
|
||||||
where
|
where
|
||||||
:start <= composite_id and
|
:start <= composite_id and
|
||||||
composite_id < :end
|
composite_id < :end
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut del2 = tx.prepare_cached(r#"
|
let mut del_integrity = tx.prepare_cached(r#"
|
||||||
delete from recording_integrity
|
delete from recording_integrity
|
||||||
where
|
where
|
||||||
:start <= composite_id and
|
:start <= composite_id and
|
||||||
composite_id < :end
|
composite_id < :end
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut del3 = tx.prepare_cached(r#"
|
let mut del_detection = tx.prepare_cached(r#"
|
||||||
|
delete from recording_object_detection
|
||||||
|
where
|
||||||
|
:start <= composite_id and
|
||||||
|
composite_id < :end
|
||||||
|
"#)?;
|
||||||
|
let mut del_main = tx.prepare_cached(r#"
|
||||||
delete from recording
|
delete from recording
|
||||||
where
|
where
|
||||||
:start <= composite_id and
|
:start <= composite_id and
|
||||||
@ -271,17 +277,20 @@ pub(crate) fn delete_recordings(tx: &rusqlite::Transaction, sample_file_dir_id:
|
|||||||
":start": ids.start.0,
|
":start": ids.start.0,
|
||||||
":end": ids.end.0,
|
":end": ids.end.0,
|
||||||
};
|
};
|
||||||
let n1 = del1.execute_named(p)?;
|
let n_playback = del_playback.execute_named(p)?;
|
||||||
if n1 != n {
|
if n_playback != n {
|
||||||
bail!("inserted {} garbage rows but deleted {} recording_playback rows!", n, n1);
|
bail!("inserted {} garbage rows but deleted {} recording_playback rows!", n, n_playback);
|
||||||
}
|
}
|
||||||
let n2 = del2.execute_named(p)?;
|
let n_integrity = del_integrity.execute_named(p)?;
|
||||||
if n2 > n { // fewer is okay; recording_integrity is optional.
|
if n_integrity > n { // fewer is okay; recording_integrity is optional.
|
||||||
bail!("inserted {} garbage rows but deleted {} recording_integrity rows!", n, n2);
|
bail!("inserted {} garbage rows but deleted {} recording_integrity rows!", n, n_integrity);
|
||||||
}
|
}
|
||||||
let n3 = del3.execute_named(p)?;
|
// Any number of object detection rows is okay, as there can be zero or more models per
|
||||||
if n3 != n {
|
// recording.
|
||||||
bail!("deleted {} recording rows but {} recording_playback rows!", n3, n);
|
del_detection.execute_named(p)?;
|
||||||
|
let n_main = del_main.execute_named(p)?;
|
||||||
|
if n_main != n {
|
||||||
|
bail!("inserted {} garbage rows but deleted {} recording rows!", n, n_main);
|
||||||
}
|
}
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
@ -497,5 +497,45 @@ create table signal_change (
|
|||||||
changes blob not null
|
changes blob not null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table object_detection_model (
|
||||||
|
id integer primary key,
|
||||||
|
uuid blob unique not null check (length(uuid) = 16),
|
||||||
|
name text not null,
|
||||||
|
|
||||||
|
-- The actual model and label mappings, in a tbd protocol buffer message
|
||||||
|
-- format.
|
||||||
|
data blob
|
||||||
|
);
|
||||||
|
|
||||||
|
-- An entry for every supported label in any model. (E.g., there is one row
|
||||||
|
-- for "person" even if there are many models that support detecting people.)
|
||||||
|
create table object_detection_label (
|
||||||
|
id integer primary key,
|
||||||
|
uuid blob unique not null check (length(uuid) = 16),
|
||||||
|
name text unique not null,
|
||||||
|
color text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table recording_object_detection (
|
||||||
|
composite_id integer not null references recording (composite_id),
|
||||||
|
model_id integer not null references object_detection_model (id),
|
||||||
|
|
||||||
|
-- repeated:
|
||||||
|
-- * frame delta unsigned varint
|
||||||
|
-- * label unsigned varint
|
||||||
|
-- * xmin, xmax, ymin, ymax as fixed 8-bit numbers
|
||||||
|
-- (any value from knowing xmin <= xmax, ymin <= ymax?
|
||||||
|
-- probably not a whole byte anyway.)
|
||||||
|
-- although 256/300 or 256/320 is not super clean. awkward.
|
||||||
|
-- * score/probability/whatever-it's-called as fixed 8-bit number
|
||||||
|
-- linear scale?
|
||||||
|
frame_data blob not null,
|
||||||
|
|
||||||
|
-- Operations are almost always done on a bounded set of recordings, so
|
||||||
|
-- and perhaps on all models. Use composite_id as the prefix of the primary
|
||||||
|
-- key to make these efficient.
|
||||||
|
primary key (composite_id, model_id)
|
||||||
|
);
|
||||||
|
|
||||||
insert into version (id, unix_time, notes)
|
insert into version (id, unix_time, notes)
|
||||||
values (6, cast(strftime('%s', 'now') as int), 'db creation');
|
values (6, cast(strftime('%s', 'now') as int), 'db creation');
|
||||||
|
@ -209,6 +209,27 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
|||||||
revocation_reason_detail = 'Blake2b->Blake3 upgrade'
|
revocation_reason_detail = 'Blake2b->Blake3 upgrade'
|
||||||
where
|
where
|
||||||
revocation_reason is null;
|
revocation_reason is null;
|
||||||
|
|
||||||
|
create table object_detection_model (
|
||||||
|
id integer primary key,
|
||||||
|
uuid blob unique not null check (length(uuid) = 16),
|
||||||
|
name text not null,
|
||||||
|
data blob
|
||||||
|
);
|
||||||
|
|
||||||
|
create table object_detection_label (
|
||||||
|
id integer primary key,
|
||||||
|
uuid blob unique not null check (length(uuid) = 16),
|
||||||
|
name text unique not null,
|
||||||
|
color text
|
||||||
|
);
|
||||||
|
|
||||||
|
create table recording_object_detection (
|
||||||
|
composite_id integer not null references recording (composite_id),
|
||||||
|
model_id integer not null references object_detection_model (id),
|
||||||
|
frame_data blob not null,
|
||||||
|
primary key (composite_id, model_id)
|
||||||
|
);
|
||||||
"#)?;
|
"#)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -252,8 +252,7 @@ Version 6 adds over version 5:
|
|||||||
streams.
|
streams.
|
||||||
* hashes in Blake3 rather than older SHA-1 (for file integrity checksums)
|
* hashes in Blake3 rather than older SHA-1 (for file integrity checksums)
|
||||||
or Blake2b (for sessions).
|
or Blake2b (for sessions).
|
||||||
|
* a preliminary schema for [object
|
||||||
|
detection](https://en.wikipedia.org/wiki/Object_detection).
|
||||||
|
|
||||||
On upgrading to this version, sessions will be wiped.
|
On upgrading to this version, sessions will be revoked.
|
||||||
|
|
||||||
Before it is finalized, it likely will also add a schema for [object
|
|
||||||
detection](https://en.wikipedia.org/wiki/Object_detection).
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user