2016-10-13 6 views
1

Моя цель - смоделировать зависящий от сигнала гауссов шум в галиде. У меня есть модель, построенная в OpenCV, которую я теперь переношу на Halide. Проблема состоит в том, что генератор случайных чисел Halide обычно не распределяется, поэтому мне нужно использовать внешнюю функцию для получения значений шума.Как использовать случайную функцию C++ в Halide?

В попытке реализации используется генератор случайных чисел C++ для создания нормально распределенного шума, Halide Func для получения стандартных отклонений шума от каждого пикселя, зависящего от сигнала, а затем шум добавляется к пикселам в режиме реноизма. Ниже я показываю компоновку функций.

// Note: This is an implementation of the noise model found in the paper below: 
// "Noise measurement for raw-data of digital imaging sensors by 
// automatic segmentation of non-uniform targets" 
float get_normal_dist_rand(float mean, float std_dev) { 
    std::default_random_engine generator; 
    std::normal_distribution<float> distribution(mean,std_dev); 
    float out = distribution(generator); 
    return out; 
} 

Func make_get_std_dev(Func *in_func) { 
    Var x, y, c; 
    float q = 0.0060; 
    float p = 0.0500; 
    // std_dev = q * sqrt(unnoised_pixel - p) 
    Func get_std_dev("get_std_dev"); 
    get_std_dev(x,y,c) = q * sqrt((*in_func)(x,y,c) - p); 
    return get_std_dev; 
} 

Func make_renoise(Func *in_func, Func *std_dev) { 
    Var x, y, c; 
    // Noise parameters 
    // noised_pixel = unnoised_pixel + 
    //     gaussian_rand(std_dev = q * sqrt(unnoised_pixel - p)) 
    // q and p values do not vary between channels 
    Func renoise("renoise"); 
    renoise(x,y,c) = (*in_func)(x,y,c) + 
         get_normal_dist_rand(0,(*std_dev)(x,y,c)); 
    return renoise; 
} 

Это имеет смысл для меня, но, к сожалению я получаю следующее сообщение об ошибке при попытке компиляции:

../common/pipe_stages.cpp: In function 'Halide::Func make_renoise(Halide::Func*, Halide::Func*)': 
../common/pipe_stages.cpp:223:64: error: cannot convert 'std::enable_if<true, Halide::FuncRef>::type {aka Halide::FuncRef}' to 'float' for argument '2' to 'float get_normal_dist_rand(float, float)' 
         get_normal_dist_rand(0,(*std_dev)(x,y,c)); 
                   ^

Таким образом, кажется, что выход из Func не может быть предоставлена ​​функция C++. Я предполагаю, что это имеет смысл как ограничение Halide, но я действительно не вижу альтернативы для реализации зависимого от сигнала нормально распределенного шума. Есть ли другой способ использовать внешние функции C++ в Halide? Я видел, как люди говорили об использовании «extern», но, к сожалению, документация по этой функции кажется довольно легкой, и я не могу найти то, что мне нужно.

+0

Кроме того, не стесняйтесь записывать проблемы со встроенной случайной поддержкой, не предоставляя необходимую вам функциональность. Я сейчас спешу, поэтому я не уверен, что здесь правильный ответ, но похоже, что это должно быть проще. –

ответ

2

Вам понадобится использовать один из наших внешних механизмов для привязки к коду C++. HalideExtern_ * является более простым из двух и позволит вам позвонить, чтобы получить случайные числа по одному за раз. Увы, тест/правильность/c_function.cpp - непосредственный пример этого, который поможет, но может быть более ясным.

Я ожидаю, что вы захотите запросить буфер случайных чисел за раз по соображениям эффективности. Это можно сделать с помощью механизма define_extern. Функция C++ должна участвовать в выводах границ, поэтому она немного больше задействована. Тест для этого - это правильность/extern_producer.cpp.

Я ожидаю, что либо преобразование наших случайных чисел будет соответствующим образом распределено, либо реализация алгоритма генерации случайных чисел в Halide - это правильный путь для действительно быстрого производственного кода, но это, скорее всего, больше работы, чем вы хотите сделать сначала выполните эту работу.

1

Вы также можете использовать ГСЧ галогенид наряду с биномиального приближения к гауссовой:

Expr gaussian_random(Expr sigma) { 
    return (random_float() + random_float() + random_float() - 1.5f) * 2 * sigma; 
} 

Добавить несколько экземпляров randomFloat, чтобы стать ближе и ближе к истинному нормальному распределению.

Смежные вопросы