DataScience
Published 2023. 7. 5. 13:28
[Rust] 동영상에 Box 그리기 Rust
728x90

decode : video-rs
imageprocess : imageproc

video-rs를 이용하여 영상을 decode후 decode_iter()로 frame별 픽셀 값을 추출합니다.
추출한 frame에 imageproc::drawing::draw_hollow_rect 함수를 이용하여 사각형을 그립니다.

 

pub fn draw_hollow_rect<I>(
    image: &I, 
    rect: Rect, 
    color: I::Pixel
) -> Image<I::Pixel> 
where
    I: GenericImage,

함수에서 입력받는 이미지 형식이 GenericImage입니다.

 

형 변환 방법

  • imagebuffer에 for문으로 픽셀값 넣어주는 방법
  • ndarray to image trait으로 generic image 변환후 사각형 그리는방법
  • 픽셀값을 직접 수정해서 사각형만 그려주는 방법

형변환: imagebuffer에 for문으로 픽셀값 넣어주는 방법

fn main() {
    video_rs::init().unwrap();
    let mut decoder = Decoder::new(&PathBuf::from("/home/yimstar9/ObjectTracking/videors/crowd.mp4").into()).unwrap();

    //사각형 설정
    let rect = Rect::at(300, 300).of_size(50, 30);

    //시간체크용 타이머
    let start = SystemTime::now();
   
    for frame in decoder.decode_iter() {
        if let Ok((_, frame)) = frame {

            // decoder의 결과값(frame)을 image trait의 imagebuffer형식으로 바꿔야 합니다. 
            // frame에서 픽셀값을 for문으로 imagebuffer에 하나씩 넣어줍니다.
            let mut img = RgbImage::new(720,1280);
            for x in 0..720 {
                for y in 0..1280 {
                    // https://crates.io/crates/video-rs/0.4.0 frame에서 x,y위치의 픽셀값 추출
                    let rgb = frame
                    .slice(ndarray::s![x as i32, y as i32, ..])
                    .to_slice()
                    .unwrap();
                    
                    img.put_pixel(x, y, Rgb([rgb[0],rgb[1],rgb[2]]));
                }
            }
            // https://docs.rs/imageproc/latest/imageproc/drawing/fn.draw_hollow_rect.html 이미지에 사각형 그립니다.
            let mut rect = draw_hollow_rect(&img, rect, Rgb([255, 0, 0]));
        } else {
            break;
        }
    }
    //시간체크용 타이머
    let end = SystemTime::now();
    let elapsed_time = end.duration_since(start);
    println!("Elapsed time: {:?}", elapsed_time);
    
}

 

형변환: array to image

image::RgbImage::from_raw 함수를 이용합니다.

use image::RgbImage;
use ndarray::Array3;
use std::path::PathBuf;
use video_rs::{self, Decoder, Locator};
use std::time::SystemTime;

fn array_to_image(arr: Array3<u8>) -> RgbImage {
    assert!(arr.is_standard_layout());

    let (height, width, _) = arr.dim();
    let raw = arr.into_raw_vec();

    RgbImage::from_raw(width as u32, height as u32, raw)
        .expect("container should have the right size for the image dimensions")
}


fn main(){
    video_rs::init().unwrap();
    let mut decoder = Decoder::new(&PathBuf::from("/home/yimstar9/github/ObjectTracking/data/crowd.mp4").into()).unwrap();
    //시간체크용 타이머
    let start = SystemTime::now();
    for frame in decoder.decode_iter() {
        if let Ok((_, frame)) = frame {
            let image = array_to_image(frame);
     
        } else {
            break;
        }
    }
    //시간체크용 타이머
    let end = SystemTime::now();
    let elapsed_time = end.duration_since(start);
    println!("Elapsed time: {:?}", elapsed_time);
}

 

profile

DataScience

@Ninestar

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!