void test_transpose_readonly(MatrixT view) { typedef typename MatrixT::value_type T; // Check that view is initialized check_matrix(view, 0); length_type const size1 = view.size(1); typename MatrixT::const_transpose_type trans = view.transpose(); test_assert(trans.size(0) == view.size(1)); test_assert(trans.size(1) == view.size(0)); for (index_type idx0=0; idx0<trans.size(0); ++idx0) for (index_type idx1=0; idx1<trans.size(1); ++idx1) { T expected = T(idx1 * size1 + idx0 + 0); test_assert(equal(trans.get(idx0, idx1), expected)); test_assert(equal(trans.get(idx0, idx1), view. get(idx1, idx0))); } // Check that view is unchanged check_matrix(view, 0); }
void convolute_3d_out_of_place(MatrixT& _image, MatrixT& _kernel) { if (_image.size() != _kernel.size()) { std::cerr << "received image and kernel of mismatching size!\n"; return; } unsigned M, N, K; M = _image.shape()[0]; N = _image.shape()[1]; K = _image.shape()[2]; unsigned fft_size = M * N * (K / 2 + 1); // setup fourier space arrays fftwf_complex* image_fourier = static_cast<fftwf_complex*>( fftwf_malloc(sizeof(fftwf_complex) * fft_size)); fftwf_complex* kernel_fourier = static_cast<fftwf_complex*>( fftwf_malloc(sizeof(fftwf_complex) * fft_size)); float scale = 1.0 / (M * N * K); // define+run forward plans fftwf_plan image_fwd_plan = fftwf_plan_dft_r2c_3d( M, N, K, _image.data(), image_fourier, FFTW_ESTIMATE); fftwf_execute(image_fwd_plan); fftwf_plan kernel_fwd_plan = fftwf_plan_dft_r2c_3d( M, N, K, _kernel.data(), kernel_fourier, FFTW_ESTIMATE); fftwf_execute(kernel_fwd_plan); // multiply for (unsigned index = 0; index < fft_size; ++index) { float real = image_fourier[index][0] * kernel_fourier[index][0] - image_fourier[index][1] * kernel_fourier[index][1]; float imag = image_fourier[index][0] * kernel_fourier[index][1] + image_fourier[index][1] * kernel_fourier[index][0]; image_fourier[index][0] = real; image_fourier[index][1] = imag; } fftwf_destroy_plan(kernel_fwd_plan); fftwf_destroy_plan(image_fwd_plan); fftwf_plan image_rev_plan = fftwf_plan_dft_c2r_3d( M, N, K, image_fourier, _image.data(), FFTW_ESTIMATE); fftwf_execute(image_rev_plan); for (unsigned index = 0; index < _image.num_elements(); ++index) { _image.data()[index] *= scale; } fftwf_destroy_plan(image_rev_plan); fftwf_free(image_fourier); fftwf_free(kernel_fourier); }
void fill_matrix(MatrixT view, int offset=0) { typedef typename MatrixT::value_type T; length_type const size1 = view.size(1); // Initialize view for (index_type idx0=0; idx0<view.size(0); ++idx0) for (index_type idx1=0; idx1<view.size(1); ++idx1) view.put(idx0, idx1, T(idx0 * size1 + idx1 + offset)); }
void check_matrix(MatrixT view, int offset=0) { typedef typename MatrixT::value_type T; length_type const size1 = view.size(1); for (index_type idx0=0; idx0<view.size(0); ++idx0) for (index_type idx1=0; idx1<view.size(1); ++idx1) { test_assert(equal(view.get(idx0, idx1), T(idx0 * size1 + idx1 + offset))); } }
void nodes_of_strongly_connected_component(MatrixT const & matrix, std::vector<IndexT> & node_list) { std::vector<bool> node_visited_already(matrix.size(), false); std::deque<IndexT> node_queue; // // Step 1: Push root nodes to queue: // for (typename std::vector<IndexT>::iterator it = node_list.begin(); it != node_list.end(); it++) { node_queue.push_back(*it); } node_list.resize(0); // // Step 2: Fill with remaining nodes of strongly connected compontent // while (!node_queue.empty()) { vcl_size_t node_id = static_cast<vcl_size_t>(node_queue.front()); node_queue.pop_front(); if (!node_visited_already[node_id]) { node_list.push_back(IndexT(node_id)); node_visited_already[node_id] = true; for (typename MatrixT::value_type::const_iterator it = matrix[node_id].begin(); it != matrix[node_id].end(); it++) { vcl_size_t neighbor_node_id = static_cast<vcl_size_t>(it->first); if (neighbor_node_id == node_id) continue; if (node_visited_already[neighbor_node_id]) continue; node_queue.push_back(IndexT(neighbor_node_id)); } } } }
void generate_layering(MatrixT const & matrix, std::vector< std::vector<IndexT> > & layer_list) { std::vector<bool> node_visited_already(matrix.size(), false); // // Step 1: Set root nodes to visited // for (vcl_size_t i=0; i<layer_list.size(); ++i) { for (typename std::vector<IndexT>::iterator it = layer_list[i].begin(); it != layer_list[i].end(); it++) node_visited_already[*it] = true; } // // Step 2: Fill next layers // while (layer_list.back().size() > 0) { vcl_size_t layer_index = layer_list.size(); //parent nodes are at layer 0 layer_list.push_back(std::vector<IndexT>()); for (typename std::vector<IndexT>::iterator it = layer_list[layer_index].begin(); it != layer_list[layer_index].end(); it++) { for (typename MatrixT::value_type::const_iterator it2 = matrix[*it].begin(); it2 != matrix[*it].end(); it2++) { if (it2->first == *it) continue; if (node_visited_already[it2->first]) continue; layer_list.back().push_back(it2->first); node_visited_already[it2->first] = true; } } } // remove last (empty) nodelist: layer_list.resize(layer_list.size()-1); }
unsigned nrow(const MatrixT& mat) { return mat.size(); }
void convolute_3d_in_place(MatrixT& _image, const MatrixT& _kernel, const bool& _verbose = false) { if (_image.size() == _kernel.size()) { std::cerr << "received image and kernel of matching size, this makes " "preparing the kernel impossible!\nExiting.\n"; return; } if (MatrixT::dimensionality != 3) { std::cerr << "received image and kernel of dimension " << MatrixT::dimensionality << " that cannot be processed by convolute_3d_in_place!\n"; return; } std::vector<unsigned> origin_image_extents(MatrixT::dimensionality); std::copy(_image.shape(), _image.shape() + MatrixT::dimensionality, origin_image_extents.begin()); std::vector<unsigned> origin_kernel_extents(MatrixT::dimensionality); std::copy(_kernel.shape(), _kernel.shape() + MatrixT::dimensionality, origin_kernel_extents.begin()); if (_verbose) { std::cout << "[convolute_3d_in_place]\timage:\n" << _image << "\n"; std::cout << "[convolute_3d_in_place]\tkernel:\n" << _kernel << "\n"; } /////////////////////////////////////////////////////////////////////////// // CALCULATE PADDING EXTENT std::vector<unsigned> common_extents(MatrixT::dimensionality); std::transform(origin_image_extents.begin(), origin_image_extents.end(), origin_kernel_extents.begin(), common_extents.begin(), add_minus_1<unsigned>()); std::vector<unsigned> common_offsets(MatrixT::dimensionality); std::transform(origin_kernel_extents.begin(), origin_kernel_extents.end(), common_offsets.begin(), minus_1_div_2<unsigned>()); /////////////////////////////////////////////////////////////////////////// // PADD IMAGE image_stack padded_image(common_extents, _image.storage_order()); image_stack_view subview_padded_image = padded_image [boost::indices[range(common_offsets[0], common_offsets[0] + origin_image_extents[0])] [range(common_offsets[1], common_offsets[1] + origin_image_extents[1])] [range(common_offsets[2], common_offsets[2] + origin_image_extents[2])]]; subview_padded_image = _image; unsigned long size_of_transform = padded_image.num_elements(); /////////////////////////////////////////////////////////////////////////// // PADD KERNEL image_stack padded_kernel(common_extents, _kernel.storage_order()); for (long z = 0; z < origin_kernel_extents[2]; ++z) for (long y = 0; y < origin_kernel_extents[1]; ++y) for (long x = 0; x < origin_kernel_extents[0]; ++x) { long intermediate_x = x - origin_kernel_extents[0] / 2L; long intermediate_y = y - origin_kernel_extents[1] / 2L; long intermediate_z = z - origin_kernel_extents[2] / 2L; intermediate_x = (intermediate_x < 0) ? intermediate_x + common_extents[0] : intermediate_x; intermediate_y = (intermediate_y < 0) ? intermediate_y + common_extents[1] : intermediate_y; intermediate_z = (intermediate_z < 0) ? intermediate_z + common_extents[2] : intermediate_z; padded_kernel[intermediate_x][intermediate_y][intermediate_z] = _kernel[x][y][z]; } /////////////////////////////////////////////////////////////////////////// // RESIZE ALL TO ALLOW FFTW INPLACE TRANSFORM std::vector<unsigned> inplace_extents(3); adapt_extents_for_fftw_inplace(common_extents, inplace_extents, _image.storage_order()); padded_image.resize(boost::extents[inplace_extents[0]][inplace_extents[1]] [inplace_extents[2]]); padded_kernel.resize(boost::extents[inplace_extents[0]][inplace_extents[1]] [inplace_extents[2]]); if (_verbose) { std::cout << "[convolute_3d_in_place]\t padded image:\n" << padded_image << "\n"; std::cout << "[convolute_3d_in_place]\t padded kernel:\n" << padded_kernel << "\n"; } float scale = 1.0 / (size_of_transform); fftwf_complex* complex_image_fourier = (fftwf_complex*)padded_image.data(); fftwf_complex* complex_kernel_fourier = (fftwf_complex*)padded_kernel.data(); // define+run forward plans fftwf_plan image_fwd_plan = fftwf_plan_dft_r2c_3d( common_extents[0], common_extents[1], common_extents[2], padded_image.data(), complex_image_fourier, FFTW_ESTIMATE); fftwf_execute(image_fwd_plan); fftwf_plan kernel_fwd_plan = fftwf_plan_dft_r2c_3d( common_extents[0], common_extents[1], common_extents[2], padded_kernel.data(), complex_kernel_fourier, FFTW_ESTIMATE); fftwf_execute(kernel_fwd_plan); fftwf_destroy_plan(kernel_fwd_plan); fftwf_destroy_plan(image_fwd_plan); // multiply unsigned fourier_num_elements = padded_image.num_elements() / 2; for (unsigned index = 0; index < fourier_num_elements; ++index) { float real = complex_image_fourier[index][0] * complex_kernel_fourier[index][0] - complex_image_fourier[index][1] * complex_kernel_fourier[index][1]; float imag = complex_image_fourier[index][0] * complex_kernel_fourier[index][1] + complex_image_fourier[index][1] * complex_kernel_fourier[index][0]; complex_image_fourier[index][0] = real; complex_image_fourier[index][1] = imag; } fftwf_plan image_rev_plan = fftwf_plan_dft_c2r_3d( common_extents[0], common_extents[1], common_extents[2], complex_image_fourier, padded_image.data(), FFTW_ESTIMATE); fftwf_execute(image_rev_plan); for (unsigned index = 0; index < padded_image.num_elements(); ++index) { padded_image.data()[index] *= scale; } fftwf_destroy_plan(image_rev_plan); _image = padded_image [boost::indices[range(common_offsets[0], common_offsets[0] + origin_image_extents[0])] [range(common_offsets[1], common_offsets[1] + origin_image_extents[1])] [range(common_offsets[2], common_offsets[2] + origin_image_extents[2])]]; if (_verbose) { std::cout << "[convolute_3d_in_place]\t padded result:\n" << padded_image << "\n"; std::cout << "[convolute_3d_in_place]\t result:\n" << _image << "\n"; } }