Compare commits
5 Commits
57a2c3197e
...
056bb2f96c
Author | SHA1 | Date | |
---|---|---|---|
|
056bb2f96c | ||
|
a612d4f7d7 | ||
|
ce6fa022f9 | ||
|
18c952f94d | ||
|
b7714ca957 |
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,4 @@
|
||||||
/venv
|
/venv
|
||||||
/frames
|
/frames
|
||||||
|
**/*.png
|
||||||
|
thermaldecoder/target
|
||||||
|
|
15
README.md
Normal file
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
### Thermal decoder
|
||||||
|
|
||||||
|
https://wiki.telavivmakers.org/tamiwiki/projects/thermalcam
|
||||||
|
|
||||||
|
|
||||||
|
### Rust lib usage
|
||||||
|
|
||||||
|
# if you don't already have a virtualenv. Linux specific, adjust to your OS.
|
||||||
|
```bash
|
||||||
|
virtualenv venv
|
||||||
|
. venv/bin/activate
|
||||||
|
pip install -r requirements.txt
|
||||||
|
(cd thermaldecoder; maturin develop -r)
|
||||||
|
python test_rust.py
|
||||||
|
```
|
|
@ -1,3 +0,0 @@
|
||||||
### Thermal decoder
|
|
||||||
|
|
||||||
https://wiki.telavivmakers.org/tamiwiki/projects/thermalcam
|
|
|
@ -12,6 +12,7 @@ jedi==0.19.1
|
||||||
kiwisolver==1.4.5
|
kiwisolver==1.4.5
|
||||||
matplotlib==3.8.2
|
matplotlib==3.8.2
|
||||||
matplotlib-inline==0.1.6
|
matplotlib-inline==0.1.6
|
||||||
|
maturin==1.4.0
|
||||||
numpy==1.26.2
|
numpy==1.26.2
|
||||||
opencv-python==4.8.1.78
|
opencv-python==4.8.1.78
|
||||||
packaging==23.2
|
packaging==23.2
|
||||||
|
|
11
test_rust.py
Normal file
11
test_rust.py
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
from pathlib import Path
|
||||||
|
from thermaldecoder import decode
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
root = Path('frames')
|
||||||
|
root.mkdir(exist_ok=True)
|
||||||
|
frames = decode('in.pcap', 'frames')
|
||||||
|
f = np.array(frames[0])
|
||||||
|
f.shape = (384, 288)
|
||||||
|
plt.imshow(f)
|
||||||
|
plt.show()
|
BIN
thermal.mp4
BIN
thermal.mp4
Binary file not shown.
|
@ -400,7 +400,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thermalcamdecoder"
|
name = "thermaldecoder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
|
@ -1,14 +1,18 @@
|
||||||
[package]
|
[package]
|
||||||
name = "thermalcamdecoder"
|
name = "thermaldecoder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "thermaldecoder"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.77"
|
anyhow = "1.0.77"
|
||||||
indicatif = "0.17.7"
|
indicatif = "0.17.7"
|
||||||
pcap-parser = { version = "0.14.1", features = ["data"] }
|
pcap-parser = { version = "0.14.1", features = ["data"] }
|
||||||
png = "0.17.10"
|
png = "0.17.10"
|
||||||
pyo3 = "0.20.0"
|
pyo3 = { version = "0.20.0", "features" = ["extension-module"] }
|
||||||
serde = { version = "1.0.193", features = ["derive", "serde_derive", "alloc"] }
|
serde = { version = "1.0.193", features = ["derive", "serde_derive", "alloc"] }
|
|
@ -1,5 +1,7 @@
|
||||||
use indicatif::{ProgressBar, ProgressIterator};
|
use indicatif::{ProgressBar, ProgressIterator};
|
||||||
use png;
|
use png;
|
||||||
|
use pyo3::exceptions::PyValueError;
|
||||||
|
use pyo3::prelude::*;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufWriter;
|
use std::io::BufWriter;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
@ -8,8 +10,8 @@ use std::path::Path;
|
||||||
use pcap_parser::traits::PcapReaderIterator;
|
use pcap_parser::traits::PcapReaderIterator;
|
||||||
use pcap_parser::*;
|
use pcap_parser::*;
|
||||||
|
|
||||||
fn get_packets_without_udp_header() -> anyhow::Result<(Vec<Vec<u8>>, usize, usize)> {
|
fn get_packets_without_udp_header(filename: &str) -> anyhow::Result<(Vec<Vec<u8>>, usize, usize)> {
|
||||||
let file = File::open("in.pcap")?;
|
let file = File::open(filename)?;
|
||||||
let mut cap = PcapNGReader::new(65535, file)?;
|
let mut cap = PcapNGReader::new(65535, file)?;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut size = 0;
|
let mut size = 0;
|
||||||
|
@ -102,11 +104,19 @@ impl Header {
|
||||||
|
|
||||||
const HDR_SIZE: usize = std::mem::size_of::<Header>();
|
const HDR_SIZE: usize = std::mem::size_of::<Header>();
|
||||||
|
|
||||||
fn main() -> anyhow::Result<()> {
|
#[pyfunction]
|
||||||
let (data, i, size) = get_packets_without_udp_header()?;
|
fn decode(filename: &str, frames_root: &str) -> PyResult<Vec<Vec<u16>>> {
|
||||||
|
let res =
|
||||||
|
decode_raw(filename, frames_root).map_err(|_| PyValueError::new_err("failed to read"))?;
|
||||||
|
Ok(res.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decode_raw(filename: &str, frames_root: &str) -> anyhow::Result<Vec<Vec<u16>>> {
|
||||||
|
let (data, i, size) = get_packets_without_udp_header(filename)?;
|
||||||
|
|
||||||
println!("found {} packets, saved {}, {} size", i, data.len(), size);
|
println!("found {} packets, saved {}, {} size", i, data.len(), size);
|
||||||
let mut dump = File::create_new("dump.bin");
|
let dump_filename = format!("{}/dump.bin", filename);
|
||||||
|
let mut dump = File::create_new(dump_filename);
|
||||||
let mut frames = vec![];
|
let mut frames = vec![];
|
||||||
let mut parts = vec![];
|
let mut parts = vec![];
|
||||||
for packet in data.iter() {
|
for packet in data.iter() {
|
||||||
|
@ -125,7 +135,7 @@ fn main() -> anyhow::Result<()> {
|
||||||
println!("writing raw pngs");
|
println!("writing raw pngs");
|
||||||
let pb = ProgressBar::new(frames.len() as u64);
|
let pb = ProgressBar::new(frames.len() as u64);
|
||||||
for (i, frame) in frames.iter().enumerate().progress_with(pb) {
|
for (i, frame) in frames.iter().enumerate().progress_with(pb) {
|
||||||
let name = format!("{:03}.png", i);
|
let name = format!("{}/{:04}.png", frames_root, i);
|
||||||
let path = Path::new(&name);
|
let path = Path::new(&name);
|
||||||
let file = File::create(path).unwrap();
|
let file = File::create(path).unwrap();
|
||||||
let ref mut w = BufWriter::new(file);
|
let ref mut w = BufWriter::new(file);
|
||||||
|
@ -138,8 +148,9 @@ fn main() -> anyhow::Result<()> {
|
||||||
|
|
||||||
println!("writing calibrated (value is temperature)");
|
println!("writing calibrated (value is temperature)");
|
||||||
let pb = ProgressBar::new(frames.len() as u64);
|
let pb = ProgressBar::new(frames.len() as u64);
|
||||||
|
let mut framesu16 = vec![];
|
||||||
for (i, frame) in frames.iter().enumerate().progress_with(pb) {
|
for (i, frame) in frames.iter().enumerate().progress_with(pb) {
|
||||||
let name = format!("temp_{:03}.png", i);
|
let name = format!("{}/temp_{:04}.png", frames_root, i);
|
||||||
let path = Path::new(&name);
|
let path = Path::new(&name);
|
||||||
let file = File::create(path).unwrap();
|
let file = File::create(path).unwrap();
|
||||||
let ref mut w = BufWriter::new(file);
|
let ref mut w = BufWriter::new(file);
|
||||||
|
@ -147,8 +158,12 @@ fn main() -> anyhow::Result<()> {
|
||||||
encoder.set_color(png::ColorType::Grayscale);
|
encoder.set_color(png::ColorType::Grayscale);
|
||||||
encoder.set_depth(png::BitDepth::Eight);
|
encoder.set_depth(png::BitDepth::Eight);
|
||||||
let mut writer = encoder.write_header()?;
|
let mut writer = encoder.write_header()?;
|
||||||
let p = frame.as_ptr();
|
//let samples: &[u16] = unsafe { std::slice::from_raw_parts(p.cast(), frame.len() / 2) };
|
||||||
let samples: &[u16] = unsafe { std::slice::from_raw_parts(p.cast(), frame.len() / 2) };
|
let samples: Vec<u16> = (0..frame.len())
|
||||||
|
.step_by(2)
|
||||||
|
.map(|i| u16::from_be_bytes([frame[i], frame[i + 1]]))
|
||||||
|
.collect();
|
||||||
|
framesu16.push(samples.clone());
|
||||||
let frame = samples
|
let frame = samples
|
||||||
.iter()
|
.iter()
|
||||||
.copied()
|
.copied()
|
||||||
|
@ -164,5 +179,11 @@ fn main() -> anyhow::Result<()> {
|
||||||
writer.write_image_data(&frame)?;
|
writer.write_image_data(&frame)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(framesu16)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[pymodule]
|
||||||
|
fn thermaldecoder(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
||||||
|
m.add_function(wrap_pyfunction!(decode, m)?)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
4
thermaldecoder/src/main.rs
Normal file
4
thermaldecoder/src/main.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
//fn main() -> anyhow::Result<()> {
|
||||||
|
// decode_raw("dump.bin")?;
|
||||||
|
// Ok(())
|
||||||
|
//}
|
Loading…
Reference in New Issue
Block a user