Skip to content

Instantly share code, notes, and snippets.

@Pzixel
Created January 25, 2018 10:48
Show Gist options
  • Save Pzixel/1fd6afc1cbb5e9473f75fe1541f17ecc to your computer and use it in GitHub Desktop.
Save Pzixel/1fd6afc1cbb5e9473f75fe1541f17ecc to your computer and use it in GitHub Desktop.
Rust OpenCV interop
template<typename T>
struct CResult
{
T value;
const char* error;
static CResult<T> FromFunction(std::function<T()> function)
{
CResult<T> result = {};
try
{
result.value = function();
}
catch( cv::Exception& e )
{
const char* err_msg = e.what();
auto len = std::strlen(err_msg);
auto retained_err = new char[len + 1];
std::strcpy(retained_err, err_msg);
result.error = retained_err;
}
return result;
}
};
EXTERN_C_BEGIN
void c_drop(void* value)
{
free(value);
value = nullptr;
}
CResult<double> cv_compare_hist(CvMatrix* first_image, CvMatrix* second_image, int method) {
cv::Mat* first_mat = reinterpret_cast<cv::Mat*>(first_image);
cv::Mat* second_mat = reinterpret_cast<cv::Mat*>(second_image);
auto result = CResult<double>::FromFunction([first_mat, second_mat, method](){
return cv::compareHist(*first_mat, *second_mat, method);
});
return result;
}
EXTERN_C_END
extern "C" {
fn c_drop(value: *mut c_void);
}
#[repr(C)]
struct CResult<T: Copy> {
value: T,
error: *const c_char
}
impl<T: Copy> Into<Result<T, Cow<'static, str>>> for CResult<T> {
fn into(self) -> Result<T, Cow<'static, str>> {
if self.error.is_null() {
Ok(self.value)
}
else {
unsafe {
let c_str = std::ffi::CStr::from_ptr(self.error);
let err = match c_str.to_str() {
Ok(message) => message.into(),
_ => "Unknown error".into()
};
Err(err)
}
}
}
}
impl<T: Copy> Drop for CResult<T> {
fn drop(&mut self) {
if !self.error.is_null() {
unsafe { c_drop(self.error as *mut c_void)}
}
}
}
struct Cv {}
impl Cv {
/// Compares two histograms.
/// The function compare two histograms using the specified method.
/// The function returns d(first_image, second_image).
/// While the function works well with 1-, 2-, 3-dimensional dense histograms, it may not be
/// suitable for high-dimensional sparse histograms.
/// In such histograms, because of aliasing and sampling problems,
/// the coordinates of non-zero histogram bins can slightly shift.
/// To compare such histograms or more general sparse configurations of weighted points,
/// consider using the cv::EMD function.
pub fn compare_hist(first_image: &Mat, second_image: &Mat, method: HistogramComparisionMethod) -> Result<f64, Cow<'static, str>> {
let method: c_int = method.to_i64().unwrap() as i32;
let result = unsafe {
cv_compare_hist(first_image.inner, second_image.inner, method)
};
result.into()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment