cyr*_*iel 6 c++ opencv image-processing while-loop halide
我正在尝试在Halide中实现Meijster距离变换算法.我已经将此代码重写为C++(使用openCV)并且它工作正常.关于这个算法的论文就在这里.现在我的卤化物代码已完成50% - 第一阶段工作正常,现在我遇到了阶段2(链接代码中的扫描3)的问题,其中(简化)看起来像这样:
//g is 2 dimensional cv::Mat (something like array) - result of previous stage
// m is g.width and n is g.height
int(*functionF)(int x, int i, int g_i) = EDT_f;
int(*functionSep)(int i, int u, int g_i, int g_u, int max_value) = EDT_Sep;
cv::Mat dt = cv::Mat(n, m, CV_32SC1);
int* s = new int[m];
int* t = new int[m];
int q = 0, w;
for (int y = 0; y<n; y++)
{
q = 0;
s[0] = 0;
t[0] = 0;
// Scan 3
for (int u = 1; u<m; u++)
{
//how can i replace this loop:
while (q >= 0 && functionF(t[q], s[q], g.at<int>(y, s[q])) > functionF(t[q], u, g.at<int>(y, u)))
q--;
//some operations which might change value of q, s[] and t[]
}
// Scan 4 - not important here
}
Run Code Online (Sandbox Code Playgroud)
是否有任何卤素友好的方式来取代这个循环?现在我到目前为止唯一的解决方案是这样的东西(尚未测试):
Expr calculateQ(Expr currentQValue, Expr y, Func t, Func s, Func g)
{
//while (q >= 0 && functionF(t[q], s[q], g.at<int>(y, s[q])) > functionF(t[q], u, g.at<int>(y, u)))
//q--;
return select(currentQValue >= 0 && functionF(t[q], s[q], g[s[q], y]) > functionF(t[q], u, g[u, y]), calculateQ(currentQValue - 1, y, t, s, g), currentQValue);
}
Run Code Online (Sandbox Code Playgroud)
但即使这样可行,最有可能的卤化物会在检查条件之前尝试评估select的两个值,而递归会使它非常慢.
如果没有办法实现Halide中的while循环有什么方法可以在Halide中使用你的代码的某些部分?还有其他想法吗?
您应该注意到,如何表达一个动态终止的(while)循环并不太明显-现在还无法用纯Halide来表达!这可能会在(不确定的,长期的)将来发生变化,但是添加这些会使循环的Halide程序图灵完成;没有它们,我们总是可以分析循环的边界,但是如果遇到它们,我们将面临停顿的问题。
但是,对于此类事情有一个逃生舱门:您可以从Halide管道内部调用外部函数(用C或其他任何方式实现)。extern函数的接口看起来与编译管道的接口相同(它采用标量和缓冲区参数,最终缓冲区为输出,如果使用空缓冲区调用,则必须在给定边界的情况下计算其输入所需的边界要求其输出)。查看extern_*测试程序中的一些示例,例如https://github.com/halide/Halide/blob/master/test/correctness/extern_stage.cpp。快速浏览一下您的代码,我相信它应该可以使用现有的C代码在外部阶段轻松实现。