Эффективно суммируйте окрестности каждого элемента матрицы - PullRequest
0 голосов
/ 15 октября 2018

Я запрограммировал кусок кода, где у меня есть огромная трехмерная матрица на C ++, используя boost :: multi_array.

Для каждого элемента матрицы я хочу суммировать окрестности на определенном расстоянии dist.Каждый элемент взвешивается в соответствии с его расстоянием до центра.Центральный элемент не должен быть включен в сумму.

Расстояние dist задается пользователем и может варьироваться.Моя программа делает правильные вычисления, но медленная, когда матрица становится большой.Иногда у меня есть матрицы с более чем 100000 элементов ...

Так что мой вопрос: есть ли способ сделать это вычисление быстрее?Может также использовать другую библиотеку?

Часть состоит в основном из двух функций.В первой функции я получаю доступ к каждому элементу матрицы и вычисляю сумму окрестности.InputMatrix - это трехмерный бустерный мультимассив:

boost::multi_array<float, 3> inputMatrix = imageMatrix;
T actualElement;
int posActualElement;
for (int depth = 0; depth<inputMatrix.shape()[2]; depth++) {
    for (int row = 0; row<inputMatrix.shape()[0]; row++) {
        for (int col = 0; col<inputMatrix.shape()[1]; col++) {

            indexOfElement[0] = row;
            indexOfElement[1] = col;
            indexOfElement[2] = depth;
            //get actual Element if it is the centre of a whole neighborhood
            actualElement = inputMatrix[row][col][depth];
            if (!std::isnan(actualElement)) {
                //get the sum of the actual neighborhood
                sumOfActualNeighborhood = getNeighborhood3D(inputMatrix, indexOfElement);
      }
    }
  }
}

Функция окрестность3D выглядит следующим образом:

template <class T, size_t R>
T NGTDMFeatures3D<T, R>::getNeighborhood3D(boost::multi_array<T, R> inputMatrix, int *indexOfElement) {
    std::vector<T> neighborhood;
    T actElement;
    float weight;
    for (int k = -dist; k<dist + 1; k++) {
        for (int i = -dist; i<dist + 1; i++) {
            for (int j = -dist; j<dist + 1; j++) {

                if (i != 0 || j != 0 || k != 0) {
                    if (indexOfElement[0] + i>-1 && indexOfElement[0] + i<inputMatrix.shape()[0] && indexOfElement[1] + j>-1 && indexOfElement[1] + j<inputMatrix.shape()[1] && indexOfElement[2] + k>-1 && indexOfElement[2] + k<inputMatrix.shape()[2]) {
                        actElement = inputMatrix[indexOfElement[0] + i][indexOfElement[1] + j][indexOfElement[2] + k];
                        if (!std::isnan(actElement)) {
                            weight = calculateWeight3D(i, j, k, normNGTDM, actualSpacing);
                            neighborhood.push_back(weight*actElement);
                        }
                    }
                }
            }
        }
    }
    T sum = accumulate(neighborhood.begin(), neighborhood.end(), 0);
    sum = sum / neighborhood.size();
    return sum;
}
...