pub struct GrayImage {
pub width: usize,
pub height: usize,
pub data: Vec<u8>,
}Expand description
Row-major 8-bit grayscale image.
Fields§
§width: usizeWidth (pixels).
height: usizeHeight (pixels).
data: Vec<u8>Row-major pixel values (length width x height).
Implementations§
Source§impl GrayImage
impl GrayImage
Sourcepub fn new(width: usize, height: usize, data: Vec<u8>) -> Result<Self>
pub fn new(width: usize, height: usize, data: Vec<u8>) -> Result<Self>
Builds from a buffer. Error if the length is not width x height.
Sourcepub fn from_f32(
width: usize,
height: usize,
f: impl Fn(usize, usize) -> f32,
) -> Self
pub fn from_f32( width: usize, height: usize, f: impl Fn(usize, usize) -> f32, ) -> Self
Builds from a [0,1] real-valued image (rounding and saturation).
Examples found in repository?
examples/bench_sift.rs (line 53)
34fn main() {
35 let args: Vec<String> = std::env::args().collect();
36 let src = args.get(1).cloned().unwrap_or_else(|| "synthetic".into());
37 let size: Option<(usize, usize)> = match (args.get(2), args.get(3)) {
38 (Some(w), Some(h)) => Some((w.parse().expect("W"), h.parse().expect("H"))),
39 _ => None,
40 };
41 let t = Instant::now();
42 let mut g = if src == "synthetic" {
43 let (w, h) = size.unwrap_or((2048, 1152));
44 let mut s = 1u64;
45 let mut noise = vec![0f32; w * h];
46 for v in noise.iter_mut() {
47 s = s.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
48 *v = (s >> 40) as f32 / (1u64 << 24) as f32;
49 }
50 let mut out = vec![0f32; w * h];
51 let mut tmp = vec![0f32; w * h];
52 sift::pyramid::gaussian_blur(&noise, &mut out, &mut tmp, w, h, 2.0);
53 GrayImage::from_f32(w, h, |x, y| (out[y * w + x] - 0.5) * 3.0 + 0.5)
54 } else {
55 read_gray(std::path::Path::new(&src)).expect("영상 읽기")
56 };
57 let t_read = t.elapsed();
58 if let Some((w, h)) = size {
59 if (w, h) != (g.width, g.height) {
60 g = g.resized(w, h);
61 }
62 }
63 println!("입력 {} ({}x{}), 읽기 {:.1} ms, 스레드 {}", src, g.width, g.height, t_read.as_secs_f64() * 1e3, rayon::current_num_threads());
64 let sift = CpuSift::new();
65 for (name, opts) in [("compat(기본)", SiftOptions::default()), ("무제한", SiftOptions { max_num_features: 0, ..Default::default() })]
66 {
67 let mut times = Vec::new();
68 let mut n = 0;
69 for _ in 0..5 {
70 let t = Instant::now();
71 let out = sift.extract(&g, &opts).expect("추출");
72 times.push(t.elapsed().as_secs_f64() * 1e3);
73 n = out.len();
74 }
75 let first = times[0];
76 let mut rest = times[1..].to_vec();
77 rest.sort_by(|a, b| a.total_cmp(b));
78 println!("{name}: 특징 {n}, 첫 실행 {first:.1} ms, 이후 중앙값 {:.1} ms", rest[rest.len() / 2]);
79 }
80}Sourcepub fn rotate_ccw(&self, k: u32) -> GrayImage
pub fn rotate_ccw(&self, k: u32) -> GrayImage
Counter-clockwise 90°xk rotation (matches the keypoint rotation transform: (x,y) -> (y, w-x)).
Sourcepub fn resized(&self, width: usize, height: usize) -> GrayImage
pub fn resized(&self, width: usize, height: usize) -> GrayImage
Resamples this image to (width, height) (Lanczos3, with anti-aliasing).
Examples found in repository?
examples/bench_sift.rs (line 60)
34fn main() {
35 let args: Vec<String> = std::env::args().collect();
36 let src = args.get(1).cloned().unwrap_or_else(|| "synthetic".into());
37 let size: Option<(usize, usize)> = match (args.get(2), args.get(3)) {
38 (Some(w), Some(h)) => Some((w.parse().expect("W"), h.parse().expect("H"))),
39 _ => None,
40 };
41 let t = Instant::now();
42 let mut g = if src == "synthetic" {
43 let (w, h) = size.unwrap_or((2048, 1152));
44 let mut s = 1u64;
45 let mut noise = vec![0f32; w * h];
46 for v in noise.iter_mut() {
47 s = s.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407);
48 *v = (s >> 40) as f32 / (1u64 << 24) as f32;
49 }
50 let mut out = vec![0f32; w * h];
51 let mut tmp = vec![0f32; w * h];
52 sift::pyramid::gaussian_blur(&noise, &mut out, &mut tmp, w, h, 2.0);
53 GrayImage::from_f32(w, h, |x, y| (out[y * w + x] - 0.5) * 3.0 + 0.5)
54 } else {
55 read_gray(std::path::Path::new(&src)).expect("영상 읽기")
56 };
57 let t_read = t.elapsed();
58 if let Some((w, h)) = size {
59 if (w, h) != (g.width, g.height) {
60 g = g.resized(w, h);
61 }
62 }
63 println!("입력 {} ({}x{}), 읽기 {:.1} ms, 스레드 {}", src, g.width, g.height, t_read.as_secs_f64() * 1e3, rayon::current_num_threads());
64 let sift = CpuSift::new();
65 for (name, opts) in [("compat(기본)", SiftOptions::default()), ("무제한", SiftOptions { max_num_features: 0, ..Default::default() })]
66 {
67 let mut times = Vec::new();
68 let mut n = 0;
69 for _ in 0..5 {
70 let t = Instant::now();
71 let out = sift.extract(&g, &opts).expect("추출");
72 times.push(t.elapsed().as_secs_f64() * 1e3);
73 n = out.len();
74 }
75 let first = times[0];
76 let mut rest = times[1..].to_vec();
77 rest.sort_by(|a, b| a.total_cmp(b));
78 println!("{name}: 특징 {n}, 첫 실행 {first:.1} ms, 이후 중앙값 {:.1} ms", rest[rest.len() / 2]);
79 }
80}Trait Implementations§
impl Eq for GrayImage
impl StructuralPartialEq for GrayImage
Auto Trait Implementations§
impl Freeze for GrayImage
impl RefUnwindSafe for GrayImage
impl Send for GrayImage
impl Sync for GrayImage
impl Unpin for GrayImage
impl UnsafeUnpin for GrayImage
impl UnwindSafe for GrayImage
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
Converts
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Scalar for T
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
The inverse inclusion map: attempts to construct
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
Checks if
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
Use with care! Same as
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
The inclusion map: converts
self to the equivalent element of its superset.