我从未使用过 OpenMP 或 C++ 优化,因此欢迎大家提供帮助。我可能正在做一些非常愚蠢的事情,这些事情会大大减慢这个过程。它不需要是最快的,但我认为一些简单的技巧会显着加快速度。任何人?非常感谢!
此函数在给定内核大小和灰度 OpenCV 图像的情况下计算补丁的标准偏差。如果补丁的中间像素低于给定阈值,则保留该像素,否则将被拒绝。这是为每个像素完成的,除了边框。
#include "stdafx.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/photo/photo.hpp"
#include <stdlib.h>
#include <stdio.h>
#include "utils.h"
#include <windows.h>
#include <string.h>
#include <math.h>
#include <numeric>
using namespace cv;
using namespace std;
Mat low_pass_filter(Mat img, int threshold, int kernelSize)
{
unsigned char *input = (unsigned char*)(img.data);
Mat output = Mat::zeros(img.size(), CV_8UC1);
unsigned char *output_ptr = (unsigned char*)(output.data);
#pragma omp parallel for
for (int i = (kernelSize - 1) / 2; i < img.rows - (kernelSize - 1) / 2; i++){
for (int j = (kernelSize - 1) / 2; j < img.cols - (kernelSize - 1) / 2; j++){
double sum, m, accum, stdev;
vector<double> v;
// Kernel Patch
for (int kx = i - (kernelSize - 1) / 2; kx <= i + (kernelSize - 1) / 2; kx++){
for (int ky = j - (kernelSize - 1) / 2; ky <= j + (kernelSize - 1) / 2; ky++){
v.push_back((double)input[img.step * kx + ky]);//.at<uchar>(kx, ky));
}
}
sum = std::accumulate(std::begin(v), std::end(v), 0.0);
m = sum / v.size();
accum = 0.0;
std::for_each(std::begin(v), std::end(v), [&](const double d) {
accum += (d - m) * (d - m);
});
stdev = sqrt(accum / (v.size() - 1));
if (stdev < threshold){
output_ptr[img.step * i + j] = input[img.step * i + j];
}
}
}
return output;
}
最佳答案
不需要 vector v。不是向其中添加项目,而是维护 d
和 d*d
的累加器,然后使用 variance = E(v²) / E(v)²这样你的内部代码就变成了:
double sum = 0;
double sum2 = 0;
int n = kernelSize * kernelSize;
// Kernel Patch
for (int kx = ...) {
for (int ky = ...) {
sum += d;
sum2 += d*d;
}
}
double mean = sum/n;
double stddev = sqrt(sum2/n - mean*mean);
if (stddev < threshold) {
...;
}
之后,考虑以 (x+1,y) 为中心的元素之和可以从 (x,y) 的结果中简单地减去前一列中的所有元素,然后将所有元素相加新右侧列中的元素。类似的操作是垂直的。
此外,请检查您的编译器选项 - 您是否自动矢量化循环并使用 SIMD 指令(如果可用)?
关于c++ - C++ OpenMP 内核的简单加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30709155/