forked from twistedfall/opencv-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hfs.rs
280 lines (258 loc) · 11.9 KB
/
hfs.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
pub mod hfs {
//! # Hierarchical Feature Selection for Efficient Image Segmentation
//!
//! The opencv hfs module contains an efficient algorithm to segment an image.
//! This module is implemented based on the paper Hierarchical Feature Selection for Efficient
//! Image Segmentation, ECCV 2016. The original project was developed by
//! Yun Liu(<https://github.com/yun-liu/hfs>).
//!
//!
//! Introduction to Hierarchical Feature Selection
//! ----------------------------------------------
//!
//!
//! This algorithm is executed in 3 stages:
//!
//! In the first stage, the algorithm uses SLIC (simple linear iterative clustering) algorithm
//! to obtain the superpixel of the input image.
//!
//! In the second stage, the algorithm view each superpixel as a node in the graph.
//! It will calculate a feature vector for each edge of the graph. It then calculates a weight
//! for each edge based on the feature vector and trained SVM parameters. After obtaining
//! weight for each edge, it will exploit EGB (Efficient Graph-based Image Segmentation)
//! algorithm to merge some nodes in the graph thus obtaining a coarser segmentation
//! After these operations, a post process will be executed to merge regions that are smaller
//! then a specific number of pixels into their nearby region.
//!
//! In the third stage, the algorithm exploits the similar mechanism to further merge
//! the small regions obtained in the second stage into even coarser segmentation.
//!
//! After these three stages, we can obtain the final segmentation of the image.
//! For further details about the algorithm, please refer to the original paper:
//! Hierarchical Feature Selection for Efficient Image Segmentation, ECCV 2016
use crate::{mod_prelude::*, core, sys, types};
pub mod prelude {
pub use { super::HfsSegmentConst, super::HfsSegment };
}
/// Constant methods for [crate::hfs::HfsSegment]
pub trait HfsSegmentConst: core::AlgorithmTraitConst {
fn as_raw_HfsSegment(&self) -> *const c_void;
}
pub trait HfsSegment: core::AlgorithmTrait + crate::hfs::HfsSegmentConst {
fn as_raw_mut_HfsSegment(&mut self) -> *mut c_void;
/// set and get the parameter segEgbThresholdI.
/// This parameter is used in the second stage mentioned above.
/// It is a constant used to threshold weights of the edge when merging
/// adjacent nodes when applying EGB algorithm. The segmentation result
/// tends to have more regions remained if this value is large and vice versa.
#[inline]
fn set_seg_egb_threshold_i(&mut self, c: f32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setSegEgbThresholdI_float(self.as_raw_mut_HfsSegment(), c, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_seg_egb_threshold_i(&mut self) -> Result<f32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getSegEgbThresholdI(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// set and get the parameter minRegionSizeI.
/// This parameter is used in the second stage
/// mentioned above. After the EGB segmentation, regions that have fewer
/// pixels then this parameter will be merged into it's adjacent region.
#[inline]
fn set_min_region_size_i(&mut self, n: i32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setMinRegionSizeI_int(self.as_raw_mut_HfsSegment(), n, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_min_region_size_i(&mut self) -> Result<i32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getMinRegionSizeI(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// set and get the parameter segEgbThresholdII.
/// This parameter is used in the third stage
/// mentioned above. It serves the same purpose as segEgbThresholdI.
/// The segmentation result tends to have more regions remained if
/// this value is large and vice versa.
#[inline]
fn set_seg_egb_threshold_ii(&mut self, c: f32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setSegEgbThresholdII_float(self.as_raw_mut_HfsSegment(), c, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_seg_egb_threshold_ii(&mut self) -> Result<f32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getSegEgbThresholdII(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// set and get the parameter minRegionSizeII.
/// This parameter is used in the third stage
/// mentioned above. It serves the same purpose as minRegionSizeI
#[inline]
fn set_min_region_size_ii(&mut self, n: i32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setMinRegionSizeII_int(self.as_raw_mut_HfsSegment(), n, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_min_region_size_ii(&mut self) -> Result<i32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getMinRegionSizeII(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// set and get the parameter spatialWeight.
/// This parameter is used in the first stage
/// mentioned above(the SLIC stage). It describes how important is the role
/// of position when calculating the distance between each pixel and it's
/// center. The exact formula to calculate the distance is
/// ![inline formula](https://latex.codecogs.com/png.latex?colorDistance%20%2B%20spatialWeight%20%5Ctimes%20spatialDistance).
/// The segmentation result tends to have more local consistency
/// if this value is larger.
#[inline]
fn set_spatial_weight(&mut self, w: f32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setSpatialWeight_float(self.as_raw_mut_HfsSegment(), w, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_spatial_weight(&mut self) -> Result<f32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getSpatialWeight(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// set and get the parameter slicSpixelSize.
/// This parameter is used in the first stage mentioned
/// above(the SLIC stage). It describes the size of each
/// superpixel when initializing SLIC. Every superpixel
/// approximately has ![inline formula](https://latex.codecogs.com/png.latex?slicSpixelSize%20%5Ctimes%20slicSpixelSize)
/// pixels in the beginning.
#[inline]
fn set_slic_spixel_size(&mut self, n: i32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setSlicSpixelSize_int(self.as_raw_mut_HfsSegment(), n, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_slic_spixel_size(&mut self) -> Result<i32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getSlicSpixelSize(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// set and get the parameter numSlicIter.
/// This parameter is used in the first stage. It
/// describes how many iteration to perform when executing SLIC.
#[inline]
fn set_num_slic_iter(&mut self, n: i32) -> Result<()> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_setNumSlicIter_int(self.as_raw_mut_HfsSegment(), n, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
#[inline]
fn get_num_slic_iter(&mut self) -> Result<i32> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_getNumSlicIter(self.as_raw_mut_HfsSegment(), ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
Ok(ret)
}
/// do segmentation gpu
/// ## Parameters
/// * src: : the input image
/// * ifDraw: : if draw the image in the returned Mat. if this parameter is false,
/// then the content of the returned Mat is a matrix of index, describing the region
/// each pixel belongs to. And it's data type is CV_16U. If this parameter is true,
/// then the returned Mat is a segmented picture, and color of each region is the
/// average color of all pixels in that region. And it's data type is the same as
/// the input image
///
/// ## C++ default parameters
/// * if_draw: true
#[inline]
fn perform_segment_gpu(&mut self, src: &dyn core::ToInputArray, if_draw: bool) -> Result<core::Mat> {
extern_container_arg!(src);
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_performSegmentGpu_const__InputArrayR_bool(self.as_raw_mut_HfsSegment(), src.as_raw__InputArray(), if_draw, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
let ret = unsafe { core::Mat::opencv_from_extern(ret) };
Ok(ret)
}
/// do segmentation with cpu
/// This method is only implemented for reference.
/// It is highly NOT recommanded to use it.
///
/// ## C++ default parameters
/// * if_draw: true
#[inline]
fn perform_segment_cpu(&mut self, src: &dyn core::ToInputArray, if_draw: bool) -> Result<core::Mat> {
extern_container_arg!(src);
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_performSegmentCpu_const__InputArrayR_bool(self.as_raw_mut_HfsSegment(), src.as_raw__InputArray(), if_draw, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
let ret = unsafe { core::Mat::opencv_from_extern(ret) };
Ok(ret)
}
}
impl dyn HfsSegment + '_ {
/// create a hfs object
/// ## Parameters
/// * height: : the height of the input image
/// * width: : the width of the input image
/// * segEgbThresholdI: : parameter segEgbThresholdI
/// * minRegionSizeI: : parameter minRegionSizeI
/// * segEgbThresholdII: : parameter segEgbThresholdII
/// * minRegionSizeII: : parameter minRegionSizeII
/// * spatialWeight: : parameter spatialWeight
/// * slicSpixelSize: : parameter slicSpixelSize
/// * numSlicIter: : parameter numSlicIter
///
/// ## C++ default parameters
/// * seg_egb_threshold_i: 0.08f
/// * min_region_size_i: 100
/// * seg_egb_threshold_ii: 0.28f
/// * min_region_size_ii: 200
/// * spatial_weight: 0.6f
/// * slic_spixel_size: 8
/// * num_slic_iter: 5
#[inline]
pub fn create(height: i32, width: i32, seg_egb_threshold_i: f32, min_region_size_i: i32, seg_egb_threshold_ii: f32, min_region_size_ii: i32, spatial_weight: f32, slic_spixel_size: i32, num_slic_iter: i32) -> Result<core::Ptr<dyn crate::hfs::HfsSegment>> {
return_send!(via ocvrs_return);
unsafe { sys::cv_hfs_HfsSegment_create_int_int_float_int_float_int_float_int_int(height, width, seg_egb_threshold_i, min_region_size_i, seg_egb_threshold_ii, min_region_size_ii, spatial_weight, slic_spixel_size, num_slic_iter, ocvrs_return.as_mut_ptr()) };
return_receive!(unsafe ocvrs_return => ret);
let ret = ret.into_result()?;
let ret = unsafe { core::Ptr::<dyn crate::hfs::HfsSegment>::opencv_from_extern(ret) };
Ok(ret)
}
}}