This is currently horrendously slow, as it operates on the full-resolution image. Also the maths is probaly wrong, and compressed videos are handled very poorly.
2ZEXFAG3WLJUWQ6BLYODFO3OCTYAVAOZAQYYPMSZYEGCO4AQU5VAC fn main() {println!("Hello, world!");
use opencv::core::{cart_to_polar, merge, no_array, normalize, split, Mat as Matrix, MatTraitConst,MatTraitConstManual, Ptr, Size, ToOutputArray, Vector, CV_32F, CV_8U, NORM_MINMAX,};use opencv::imgcodecs::imwrite;use opencv::imgproc::{cvt_color, COLOR_HSV2BGR};use opencv::optflow::{calc_optical_flow_dense_rlof, InterpolationType, RLOFOpticalFlowParameter};use opencv::prelude::MatExprTraitConst;use opencv::types::VectorOfMat;use opencv::videoio::{VideoCapture, VideoCaptureTrait, VideoCaptureTraitConst, VideoWriter, VideoWriterTrait,CAP_ANY, CAP_PROP_FOURCC, CAP_PROP_FPS, CAP_PROP_FRAME_HEIGHT, CAP_PROP_FRAME_WIDTH,};fn read_frame(video: &mut VideoCapture,frame: &mut impl ToOutputArray,) -> Result<bool, anyhow::Error> {Ok(video.read(frame)?)}fn main() -> Result<(), anyhow::Error> {let mut input_video = VideoCapture::from_file("../clips/edit.webm", CAP_ANY)?;let mut output_video = VideoWriter::new("output.webm",input_video.get(CAP_PROP_FOURCC)? as i32,input_video.get(CAP_PROP_FPS)?,Size::new(input_video.get(CAP_PROP_FRAME_WIDTH)? as i32,input_video.get(CAP_PROP_FRAME_HEIGHT)? as i32,),true,)?;let mut frame_count = 0;let mut last_frame = Matrix::default();input_video.read(&mut last_frame).expect("Video cannot be empty");let mut current_frame = Matrix::default();while read_frame(&mut input_video, &mut current_frame)? {println!("Frame {frame_count}");let mut computed_flow = unsafe { Matrix::new_size(current_frame.size()?, CV_32F)? };calc_optical_flow_dense_rlof(&last_frame,¤t_frame,&mut computed_flow,Ptr::new(RLOFOpticalFlowParameter::default()?),1 as f32,Size::new(6, 6),InterpolationType::INTERP_EPIC,128,0.005,999 as f32,15,100,true,500 as f32,1.5,false,)?;let mut flow_parts: VectorOfMat = Vec::with_capacity(2).into();split(&computed_flow, &mut flow_parts)?;assert_eq!(flow_parts.len(), 2);let mut magnitude = Matrix::default();let mut normalized_magnitude = Matrix::default();let mut angle = Matrix::default();cart_to_polar(&flow_parts.get(0)?,&flow_parts.get(1)?,&mut magnitude,&mut angle,true,)?;normalize(&magnitude,&mut normalized_magnitude,0 as f64,1 as f64,NORM_MINMAX,-1,&no_array(),)?;angle = (angle * (1_f64 / 360_f64) * (180_f64 / 255_f64)).into_result()?.to_mat()?;let mut hsv_vec = VectorOfMat::with_capacity(3);hsv_vec.push(angle.clone());hsv_vec.push(Matrix::ones_size(angle.size()?, CV_32F)?.to_mat()?);hsv_vec.push(normalized_magnitude);assert_eq!(hsv_vec.len(), 3);let mut hsv = Matrix::default();let mut hsv_8 = Matrix::default();let mut bgr = Matrix::default();merge(&hsv_vec, &mut hsv)?;hsv.convert_to(&mut hsv_8, CV_8U, 255 as f64, 0 as f64)?;cvt_color(&hsv_8, &mut bgr, COLOR_HSV2BGR, 0)?;// output_video.write(&bgr)?;imwrite(&format!("frames/frame{frame_count}.jpg"),&bgr,&Vector::new(),)?;assert_eq!(current_frame.size()?, last_frame.size()?);last_frame = current_frame.clone();// if frame_count > 5 {// break;// } else {// }frame_count += 1;}Ok(())
anyhow = { version = "1.0.71", features = ["backtrace"] }opencv = { version = "0.83.0", default-features = false, features = ["optflow", "videoio", "imgproc", "imgcodecs"] }
[[package]]name = "addr2line"version = "0.20.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"dependencies = ["gimli",][[package]]name = "adler"version = "1.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"[[package]]name = "aho-corasick"version = "1.0.2"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"dependencies = ["memchr",][[package]]name = "anyhow"version = "1.0.71"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"dependencies = ["backtrace",][[package]]name = "autocfg"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"[[package]]name = "backtrace"version = "0.3.68"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"dependencies = ["addr2line","cc","cfg-if","libc","miniz_oxide","object","rustc-demangle",][[package]]name = "cc"version = "1.0.79"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"dependencies = ["jobserver",][[package]]name = "cfg-if"version = "1.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
name = "clang"version = "2.0.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "84c044c781163c001b913cd018fc95a628c50d0d2dfea8bca77dad71edb16e37"dependencies = ["clang-sys","libc",][[package]]name = "clang-sys"version = "1.6.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"dependencies = ["glob","libc",][[package]]
dependencies = ["anyhow","opencv",][[package]]name = "dunce"version = "1.0.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b"[[package]]name = "gimli"version = "0.27.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"[[package]]name = "glob"version = "0.3.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"[[package]]name = "jobserver"version = "0.1.26"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"dependencies = ["libc",][[package]]name = "libc"version = "0.2.147"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"[[package]]name = "memchr"version = "2.5.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"[[package]]name = "miniz_oxide"version = "0.7.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"dependencies = ["adler",][[package]]name = "num-traits"version = "0.2.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"dependencies = ["autocfg",][[package]]name = "object"version = "0.31.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"dependencies = ["memchr",][[package]]name = "once_cell"version = "1.18.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"[[package]]name = "opencv"version = "0.83.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "998598d7574b0ec0f7230b7b9782ab516ccf612dbacb6ba83ca1b0e2af537359"dependencies = ["cc","dunce","jobserver","libc","num-traits","once_cell","opencv-binding-generator","pkg-config","semver","shlex","vcpkg",][[package]]name = "opencv-binding-generator"version = "0.67.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "eb6b3b79658fe7db11c250913b85915b4cadc7bf5f70181572f55437327fb294"dependencies = ["clang","clang-sys","dunce","once_cell","percent-encoding","regex",][[package]]name = "percent-encoding"version = "2.3.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"[[package]]name = "pkg-config"version = "0.3.27"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"[[package]]name = "regex"version = "1.9.1"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"dependencies = ["aho-corasick","memchr","regex-automata","regex-syntax",][[package]]name = "regex-automata"version = "0.3.3"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"dependencies = ["aho-corasick","memchr","regex-syntax",][[package]]name = "regex-syntax"version = "0.7.4"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"[[package]]name = "rustc-demangle"version = "0.1.23"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"[[package]]name = "semver"version = "1.0.17"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"[[package]]name = "shlex"version = "1.1.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3"[[package]]name = "vcpkg"version = "0.2.15"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
output.webm