|
6 | 6 | #define PARTPLAY_GRADIENT_HPP |
7 | 7 |
|
8 | 8 | #include "src/data_structures/Mesh/MeshData.hpp" |
| 9 | +#include "src/io/TiffUtils.hpp" |
| 10 | + |
9 | 11 | #ifdef HAVE_OPENMP |
10 | 12 | #include "omp.h" |
11 | 13 | #endif |
@@ -49,9 +51,9 @@ class ComputeGradient { |
49 | 51 |
|
50 | 52 | // Gradient computation |
51 | 53 |
|
52 | | - template<typename T, typename S> |
| 54 | + template<typename S> |
53 | 55 | void |
54 | | - calc_bspline_fd_ds_mag(MeshData<T> &input, MeshData<S> &grad, const float hx, const float hy, const float hz); |
| 56 | + calc_bspline_fd_ds_mag(const MeshData<S> &input, MeshData<S> &grad, const float hx, const float hy, const float hz); |
55 | 57 |
|
56 | 58 | template<typename T,typename S> |
57 | 59 | void mask_gradient(MeshData<T>& grad_ds,MeshData<S>& temp_ds,MeshData<T>& temp_full,APRParameters& par); |
@@ -719,74 +721,85 @@ void ComputeGradient::get_smooth_bspline_3D(MeshData<T>& input,APRParameters& pa |
719 | 721 | spline_timer.stop_timer(); |
720 | 722 | } |
721 | 723 |
|
722 | | -template<typename T,typename S> |
723 | | -void ComputeGradient::calc_bspline_fd_ds_mag(MeshData<T> &input, MeshData<S> &grad, const float hx, const float hy,const float hz){ |
724 | | - // |
725 | | - // Bevan Cheeseman 2016 |
726 | | - // |
727 | | - // Calculate fd filt, for xgrad with bsplines |
728 | | - |
| 724 | +/** |
| 725 | + * Calculates downsampled gradient (maximum magnitude) with 'replicate' boundary approach (nearest border value) |
| 726 | + * @param input - input mesh |
| 727 | + * @param grad - output gradient (must be initialized) |
| 728 | + * @param hx - step in x dir |
| 729 | + * @param hy - step in y dir |
| 730 | + * @param hz - step in z dir |
| 731 | + */ |
| 732 | +template<typename S> |
| 733 | +void ComputeGradient::calc_bspline_fd_ds_mag(const MeshData<S> &input, MeshData<S> &grad, const float hx, const float hy,const float hz) { |
729 | 734 | const size_t z_num = input.z_num; |
730 | 735 | const size_t x_num = input.x_num; |
731 | 736 | const size_t y_num = input.y_num; |
732 | 737 |
|
733 | 738 | const size_t x_num_ds = grad.x_num; |
734 | 739 | const size_t y_num_ds = grad.y_num; |
735 | 740 |
|
736 | | - const float a1 = -1.0/2.0; |
737 | | - const float a3 = 1.0/2.0; |
738 | | - |
739 | | - std::vector<S> temp(y_num,0); |
| 741 | + std::vector<S> temp(y_num, 0); |
740 | 742 | const size_t xnumynum = x_num * y_num; |
741 | 743 |
|
742 | 744 | #ifdef HAVE_OPENMP |
743 | | - #pragma omp parallel for default(shared)firstprivate(temp) |
| 745 | + #pragma omp parallel for default(shared) firstprivate(temp) |
744 | 746 | #endif |
745 | | - for (size_t j = 0;j < z_num; ++j) { |
746 | | - S *temp_vec_1 = input.mesh.begin() + j*x_num*y_num + 1*y_num; |
747 | | - S *temp_vec_2 = input.mesh.begin() + j*x_num*y_num; |
| 747 | + for (size_t z = 0; z < z_num; ++z) { |
| 748 | + // Belows pointers up, down... are forming stencil in X (left <-> right) and Z ( up <-> down) direction and |
| 749 | + // are pointing to whole Y column. If out of bounds then 'replicate' (nearest array border value) approach is used. |
| 750 | + // |
| 751 | + // up |
| 752 | + // ... left center right ... |
| 753 | + // down |
| 754 | + const S *left = input.mesh.begin() + z * xnumynum + 0 * y_num; // boundary value is chosen |
| 755 | + const S *center = input.mesh.begin() + z * xnumynum + 0 * y_num; |
748 | 756 |
|
749 | 757 | //LHS boundary condition is accounted for wiht this initialization |
750 | | - const size_t j_m = j > 0 ? j - 1 : 0; |
751 | | - const size_t j_p = std::min(z_num-1, j+1); |
| 758 | + const size_t zMinus = z > 0 ? z - 1 : 0 /* boundary */; |
| 759 | + const size_t zPlus = std::min(z + 1, z_num - 1 /* boundary */); |
752 | 760 |
|
753 | | - for (size_t i = 0; i < x_num-1; ++i) { |
754 | | - S *temp_vec_4 = input.mesh.begin() + j_m*xnumynum + i * y_num; |
755 | | - S *temp_vec_5 = input.mesh.begin() + j_p*xnumynum + i * y_num; |
756 | | - S *temp_vec_3 = input.mesh.begin() + j*x_num*y_num + (i+1)*y_num; |
| 761 | + for (size_t x = 0; x < x_num; ++x) { |
| 762 | + const S *up = input.mesh.begin() + zMinus * xnumynum + x * y_num; |
| 763 | + const S *down = input.mesh.begin() + zPlus * xnumynum + x * y_num; |
| 764 | + const size_t xPlus = std::min(x + 1, x_num - 1 /* boundary */); |
| 765 | + const S *right = input.mesh.begin() + z * xnumynum + xPlus * y_num; |
757 | 766 |
|
758 | 767 | //compute the boundary values |
759 | | - temp[0] = sqrt(pow((a1*temp_vec_1[0] + a3*temp_vec_3[0])/hx,2.0) + pow((a1*temp_vec_4[0] + a3*temp_vec_5[0])/hz,2.0)); |
| 768 | + if (y_num >= 2) { |
| 769 | + temp[0] = sqrt(pow((right[0] - left[0]) / (2 * hx), 2.0) + pow((down[0] - up[0]) / (2 * hz), 2.0) + pow((center[1] - center[0 /* boundary */]) / (2 * hy), 2.0)); |
| 770 | + temp[y_num - 1] = sqrt(pow((right[y_num - 1] - left[y_num - 1]) / (2 * hx), 2.0) + pow((down[y_num - 1] - up[y_num - 1]) / (2 * hz), 2.0) + pow((center[y_num - 1 /* boundary */] - center[y_num - 2]) / (2 * hy), 2.0)); |
| 771 | + } |
| 772 | + else { |
| 773 | + temp[0] = 0; // same values minus same values in x/y/z |
| 774 | + } |
760 | 775 |
|
761 | | - //do the y gradient |
| 776 | + //do the y gradient in range 1..y_num-2 |
762 | 777 | #ifdef HAVE_OPENMP |
763 | | - #pragma omp simd |
| 778 | + #pragma omp simd |
764 | 779 | #endif |
765 | | - for (size_t k = 1; k < (y_num-1); ++k) { |
766 | | - temp[k] = sqrt(pow((a1*temp_vec_4[k] + a3*temp_vec_5[k])/hz,2.0) + pow((a1*temp_vec_2[k-1] + a3*temp_vec_2[k+1])/hy,2.0) + pow((a1*temp_vec_1[k] + a3*temp_vec_3[k])/hx,2.0)); |
| 780 | + for (size_t y = 1; y < y_num - 1; ++y) { |
| 781 | + temp[y] = sqrt(pow((right[y] - left[y]) / (2 * hx), 2.0) + pow((down[y] - up[y]) / (2 * hz), 2.0) + pow((center[y + 1] - center[y - 1]) / (2 * hy), 2.0)); |
767 | 782 | } |
768 | 783 |
|
769 | | - temp[y_num - 1] = sqrt(pow((a1*temp_vec_1[(y_num-1)] + a3*temp_vec_3[(y_num-1)])/hx,2.0) + pow((a1*temp_vec_4[(y_num-1)] + a3*temp_vec_5[(y_num-1)])/hz,2.0)); |
770 | | - |
771 | | - int64_t j_2 = j/2; |
772 | | - int64_t i_2 = i/2; |
773 | | - |
774 | | - for (size_t k = 0; k < (y_num_ds); ++k) { |
775 | | - size_t k_s = std::min(2*k+1, y_num-1); |
776 | | - const size_t idx = j_2 * x_num_ds * y_num_ds + i_2 * y_num_ds + k; |
| 784 | + // Set as a downsampled gradient maximum from 2x2x2 gradient cubes |
| 785 | + int64_t z_2 = z / 2; |
| 786 | + int64_t x_2 = x / 2; |
| 787 | + for (size_t k = 0; k < y_num_ds; ++k) { |
| 788 | + size_t k_s = std::min(2 * k + 1, y_num - 1); |
| 789 | + const size_t idx = z_2 * x_num_ds * y_num_ds + x_2 * y_num_ds + k; |
777 | 790 | grad.mesh[idx] = std::max(temp[2 * k], std::max(temp[k_s], grad.mesh[idx])); |
778 | 791 | } |
779 | 792 |
|
780 | | - std::swap(temp_vec_1, temp_vec_2); |
781 | | - std::swap(temp_vec_2, temp_vec_3); |
| 793 | + // move left, center to current center, right (both +1 to right) |
| 794 | + std::swap(left, center); |
| 795 | + std::swap(center, right); |
782 | 796 | } |
783 | 797 | } |
784 | 798 | } |
785 | 799 |
|
786 | | -/* |
| 800 | +/** |
787 | 801 | * Caclulation of signal value from B-Spline co-efficients |
788 | 802 | */ |
789 | | - |
790 | 803 | template<typename T> |
791 | 804 | void ComputeGradient::calc_inv_bspline_y(MeshData<T>& input){ |
792 | 805 | // |
|
0 commit comments