Your debugging steps sound good.
I had a look at the model and couldn’t find any obvious errors, so I tried to overfit a random image using this simple code:
model = UNet(1, 1)
x = torch.randn(1, 1, 224, 224)
target = torch.randint(0, 2, (1, 1, 224, 224)).float()

optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
criterion = nn.BCEWithLogitsLoss()


for epoch in range(30):
    optimizer.zero_grad()
    output = model(x)
    loss = criterion(output, target)
    loss.backward()
    optimizer.step()
    print('Epoch {}, loss {}, accuracy {}'.format(epoch, loss.item(),
        (target[0, 0] == (output[0, 0] > 0.0)).float().mean().item()))

and can reach an accuracy of ~0.9984 after 30 epochs, so the model seems to work fine.
Also, I cannot find any issues in the training code.
Could you share a single input and target, if they are open source, so that we can have a look?