Vector<T> IM_Solver::Gauss_Seidel_Iteration(const Base_Matrix<T>& A, const Vector<T>& b, Vector<T>& XO, const T TOL, const unsigned int Limit) { unsigned int k = 1, n = b.getSize(); Vector<T> x(n); if(A.numCols() != n || A.numRows() != n || XO.getSize() != n) throw Incompatible_Vector_Err(); while(k <= Limit) { for(unsigned int i = 0; i < n; i++) { T sum = 0; for(unsigned int j = 0; j < n; j++) { if(j < i) { sum += -A(i,j)*x[j]; } else if(j > i) { sum += -A(i,j)*XO[j]; } } x[i] = (sum+b[i])/A(i,i); } if(L2_norm(x-XO) < TOL) { return x; } k++; XO = x; } return Vector<T>(0); }
//Main function void *Sub_denoise_mt(void *arguments) { nl_mean_mt arg; arg=*(nl_mean_mt *)arguments; int PID=0; PID=arg.thread_num; int ret; int x_min,x_max,y_min,y_max, z_min, z_max; int NbElement2 = (2*arg.neighborhoodsize[0]+1)*(2*arg.neighborhoodsize[1]+1)*(2*arg.neighborhoodsize[2]+1); typedef float Voisinages[NbElement2]; Voisinages V1,V2; float w_max = 0; double epsilon= 0.0001; int offset_k = 0; int offset_j = 0; int offset_kk = 0; int offset_jj = 0; for (int k=arg.debut; k < arg.fin ; k++) { double count = 0; offset_k = k*(arg.vol_size[0]*arg.vol_size[1]); for (int j=0; j < arg.vol_size[1] ; j++) { offset_j = j*arg.vol_size[0]; for (int i=0; i < arg.vol_size[0] ; i++) { float global_sum = 0; float average = 0; x_min = MAX(0,i-arg.search[0]); x_max = MIN(arg.vol_size[0]-1,i+arg.search[0]); y_min = MAX(0,j-arg.search[1]); y_max = MIN(arg.vol_size[1]-1,j+arg.search[1]); z_min = MAX(0,k-arg.search[2]); z_max = MIN(arg.vol_size[2]-1,k+arg.search[2]); // Only the voxel with a local mean and variance different to zero are processed. // By this way the computational time is reduced since the background is not taken into account (or the B-scan mask for US image) if ((arg.mean_map[offset_k + offset_j + i] > epsilon) && (arg.var_map[offset_k + offset_j + i] > epsilon)) { if ((arg.weight_method == 0) || (arg.weight_method == 2)) Neiborghood(arg.in,i,j,k,arg.neighborhoodsize,V1,arg.vol_size,arg.weight_method); // if (arg.weight_method == 1) Neiborghood(arg.in,i,j,k,arg.neighborhoodsize,V1,arg.vol_size,arg.weight_method); w_max = 0; for (int kk = z_min; kk <= z_max; kk++) { offset_kk = kk*(arg.vol_size[0]*arg.vol_size[1]); for (int jj = y_min; jj <= y_max; jj++) { offset_jj = jj*arg.vol_size[0]; for (int ii = x_min; ii <= x_max; ii++) { // To avoid the compute the weigh with null patch and the division by zero in ratio and ratio 2 if ((arg.mean_map[offset_kk + offset_jj + ii] > epsilon) && (arg.var_map[offset_kk + offset_jj + ii] > epsilon)) { float ratio = arg.mean_map[offset_k + offset_j + i]/arg.mean_map[offset_kk + offset_jj + ii]; float ratio2 = arg.var_map[offset_k + offset_j + i]/arg.var_map[offset_kk + offset_jj + ii]; float weight = 0; if ((arg.weight_method == 0) || (arg.weight_method == 2)) { if ( (arg.m_min <= ratio) && (ratio <= (1/arg.m_min)) && (arg.v_min <= ratio2) && (ratio2 <= (1/arg.v_min)) ) { if ((ii != i) || (jj != j) || (kk != k)) { float val_in; count = count + 1; Neiborghood(arg.in,ii,jj,kk,arg.neighborhoodsize,V2,arg.vol_size,arg.weight_method); weight = Weight(L2_norm(V1,V2,arg.neighborhoodsize),arg.beta,arg.filtering_param); global_sum = global_sum + weight; val_in=arg.hallucinate?arg.hallucinate[offset_kk + offset_jj + ii]:arg.in[offset_kk + offset_jj + ii];//VF //Rician denoising if (arg.weight_method == 2) average = average + val_in * val_in *weight; else average = average + val_in * weight; if (weight > w_max) w_max = weight; } } } else { if ( (arg.m_min <= ratio) && (ratio <= (1/arg.m_min))) { if ((ii != i) || (jj != j) || (kk != k)) { float val_in; count = count + 1; //Pearson distance computation weight = Weight(Pearson_distance(V1,V2,arg.neighborhoodsize),arg.beta,arg.filtering_param); global_sum = global_sum + weight; val_in=arg.hallucinate?arg.hallucinate[offset_kk + offset_jj + ii]:arg.in[offset_kk + offset_jj + ii]; //VF average = average + val_in * weight; if (weight > w_max) w_max = weight; } } } } } } } global_sum = global_sum + w_max; double denoised_value = 0.0; float val_in=arg.hallucinate?arg.hallucinate[offset_k + offset_j + i]:arg.in[offset_k + offset_j + i];//VF // Rician denoising if (arg.weight_method == 2) { average = average + val_in * val_in * w_max; if (global_sum != 0.0) { denoised_value = (average/global_sum) - (2*arg.filtering_param * arg.filtering_param); if (denoised_value > 0.0) denoised_value = sqrt (denoised_value); else denoised_value = 0.0; arg.out[offset_k + offset_j + i] = denoised_value; } else { arg.out[offset_k + offset_j + i] = val_in; } } // Gaussian and Speckle denoising else { average = average + val_in*w_max; if (global_sum != 0.0) arg.out[offset_k + offset_j + i] = average/global_sum; else arg.out[offset_k + offset_j + i] = val_in; } } } } if(debug) std::cout<<"Thread ( "<< std::setw(2) <<PID+1<< " ) has finished the slice :"<<std::setw(3)<< k <<std::endl; ret = pthread_mutex_lock(arg.mp); *arg.mean_neighboors = *arg.mean_neighboors + count/(arg.vol_size[0]*arg.vol_size[1]); ret = pthread_mutex_unlock(arg.mp); } if(debug) std::cout<<"End of the thread : "<<std::setw(2)<<PID+1<<std::endl; pthread_exit(0); }