(self, gt_dict)
| 154 | |
| 155 | |
| 156 | def forward(self, gt_dict): |
| 157 | |
| 158 | points=gt_dict["strand_positions"] |
| 159 | dirs=gt_dict["strand_directions"] |
| 160 | |
| 161 | #points |
| 162 | points = points.permute(0, 2, 1) ## nr_strands, xyz, 100 |
| 163 | nr_strands = points.shape[0] |
| 164 | #dirs |
| 165 | last_dir = dirs[:, -1:, :] |
| 166 | dirs = torch.cat([dirs, last_dir],1) # make the direction nr_strands, 100, 3 |
| 167 | dirs = dirs.permute(0, 2, 1) |
| 168 | |
| 169 | per_point_features = torch.cat([points, dirs] ,1) |
| 170 | # per_point_features = points |
| 171 | x=per_point_features |
| 172 | |
| 173 | # print("x",x.mean(),x.std()) |
| 174 | |
| 175 | strand_features = self.cnn_encoder(x) # nr_strands, 128(nr_features), 3(elements per string) |
| 176 | |
| 177 | # print("strand_features after encoder", strand_features.mean(), strand_features.std()) |
| 178 | |
| 179 | strand_features = strand_features.view(nr_strands, -1).contiguous() |
| 180 | # strand_features = self.final_cnn_aggregator(strand_features) # outputs nr_strands x 128 |
| 181 | |
| 182 | # print("strand_features after aggregate", strand_features.mean(), strand_features.std()) |
| 183 | |
| 184 | strand_features_mean = self.aggregate_towards_mean(strand_features) # outputs nr_strands x 128 |
| 185 | s = self.pred_mean(strand_features_mean) |
| 186 | |
| 187 | # s = self.pred_mean(strand_features) |
| 188 | # s=s |
| 189 | |
| 190 | # print("s mean and std", s.mean(), s.std()) |
| 191 | |
| 192 | |
| 193 | #pass the s through a tanh so it's bounded by -1,1 this makes it easier to consider it as an image later on when we train our diffusion model on scalp textures |
| 194 | s=self.tanh(s) |
| 195 | |
| 196 | |
| 197 | # exit(1) |
| 198 | |
| 199 | encoded_dict={} |
| 200 | encoded_dict["z"]=s |
| 201 | encoded_dict["z_no_eps"]=s |
| 202 | |
| 203 | if self.do_vae: |
| 204 | s_mean = s |
| 205 | # print("s_mean has mean std ", s_mean.mean(), s_mean.std()) |
| 206 | # s_logstd = 0.1 * self.pred_logstd(strand_features) |
| 207 | strand_features_logstd = self.aggregate_towards_logstd(strand_features) # outputs nr_strands x 128 |
| 208 | s_logstd = -2.0 + 0.01*self.pred_logstd(strand_features_logstd) #start with logstd that is low so that initially the variance of the normal is also low |
| 209 | encoded_dict["z_mean"] = s_mean |
| 210 | encoded_dict["z_logstd"] = s_logstd |
| 211 | # print("s_logstd has mean std ", s_logstd.mean(), s_logstd.std()) |
| 212 | if self.training: |
| 213 | std = torch.exp(s_logstd) |
nothing calls this directly
no outgoing calls
no test coverage detected