包含: - hair_service_sd: 主服务(换发型/换发色/生发,端口8801) - photo_service: LoRA调度+训练(端口32678) - hair_grow_service: 调试测试页(端口8888,含4个测试页) - 批量训练脚本(batch_train_hairstyles.py) - 发际线mask自动识别(hairline_mask.py,4种方案) - 手绘mask换发型(hair_swap_manual.py) - 文档:README.md + LARGE_FILES.md + docs/ 大文件(模型权重200G、训练数据123G)已排除,见 LARGE_FILES.md OSS/COS密钥已脱敏为环境变量,原文件备份在本地
76 lines
2.0 KiB
Python
76 lines
2.0 KiB
Python
import numpy as np
|
|
import torch
|
|
from torch import nn
|
|
|
|
def get_norm(norm, out_channels=None):
|
|
"""
|
|
Args:
|
|
norm (str or callable):
|
|
|
|
Returns:
|
|
nn.Module or None: the normalization layer
|
|
"""
|
|
if isinstance(norm, str):
|
|
if len(norm) == 0:
|
|
return None
|
|
norm = {
|
|
"BN": nn.BatchNorm2d,
|
|
"IN": nn.InstanceNorm2d,
|
|
"GN": lambda channels: nn.GroupNorm(32, channels),
|
|
"nnSyncBN": nn.SyncBatchNorm, # keep for debugging
|
|
}[norm]
|
|
if out_channels is not None:
|
|
return norm(out_channels)
|
|
else:
|
|
return norm
|
|
|
|
class Conv2d(torch.nn.Conv2d):
|
|
"""
|
|
A wrapper around :class:`torch.nn.Conv2d` to support zero-size tensor and more features.
|
|
"""
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
"""
|
|
Extra keyword arguments supported in addition to those in `torch.nn.Conv2d`:
|
|
|
|
Args:
|
|
norm (nn.Module, optional): a normalization layer
|
|
activation (callable(Tensor) -> Tensor): a callable activation function
|
|
|
|
It assumes that norm layer is used before activation.
|
|
"""
|
|
norm = kwargs.pop("norm", None)
|
|
activation = kwargs.pop("activation", None)
|
|
super().__init__(*args, **kwargs)
|
|
|
|
self.norm = norm
|
|
self.activation = activation
|
|
|
|
def forward(self, x):
|
|
x = super().forward(x)
|
|
if self.norm is not None:
|
|
x = self.norm(x)
|
|
if self.activation is not None:
|
|
x = self.activation(x)
|
|
return x
|
|
|
|
class Backbone(nn.Module):
|
|
"""
|
|
Abstract base class for network backbones.
|
|
"""
|
|
|
|
def __init__(self):
|
|
"""
|
|
The `__init__` method of any subclass can specify its own set of arguments.
|
|
"""
|
|
super().__init__()
|
|
|
|
def forward(self):
|
|
"""
|
|
Subclasses must override this method, but adhere to the same return type.
|
|
|
|
Returns:
|
|
dict[str: Tensor]: mapping from feature name (e.g., "res2") to tensor
|
|
"""
|
|
pass
|