我正在研究ARM,我正在尝试优化对图像的下采样,我已经使用了OpenCV cv :: resize,它的速度慢了〜3ms,用于1280 * 960到400 * 300,I&#39 ;我试图使用OpenMP来加速它,但是在放置并行for语句时,图像已经失真。我知道这与线程之间的私有变量和共享数据有关,但我无法找到问题。
void resizeBilinearGray(uint8_t *pixels, uint8_t *temp, int w, int h, int w2, int h2) {
int A, B, C, D, x, y, index, gray ;
float x_ratio = ((float)(w-1))/w2 ;
float y_ratio = ((float)(h-1))/h2 ;
float x_diff, y_diff;
int offset = 0 ;
#pragma omp parallel for
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*w+x ;
// range is 0 to 255 thus bitwise AND with 0xff
A = pixels[index] & 0xff ;
B = pixels[index+1] & 0xff ;
C = pixels[index+w] & 0xff ;
D = pixels[index+w+1] & 0xff ;
// Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
gray = (int)(
A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff)
) ;
temp[offset++] = gray ;
}
}
}
答案 0 :(得分:2)
我认为您的问题是offset
变量。由于许多线程可以同时工作,因此您永远不会知道哪个线程会首先更新偏移量。这就是生成的图像失真的原因。
更好的策略是迭代生成的图像像素。对于每个结果像素,您可以找到源图像像素的坐标,执行插值并写入结果。这样,您就可以确定每个线程都在不同的像素和右侧像素上工作。
答案 1 :(得分:2)
为什么不尝试用temp [i * w2 + j]替换temp [offset ++]?
您的偏移有多个问题。一个人有竞争条件。但更糟糕的是,OpenMP为每个线程分配了非常不同的i和j值,因此它们正在读取非相邻的内存部分。这就是你的图像失真的原因。
除了OpenMP之外,还有其他几种方法可以加速您可以尝试的代码。我不知道ARM,但在英特尔,您可以通过SSE获得大幅提升。此外,您可以尝试固定浮点。我发现双线性插值都有加速。 fastcpp.blogspot.no/2011/06/bilinear-pixel-interpolation-using-sse.html