Skip to main content

singe_npp/image/
filtering_hog.rs

1use singe_cuda::memory::DeviceMemory;
2use singe_npp_sys as sys;
3
4use crate::{
5    context::StreamContext,
6    error::{Error, Result},
7    image::view::{C1, C3, ChannelLayout, ImageView},
8    try_ffi,
9    types::{BorderType, DataTypeLike, HistogramOfGradientsConfig, Point, Size},
10    utility::to_usize,
11};
12
13use super::filtering_validation::*;
14
15pub fn histogram_of_gradients_border_buffer_size(
16    config: HistogramOfGradientsConfig,
17    locations: &[Point],
18    roi: Size,
19) -> Result<usize> {
20    validate_positive_size(roi)?;
21    let location_count = i32::try_from(locations.len()).map_err(|_| Error::OutOfRange {
22        name: "location count".into(),
23    })?;
24    let mut bytes = 0;
25    unsafe {
26        try_ffi!(sys::nppiHistogramOfGradientsBorderGetBufferSize(
27            config.into(),
28            locations.as_ptr().cast(),
29            location_count,
30            roi.into(),
31            &raw mut bytes,
32        ))?;
33    }
34    to_usize(bytes, "buffer size")
35}
36
37pub fn histogram_of_gradients_border_descriptors_size(
38    config: HistogramOfGradientsConfig,
39    location_count: usize,
40) -> Result<usize> {
41    let location_count = i32::try_from(location_count).map_err(|_| Error::OutOfRange {
42        name: "location count".into(),
43    })?;
44    let mut bytes = 0;
45    unsafe {
46        try_ffi!(sys::nppiHistogramOfGradientsBorderGetDescriptorsSize(
47            config.into(),
48            location_count,
49            &raw mut bytes,
50        ))?;
51    }
52    to_usize(bytes, "descriptors size")
53}
54
55macro_rules! impl_histogram_of_gradients_border {
56    ($name:ident, $pixel_ty:ty, $layout:ty, $ffi_name:ident) => {
57        pub fn $name(
58            stream_context: &StreamContext,
59            source: &ImageView<'_, $pixel_ty, $layout>,
60            source_offset: Point,
61            locations: &[Point],
62            descriptors: &mut DeviceMemory<f32>,
63            roi: Size,
64            config: HistogramOfGradientsConfig,
65            scratch: &mut DeviceMemory<u8>,
66            border_type: BorderType,
67        ) -> Result<()> {
68            validate_border_roi(source.size(), source_offset, roi)?;
69            let descriptor_bytes =
70                histogram_of_gradients_border_descriptors_size(config, locations.len())?;
71            if descriptors.byte_len() < descriptor_bytes {
72                return Err(Error::OutOfRange {
73                    name: "descriptors length".into(),
74                });
75            }
76            let scratch_bytes = histogram_of_gradients_border_buffer_size(config, locations, roi)?;
77            if scratch.len() < scratch_bytes {
78                return Err(Error::OutOfRange {
79                    name: "scratch length".into(),
80                });
81            }
82            let location_count = i32::try_from(locations.len()).map_err(|_| Error::OutOfRange {
83                name: "location count".into(),
84            })?;
85            unsafe {
86                try_ffi!(sys::$ffi_name(
87                    source.as_ptr().cast(),
88                    source.step(),
89                    source.size().into(),
90                    source_offset.into(),
91                    locations.as_ptr().cast(),
92                    location_count,
93                    descriptors.as_mut_ptr().cast(),
94                    roi.into(),
95                    config.into(),
96                    scratch.as_mut_ptr().cast(),
97                    border_type.into(),
98                    stream_context.as_raw(),
99                ))?;
100            }
101            Ok(())
102        }
103    };
104}
105
106impl_histogram_of_gradients_border!(
107    histogram_of_gradients_border_u8_to_f32_c1,
108    u8,
109    C1,
110    nppiHistogramOfGradientsBorder_8u32f_C1R_Ctx
111);
112impl_histogram_of_gradients_border!(
113    histogram_of_gradients_border_u8_to_f32_c3,
114    u8,
115    C3,
116    nppiHistogramOfGradientsBorder_8u32f_C3R_Ctx
117);
118impl_histogram_of_gradients_border!(
119    histogram_of_gradients_border_u16_to_f32_c1,
120    u16,
121    C1,
122    nppiHistogramOfGradientsBorder_16u32f_C1R_Ctx
123);
124impl_histogram_of_gradients_border!(
125    histogram_of_gradients_border_u16_to_f32_c3,
126    u16,
127    C3,
128    nppiHistogramOfGradientsBorder_16u32f_C3R_Ctx
129);
130impl_histogram_of_gradients_border!(
131    histogram_of_gradients_border_i16_to_f32_c1,
132    i16,
133    C1,
134    nppiHistogramOfGradientsBorder_16s32f_C1R_Ctx
135);
136impl_histogram_of_gradients_border!(
137    histogram_of_gradients_border_i16_to_f32_c3,
138    i16,
139    C3,
140    nppiHistogramOfGradientsBorder_16s32f_C3R_Ctx
141);
142impl_histogram_of_gradients_border!(
143    histogram_of_gradients_border_f32_c1,
144    f32,
145    C1,
146    nppiHistogramOfGradientsBorder_32f_C1R_Ctx
147);
148impl_histogram_of_gradients_border!(
149    histogram_of_gradients_border_f32_c3,
150    f32,
151    C3,
152    nppiHistogramOfGradientsBorder_32f_C3R_Ctx
153);
154
155pub trait HistogramOfGradientsBorder<L: ChannelLayout>: DataTypeLike {
156    fn histogram_of_gradients_border(
157        stream_context: &StreamContext,
158        source: &ImageView<'_, Self, L>,
159        source_offset: Point,
160        locations: &[Point],
161        descriptors: &mut DeviceMemory<f32>,
162        roi: Size,
163        config: HistogramOfGradientsConfig,
164        scratch: &mut DeviceMemory<u8>,
165        border_type: BorderType,
166    ) -> Result<()>;
167}
168
169macro_rules! impl_histogram_of_gradients_border_dispatch {
170    ($pixel_ty:ty, $layout:ty, $name:ident) => {
171        impl HistogramOfGradientsBorder<$layout> for $pixel_ty {
172            fn histogram_of_gradients_border(
173                stream_context: &StreamContext,
174                source: &ImageView<'_, Self, $layout>,
175                source_offset: Point,
176                locations: &[Point],
177                descriptors: &mut DeviceMemory<f32>,
178                roi: Size,
179                config: HistogramOfGradientsConfig,
180                scratch: &mut DeviceMemory<u8>,
181                border_type: BorderType,
182            ) -> Result<()> {
183                $name(
184                    stream_context,
185                    source,
186                    source_offset,
187                    locations,
188                    descriptors,
189                    roi,
190                    config,
191                    scratch,
192                    border_type,
193                )
194            }
195        }
196    };
197}
198
199impl_histogram_of_gradients_border_dispatch!(u8, C1, histogram_of_gradients_border_u8_to_f32_c1);
200impl_histogram_of_gradients_border_dispatch!(u8, C3, histogram_of_gradients_border_u8_to_f32_c3);
201impl_histogram_of_gradients_border_dispatch!(u16, C1, histogram_of_gradients_border_u16_to_f32_c1);
202impl_histogram_of_gradients_border_dispatch!(u16, C3, histogram_of_gradients_border_u16_to_f32_c3);
203impl_histogram_of_gradients_border_dispatch!(i16, C1, histogram_of_gradients_border_i16_to_f32_c1);
204impl_histogram_of_gradients_border_dispatch!(i16, C3, histogram_of_gradients_border_i16_to_f32_c3);
205impl_histogram_of_gradients_border_dispatch!(f32, C1, histogram_of_gradients_border_f32_c1);
206impl_histogram_of_gradients_border_dispatch!(f32, C3, histogram_of_gradients_border_f32_c3);
207
208pub fn histogram_of_gradients_border<T, L>(
209    stream_context: &StreamContext,
210    source: &ImageView<'_, T, L>,
211    source_offset: Point,
212    locations: &[Point],
213    descriptors: &mut DeviceMemory<f32>,
214    roi: Size,
215    config: HistogramOfGradientsConfig,
216    scratch: &mut DeviceMemory<u8>,
217    border_type: BorderType,
218) -> Result<()>
219where
220    T: HistogramOfGradientsBorder<L>,
221    L: ChannelLayout,
222{
223    T::histogram_of_gradients_border(
224        stream_context,
225        source,
226        source_offset,
227        locations,
228        descriptors,
229        roi,
230        config,
231        scratch,
232        border_type,
233    )
234}