use nalgebra::*;
use nalgebra::storage::*;
use std::iter::Iterator;
use std::fmt::Display;
use std::convert::TryFrom;
use std::ops::Range;
use opencv::{core, imgproc};
use opencv::prelude::MatTrait;
use opencv::prelude::MatTraitManual;
use std::ffi;
use std::mem;
pub fn get_cv_type<T>() -> i32
where
T : Scalar
{
if T::is::<u8>() {
core::CV_8UC1
} else {
if T::is::<i16>() {
core::CV_16SC1
} else {
if T::is::<f32>() {
core::CV_32FC1
} else {
if T::is::<f64>() {
core::CV_64FC1
} else {
panic!("Invalid matrix type");
}
}
}
}
}
pub unsafe fn dmatrix_to_mat<T>(d : &DMatrix<T>) -> core::Mat
where
T : Scalar
{
slice_to_mat(d.as_slice(), d.ncols(), None)
}
pub unsafe fn dvector_to_mat<T>(d : &DVector<T>) -> core::Mat
where
T : Scalar
{
slice_to_mat(d.as_slice(), 1, None)
}
pub unsafe fn slice_to_mat<T>(
slice : &[T],
stride : usize,
opt_subslice : Option<((usize, usize), (usize, usize))>,
) -> core::Mat
where
T : Scalar
{
let (nrow, ncol) = if let Some((_, sz)) = opt_subslice {
sz
} else {
(slice.len() / stride, stride)
};
let byte_stride = if opt_subslice.is_some() {
stride * mem::size_of::<T>()
} else {
core::Mat_AUTO_STEP
};
let effective_slice : &[T] = if let Some((offset, _)) = opt_subslice {
let fst_ix = stride*offset.0 + offset.1;
&slice[fst_ix..]
} else {
slice
};
let cv_type = get_cv_type::<T>();
core::Mat::new_rows_cols_with_data(
nrow as i32,
ncol as i32,
cv_type,
effective_slice.as_ptr() as *mut ffi::c_void,
byte_stride
).unwrap()
}
pub unsafe fn convert<T, U>(
src : &[T],
dst : &mut [U],
src_stride : usize,
src_opt_subsample : Option<((usize, usize), (usize, usize))>,
dst_stride : usize,
dst_opt_subsample : Option<((usize, usize), (usize, usize))>
)
where
T : Scalar,
U : Scalar
{
let src = slice_to_mat(src, src_stride, src_opt_subsample);
let mut dst = slice_to_mat(&dst, dst_stride, dst_opt_subsample);
let scale = 1.0;
let offset = 0.0;
src.convert_to(&mut dst, get_cv_type::<U>(), scale, offset).unwrap();
}
pub unsafe fn resize<T>(
src : &[T],
dst : &mut [T],
src_stride : usize,
src_opt_subsample : Option<((usize, usize), (usize, usize))>,
dst_stride : usize,
dst_opt_subsample : Option<((usize, usize), (usize, usize))>
)
where
T : Scalar
{
let src = slice_to_mat(src, src_stride, src_opt_subsample);
let mut dst = slice_to_mat(&dst, dst_stride, dst_opt_subsample);
let dst_sz = dst.size().unwrap();
imgproc::resize(&src, &mut dst, dst_sz, 0.0, 0.0, imgproc::INTER_NEAREST);
}
pub unsafe fn write_text(dst : &mut [u8], ncol : usize, tl_pos : (usize, usize), text : &str, color : u8) {
let mut dst_mat = slice_to_mat(&dst, ncol, None);
imgproc::put_text(
&mut dst_mat,
text,
core::Point{ x : tl_pos.1 as i32, y : tl_pos.0 as i32 },
imgproc::FONT_HERSHEY_SIMPLEX,
1.0,
core::Scalar::all(color.into()),
1,
imgproc::LINE_8,
false
).unwrap()
}
pub unsafe fn draw_line(dst : &mut [u8], ncol : usize, from : (usize, usize), to : (usize, usize), color : u8) {
let nrow = dst.len() / ncol;
if from.0 > nrow || from.1 > ncol {
println!("Line origin outside bounds");
return;
}
if to.0 > nrow || to.1 > ncol {
println!("Line destination outside bounds");
return;
}
let mut dst_mat = slice_to_mat(&dst, ncol, None);
let line_ty = imgproc::LINE_8;
imgproc::line(
&mut dst_mat,
core::Point{ x : from.1 as i32, y : from.0 as i32 },
core::Point{ x : to.1 as i32, y : to.0 as i32 },
core::Scalar::all(color.into()),
1,
line_ty,
0
).unwrap()
}
pub unsafe fn draw_circle(dst : &mut [u8], ncol : usize, center : (usize, usize), radius : usize, color : u8) {
let nrow = dst.len() / ncol;
if center.0 + radius > nrow || center.1 + radius > ncol {
return;
}
let mut dst_mat = slice_to_mat(&dst, ncol, None);
let thickness = 1;
let line_ty = imgproc::LINE_8;
let shift = 0;
imgproc::circle(
&mut dst_mat,
core::Point2i{ x : center.1 as i32, y : center.0 as i32 },
radius as i32,
core::Scalar::all(color.into()),
thickness,
line_ty,
shift
).unwrap();
}