123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- use ndarray::{Array, Axis, IxDyn};
- #[derive(Clone, PartialEq, Default)]
- pub struct YOLOResult {
- // YOLO tasks results of an image
- pub probs: Option<Embedding>,
- pub bboxes: Option<Vec<Bbox>>,
- pub keypoints: Option<Vec<Vec<Point2>>>,
- pub masks: Option<Vec<Vec<u8>>>,
- }
- impl std::fmt::Debug for YOLOResult {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_struct("YOLOResult")
- .field(
- "Probs(top5)",
- &format_args!("{:?}", self.probs().map(|probs| probs.topk(5))),
- )
- .field("Bboxes", &self.bboxes)
- .field("Keypoints", &self.keypoints)
- .field(
- "Masks",
- &format_args!("{:?}", self.masks().map(|masks| masks.len())),
- )
- .finish()
- }
- }
- impl YOLOResult {
- pub fn new(
- probs: Option<Embedding>,
- bboxes: Option<Vec<Bbox>>,
- keypoints: Option<Vec<Vec<Point2>>>,
- masks: Option<Vec<Vec<u8>>>,
- ) -> Self {
- Self {
- probs,
- bboxes,
- keypoints,
- masks,
- }
- }
- pub fn probs(&self) -> Option<&Embedding> {
- self.probs.as_ref()
- }
- pub fn keypoints(&self) -> Option<&Vec<Vec<Point2>>> {
- self.keypoints.as_ref()
- }
- pub fn masks(&self) -> Option<&Vec<Vec<u8>>> {
- self.masks.as_ref()
- }
- pub fn bboxes(&self) -> Option<&Vec<Bbox>> {
- self.bboxes.as_ref()
- }
- pub fn bboxes_mut(&mut self) -> Option<&mut Vec<Bbox>> {
- self.bboxes.as_mut()
- }
- }
- #[derive(Debug, PartialEq, Clone, Default)]
- pub struct Point2 {
- // A point2d with x, y, conf
- x: f32,
- y: f32,
- confidence: f32,
- }
- impl Point2 {
- pub fn new_with_conf(x: f32, y: f32, confidence: f32) -> Self {
- Self { x, y, confidence }
- }
- pub fn new(x: f32, y: f32) -> Self {
- Self {
- x,
- y,
- ..Default::default()
- }
- }
- pub fn x(&self) -> f32 {
- self.x
- }
- pub fn y(&self) -> f32 {
- self.y
- }
- pub fn confidence(&self) -> f32 {
- self.confidence
- }
- }
- #[derive(Debug, Clone, PartialEq, Default)]
- pub struct Embedding {
- // An float32 n-dims tensor
- data: Array<f32, IxDyn>,
- }
- impl Embedding {
- pub fn new(data: Array<f32, IxDyn>) -> Self {
- Self { data }
- }
- pub fn data(&self) -> &Array<f32, IxDyn> {
- &self.data
- }
- pub fn topk(&self, k: usize) -> Vec<(usize, f32)> {
- let mut probs = self
- .data
- .iter()
- .enumerate()
- .map(|(a, b)| (a, *b))
- .collect::<Vec<_>>();
- probs.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
- let mut topk = Vec::new();
- for &(id, confidence) in probs.iter().take(k) {
- topk.push((id, confidence));
- }
- topk
- }
- pub fn norm(&self) -> Array<f32, IxDyn> {
- let std_ = self.data.mapv(|x| x * x).sum_axis(Axis(0)).mapv(f32::sqrt);
- self.data.clone() / std_
- }
- pub fn top1(&self) -> (usize, f32) {
- self.topk(1)[0]
- }
- }
- #[derive(Debug, Clone, PartialEq, Default)]
- pub struct Bbox {
- // a bounding box around an object
- xmin: f32,
- ymin: f32,
- width: f32,
- height: f32,
- id: usize,
- confidence: f32,
- }
- impl Bbox {
- pub fn new_from_xywh(xmin: f32, ymin: f32, width: f32, height: f32) -> Self {
- Self {
- xmin,
- ymin,
- width,
- height,
- ..Default::default()
- }
- }
- pub fn new(xmin: f32, ymin: f32, width: f32, height: f32, id: usize, confidence: f32) -> Self {
- Self {
- xmin,
- ymin,
- width,
- height,
- id,
- confidence,
- }
- }
- pub fn width(&self) -> f32 {
- self.width
- }
- pub fn height(&self) -> f32 {
- self.height
- }
- pub fn xmin(&self) -> f32 {
- self.xmin
- }
- pub fn ymin(&self) -> f32 {
- self.ymin
- }
- pub fn xmax(&self) -> f32 {
- self.xmin + self.width
- }
- pub fn ymax(&self) -> f32 {
- self.ymin + self.height
- }
- pub fn tl(&self) -> Point2 {
- Point2::new(self.xmin, self.ymin)
- }
- pub fn br(&self) -> Point2 {
- Point2::new(self.xmax(), self.ymax())
- }
- pub fn cxcy(&self) -> Point2 {
- Point2::new(self.xmin + self.width / 2., self.ymin + self.height / 2.)
- }
- pub fn id(&self) -> usize {
- self.id
- }
- pub fn confidence(&self) -> f32 {
- self.confidence
- }
- pub fn area(&self) -> f32 {
- self.width * self.height
- }
- pub fn intersection_area(&self, another: &Bbox) -> f32 {
- let l = self.xmin.max(another.xmin);
- let r = (self.xmin + self.width).min(another.xmin + another.width);
- let t = self.ymin.max(another.ymin);
- let b = (self.ymin + self.height).min(another.ymin + another.height);
- (r - l + 1.).max(0.) * (b - t + 1.).max(0.)
- }
- pub fn union(&self, another: &Bbox) -> f32 {
- self.area() + another.area() - self.intersection_area(another)
- }
- pub fn iou(&self, another: &Bbox) -> f32 {
- self.intersection_area(another) / self.union(another)
- }
- }
|