| 63 | } |
| 64 | |
| 65 | UNetDecoderImpl::UNetDecoderImpl(std::vector<int> encoder_channels, std::vector<int> decoder_channels, int n_blocks, |
| 66 | bool use_attention, bool use_center) |
| 67 | { |
| 68 | if (n_blocks != decoder_channels.size()) throw "Model depth not equal to your provided `decoder_channels`"; |
| 69 | std::reverse(std::begin(encoder_channels),std::end(encoder_channels)); |
| 70 | |
| 71 | // computing blocks input and output channels |
| 72 | int head_channels = encoder_channels[0]; |
| 73 | std::vector<int> out_channels = decoder_channels; |
| 74 | decoder_channels.pop_back(); |
| 75 | decoder_channels.insert(decoder_channels.begin(),head_channels); |
| 76 | std::vector<int> in_channels = decoder_channels; |
| 77 | encoder_channels.erase(encoder_channels.begin()); |
| 78 | std::vector<int> skip_channels = encoder_channels; |
| 79 | skip_channels[skip_channels.size()-1] = 0; |
| 80 | |
| 81 | if(use_center) center = CenterBlock(head_channels, head_channels); |
| 82 | else center = torch::nn::Sequential(torch::nn::Identity()); |
| 83 | //the last DecoderBlock of blocks need no skip tensor |
| 84 | for (int i = 0; i< in_channels.size()-1; i++) { |
| 85 | blocks->push_back(DecoderBlock(in_channels[i], skip_channels[i], out_channels[i], true, use_attention)); |
| 86 | } |
| 87 | blocks->push_back(DecoderBlock(in_channels[in_channels.size()-1], skip_channels[in_channels.size()-1], |
| 88 | out_channels[in_channels.size()-1], false, use_attention)); |
| 89 | |
| 90 | register_module("center", center); |
| 91 | register_module("blocks", blocks); |
| 92 | } |
| 93 | |
| 94 | torch::Tensor UNetDecoderImpl::forward(std::vector<torch::Tensor> features){ |
| 95 | std::reverse(std::begin(features),std::end(features)); |