c++ - C++ OpenMP 内核的简单加速

标签 c++ opencv openmp

我从未使用过 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。不是向其中添加项目,而是维护 dd*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/

相关文章:

python-3.x - 不能将 OpenCV GeneralizedHoughTransform 类与 Python 一起使用

gcc - OpenMP 并行区域中嵌套函数的内部编译器错误

c++ - 寻找 map 技术

c++ - 从控制台模拟按钮单击到 UI 类

c++ - 查找显示链表的错误

opencv - 我运行 ffmpeg 时的问题

image-processing - 有没有办法检测图像是否模糊?

C++错误: declaration of ‘~Destructor’ as member of ‘Class’

c++ - 我可以通过整数索引访问 C++ std::map 中的元素吗?

c++ - OMP 目标中对全局数组(malloc 与静态)的不同处理