Giter Site home page Giter Site logo

hairmapper's Introduction

HairMapper: Removing Hair from Portraits Using GANs

HairMapper is a hair-removal network that can be applied in hair design and 3D face reconstruction.

hairmapper

Published in 2022 IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR’2022)

Yiqian Wu, Yongliang Yang, Xiaogang Jin*

Project Paper Suppl Video Dataset Github

Abstract:

Removing hair from portrait images is challenging due to the complex occlusions between hair and face, as well as the lack of paired portrait data with/without hair. To this end, we present a dataset and a baseline method for removing hair from portrait images using generative adversarial networks (GANs). Our core idea is to train a fully connected network HairMapper to find the direction of hair removal in the latent space of StyleGAN for the training stage. We develop a new separation boundary and diffuse method to generate paired training data for males, and a novel ''female-male-bald'' pipeline for paired data of females. Experiments show that our method can naturally deal with portrait images with variations on gender, age, etc. We validate the superior performance of our method by comparing it to state-of-the-art methods through extensive experiments and user studies. We also demonstrate its applications in hair design and 3D face reconstruction.

License

You can use, redistribute, and adapt this software for NON-COMMERCIAL purposes only.

Demo

Open In Colab

Requirements

  1. Windows (not tested on Linux yet)
  2. Python 3.7
  3. NVIDIA GPU + CUDA11.1 + CuDNN

Install

  1. git clone [email protected]:oneThousand1000/HairMapper.git
  2. Download the following pretrained models, put each of them to path:

    model path
    StyleGAN2-ada-Generator.pth ./ckpts
    e4e_ffhq_encode.pt ./ckpts
    model_ir_se50.pth ./ckpts
    face_parsing.pth ./ckpts
    vgg16.pth ./ckpts
    classification_model.pth ./classifier/gender_classification
    classification_model.pth ./classifier/hair_classification

​ face_parsing.pth from: https://github.com/switchablenorms/CelebAMask-HQ/tree/master/face_parsing (79999_iter.pth)

​ e4e_ffhq_encode.pt from: https://github.com/omertov/encoder4editing

​ model_ir_se50.pth from: https://github.com/orpatashnik/StyleCLIP

The StyleGAN2-ada-Generator.pth contains the same model parameters as the original stylegan2 pkl model stylegan2-ffhq-config-f.pkl.

  1. Create conda environment:

    conda create -n HairMapper python=3.7
    activate HairMapper
    
  2. StyleGAN2-ada requirements: The code relies heavily on custom PyTorch extensions that are compiled on the fly using NVCC. On Windows, the compilation requires Microsoft Visual Studio. We recommend installing Visual Studio Community Edition and adding it into PATH using "C:\Program Files (x86)\Microsoft Visual Studio\<VERSION>\Community\VC\Auxiliary\Build\vcvars64.bat".

    Please modify compiler path in ./styleGAN2_ada_model/stylegan2_ada/torch_utils/custom_ops.py according to your own Microsoft Visual Studio installation path (default: C:\Program Files (x86)\Microsoft Visual Studio).

    def _find_compiler_bindir():
        patterns = [
            '''
            	modify the compiler dir according to your own VS installation path
            ''' 
        ]
        for pattern in patterns:
            matches = sorted(glob.glob(pattern))
            if len(matches):
                return matches[-1]
        return None
  3. Then install other dependencies by

    pip install torch===1.7.1+cu110 torchvision===0.8.2+cu110 torchaudio===0.7.2 -f https://download.pytorch.org/whl/torch_stable.html
    
    pip install -r requirements.txt
    

We modified the stylegan-ada pytorch version to output latent codes in Z, W, W+ and StyleSpace more conveniently.

Since we find that getting those CUDA extensions to run on Windows is a hassle (stytlegan2-ada issue#97), we also modified the stylegan-ada so that you can choose to use a slow reference implementation of upfirdn2d() and bias_act() (slower, but can be directly used without compiling CUDA extensions).

For those who can not compile the CUDA extensions successfully, please set USING_CUDA_TO_SPEED_UP = False in styleGAN2_ada_model/stylegan2_ada/torch_utils/ops/bias_act.py and styleGAN2_ada_model/stylegan2_ada/torch_utils/ops/upfirdn2d.py to use the slow reference implementation.

Models

Please fill out this google form for pre-trained models access:

https://forms.gle/a5pRbE3yxEr7sZDm7

Then download and put the pre-trained models to path:

model path
Final HairMapper (can be applied to female and male) mapper/checkpoints/final/best_model.pt
Man HairMapper (can only be applied to male) mapper/checkpoints/man/best_model.pt

Testing

Directly use our pre-trained model for hair removal.

step1:

Real images should be extracted and aligned using DLib and a function from the original FFHQ dataset preparation step, you can use the image align code provided by stylegan-encoder.

Please put the aligned real images to ./test_data/origin (examplar data can be found in ./data/test_data/final/origin).

step2:

Then using encoder4editing to get the corresponding latent codes:

cd encoder4editing
python encode.py  --data_dir ../test_data

latent codes will be saved to ./test_data/code.

step3:

Then run HairMapper:

cd ../
python main_mapper.py  --data_dir ./test_data

If you want to perform an additional diffusion (slower, but can achieve better results):

python main_mapper.py  --data_dir ./test_data --diffuse

Training

Considering that our method involves several optimizations and several network trainings, we provide a step-by-step training procedure.

Data Preparation (Sec 3.2)

Generate D_0 dataset:

python step1_generate_data.py --dataset_name D0 --num DatasetSize

Generate D_noise dataset:

python step1_generate_data.py --dataset_name Dnoise --num DatasetSize --add_noise

Datasets will be saved to ./training_runs/dataset/D0 and ./training_runs/dataset/Dnoise.

Boundary Training (Sec 3.3)

There should be enough bald-data in D0 to train a hair separation boundary, but a randomly sampled dataset consists of 10000-images may only contains 100 bald-images. So that we recommend you to directly use our pre-trained male hair separation boundary in ./data/boundaries/stylegan2_ada/coarse/stylegan2_ffhq_hair_w_male and gender separation boundary in ./data/boundaries/stylegan2_ada/coarse/stylegan2_ffhq_gender_styleflow.

Or you can train male hair separation boundary on D_0 for yourself. (not recommended)

python step2_train_man_hair_coarse_boundary.py  --output_dir $HairBoundaryDir$  --dataset_path ./training_runs/dataset/D0

Train gender separation boundary on StyleFlow results. (We prepared the gender transition results in ./data/styleflow_gender_training_data)

python step2_train_gender_boundary.py --output_dir $GenderBoundaryDir$ --dataset_path ./data/styleflow_gender_training_data 

Male Hair Removal (Sec 3.4)

Male_Hair_Removal

For D_0

python step3_train_bald_male_data.py  --dataset_name D0 --num 2500

to use your own hair boundary:

python step3_train_bald_male_data.py --dataset_name D0  --hair_boundary_dir $HairBoundaryDir$ --num 2500

Results will be saved to ./training_runs/male_training/D0

For D_noise

python step3_train_bald_male_data.py --dataset_name Dnoise --num 2500

to use your own hair boundary:

python step3_train_bald_male_data.py  --dataset_name Dnoise  --hair_boundary_dir $HairBoundaryDir$  --num 2500

Results will be saved to ./training_runs/male_training/Dnoise

Male Mapper Training (Sec 3.5)

Male_Mapper_Training

First, prepare training data:

python step4_male_mapper_data_preparation.py  --dataset_name D0  --noise_dataset_name Dnoise --mapper_name male_mapper

Training data list will be saved to ./training_runs/male_mapper/data

Train male mapper:

python train_mapper.py --mapper_name male_mapper --max_steps 52000

Female Hair Removal (Sec 3.6)

Female_Hair_Removal

python step6_train_bald_female_data.py  --dataset_name D0  --male_mapper_name male_mapper --num 2500 
python step6_train_bald_female_data.py  --dataset_name Dnoise --male_mapper_name male_mapper --num 2500

Results will be saved to ./training_runs/female_training/D0

or use the pre-trained male mapper:

python step6_train_bald_female_data.py  --dataset_name D0  --mapper_ckpt_path mapper/checkpoints/man/best_model.pt --num 2500
python step6_train_bald_female_data.py  --dataset_name Dnoise  --mapper_ckpt_path mapper/checkpoints/man/best_model.pt --num 2500

Results will be saved to ./training_runs/female_training/Dnoise

Final Mapper Training (Sec 3.6)

Final_Mapper_Training

First, prepare training data:

python step7_final_mapper_data_preparation.py --dataset_name D0 --noise_dataset_name Dnoise --mapper_name final_mapper 

Training data list will be saved to ./training_runs/final_mapper/data

Train final mapper:

python train_mapper.py --mapper_name final_mapper --max_steps 26000

Contact

[email protected] / [email protected]

Citation

@InProceedings{Wu_2022_CVPR,
    author    = {Wu, Yiqian and Yang, Yong-Liang and Jin, Xiaogang},
    title     = {HairMapper: Removing Hair From Portraits Using GANs},
    booktitle = {Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
    month     = {June},
    year      = {2022},
    pages     = {4227-4236}
}

Reference and Acknowledgements

We thanks the following works:

stylegan2-ada-pytorch

StyleCLIP

encoder4editing

InterFaceGAN

idinvert

@InProceedings{Patashnik_2021_ICCV,
    author    = {Patashnik, Or and Wu, Zongze and Shechtman, Eli and Cohen-Or, Daniel and Lischinski, Dani},
    title     = {StyleCLIP: Text-Driven Manipulation of StyleGAN Imagery},
    booktitle = {Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV)},
    month     = {October},
    year      = {2021},
    pages     = {2085-2094}
}
@inproceedings{zhu2020indomain,
  title     = {In-domain GAN Inversion for Real Image Editing},
  author    = {Zhu, Jiapeng and Shen, Yujun and Zhao, Deli and Zhou, Bolei},
  booktitle = {Proceedings of European Conference on Computer Vision (ECCV)},
  year      = {2020}
}
@inproceedings{shen2020interpreting,
  title     = {Interpreting the Latent Space of GANs for Semantic Face Editing},
  author    = {Shen, Yujun and Gu, Jinjin and Tang, Xiaoou and Zhou, Bolei},
  booktitle = {CVPR},
  year      = {2020}
}
@article{tov2021designing,
  title={Designing an Encoder for StyleGAN Image Manipulation},
  author={Tov, Omer and Alaluf, Yuval and Nitzan, Yotam and Patashnik, Or and Cohen-Or, Daniel},
  journal={arXiv preprint arXiv:2102.02766},
  year={2021}
}
@inproceedings{Karras2020ada,
  title     = {Training Generative Adversarial Networks with Limited Data},
  author    = {Tero Karras and Miika Aittala and Janne Hellsten and Samuli Laine and Jaakko Lehtinen and Timo Aila},
  booktitle = {Proc. NeurIPS},
  year      = {2020}
}

hairmapper's People

Contributors

onethousand1000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hairmapper's Issues

About loss hair and loss face different from paper

in parer loss hair is difine as

image

but in train_mapper.py this loss do not dot with hair mask.. wondering why

    loss_l2_latent = self.latent_l2_loss(w_hat, res_w)
    loss_dict['loss_l2_latent'] = float(loss_l2_latent)
    loss += loss_l2_latent * self.latent_l2_lambda

    loss_l2_img = torch.mean(((res_x - x_hat)) ** 2, dim=[0, 1, 2, 3])  ### do not dot with hair mask
    loss_dict['loss_l2_res_img'] = float(loss_l2_img)
    loss += loss_l2_img * self.img_l2_lambda_res

    loss_l2_img = torch.mean(((origin_img - x_hat) * mask) ** 2, dim=[0, 1, 2, 3])
    loss_dict['loss_l2_origin_img'] = float(loss_l2_img)
    loss += loss_l2_img * self.img_l2_lambda_origin

AssertionError : Stylegan_ada

Hey @oneThousand1000 ,
Thanks for this amazing repo.
I was trying the given Google Colab and found an Assertion Error below,

WARNING:stylegan2_ada_generator:Load model from ../ckpts/StyleGAN2-ada-Generator.pth
WARNING:stylegan2_ada_generator:No pre-trained model will be loaded!
Initializing generator.
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
<ipython-input-20-8b3677e0e584> in <module>
     3 data_dir = '/content/drive/MyDrive/3DAI/HairMapper/test_data'
     4 print(f'Initializing generator.')
----> 5 model = StyleGAN2adaGenerator(model_name, logger=None, truncation_psi=1.0)
     6 
     7 mapper = LevelMapper(input_dim=512).eval().cuda()

../styleGAN2_ada_model/stylegan2_ada_generator.py in __init__(self, model_name, logger, truncation_psi, randomize_noise)

../styleGAN2_ada_model/base_generator.py in __init__(self, model_name, logger)

AssertionError: 

And the code cell producing the above error is below,

model_name = 'stylegan2_ada'
latent_space_type = 'wp'
data_dir = '/content/drive/MyDrive/3DAI/HairMapper/test_data'
print(f'Initializing generator.')
model = StyleGAN2adaGenerator(model_name, logger=None, truncation_psi=1.0)

mapper = LevelMapper(input_dim=512).eval().cuda()
ckpt = torch.load('./mapper/checkpoints/final/best_model.pt')
alpha = float(ckpt['alpha']) * 1.2
mapper.load_state_dict(ckpt['state_dict'], strict=True)
kwargs = {'latent_space_type': latent_space_type}
parsingNet = get_parsingNet(save_pth='./ckpts/face_parsing.pth')
inverter = InverterRemoveHair(
        model_name,
        Generator=model,
        learning_rate=0.01,
        reconstruction_loss_weight=1.0,
        perceptual_loss_weight=5e-5,
        truncation_psi=1.0,
        logger=None
)

code_dir = os.path.join(data_dir, 'code')
origin_img_dir = os.path.join(data_dir, 'actress_imgs')
res_dir = os.path.join(data_dir, 'mapper_res')

os.makedirs(res_dir, exist_ok=True)

Please suggest any way to tackle this issue.
Thanks once again.

separation boundary

First of all, thank you for your work.
When using the separation boundary of InterfaceGAN, the gender score is 1 for boys and 0 for girls? Do I need to train a separate gender classifier to score? The hair score is trained by Resnet50 as a classifier, but do you also binarize the final score to 0 or 1?

Color cast in the result images

Hi, Thanks for you nice work!
When I use you inference code, I notice that there are very obvious color change in some results, just as follows. But in your paper and supplyment, there is no such problem. Is there anything wrong with me?
image

What about beard?

Hi,
thanks for the nice work! What about beard removal? Can this work be adapted to that?

Thanks!
L.

How is the file StyleGAN2-ada-Generator.pth generated?

I want to ask a question, how is the file StyleGAN2-ada-Generator.pth generated? I have run the stylegan2-ada-pytorch project, and the generated weight file is pkl. If I use pkl directly, it seems not feasible. How can I generate StyleGAN2-ada-Generator.pth with my own data set?

Very Important Issue - Leftover hair after using align image code. How can i train even if i imcrease more croppin area till chest level so that neck, cloth, shoulder get good Reconstruction?

How can i train so that the shoulder and neck part get good Reconstruction after using image aligning code. Please find the reference images of ORIGINAL and GENERATED. Btw, Fantastic work but needed to train by increasing the ratio value more than 1 so that it crops more but results are weird. How to train more than 1 ratio value? Even if I try going more than 0.5 might give an error because the box is going too much of boundaries.

In short, how to train to remove the more hair and reconstruct if i increase the boundaries more?

The model itself WASN'T trained much with images coming till shoulders? Is that the issue? If yes, how can I train the images till CHEST level so that it would have good Reconstruction?

Please, let me know.
thumb_09c8c98KA002_1_01_res
thumb_rangriti_valleyo3611ss20blu_1_01_res
thumb_09c8c98KA002_1
thumb_rangriti_valleyo3611ss20blu_1

How to blend other hair style?

Hi researchers of HairMapper,
Could you please give me some hints on how to blend other hairstyles like the Figure 1 shown on the front page of the paper?
thank you !

What is D_noise for?

Thank you for your excellent work.
I wonder what the D_0 and D_noise for, why you generate two part of random images?

Output Color is changed

Hey @oneThousand1000 ,
Sorry for bothering, But the result i'm getting has a lot differences between color map.
Here is one reference,
aish_color_change

I though it's due to RGB image mode so i checked it by converting into BGR, But that's also not matching to the original image color and light.

Any suggestions?

Running Mapper on Batches

Dear all,
Is there a way to paralyze the mapper code? i.e., if I have a batch of latent codes, is it possible to run the line below on a batch?
mapper(mapper_input_tensor)
Thanks!

Results on horizontal flipped images

Hi, another small questions:). I tried to verify the performance consistency for HairMapper and found the ediited images are different from horizontal flipped images, that is the models used in HairMapper (maybe the encoder) are not left-right symmetry.

More specifically, define HairMapper edition as H(), any components of face parsing as Seg(), and cv2.flip(*, 1) as Flip, there is:
H(aligned_image) and Flip(H(Flip(aligned_image))) are rather different and Seg(H(aligned_image)) and Seg(Flip(H(Flip(aligned_image)))) are different as well.

Maybe more horizontal flipping augmentation can fix it?

About 'keeping the rest of the layers unchanged'.

Hi!
In reading your code, I found a detail that may not correspond to the paper. This detail is insignificant, but if possible, I still want to know if you have unique thinking.

Specifically, in '.\styleGAN2_ada_model\stylegan2_ada_generator.py', near line 384,
image
the [7-17] layers (starting from 0) of the edited W + are replaced by the original W +. That is, only the first 7 layers of W + are ''obviously'' manipulated.

Is this inconsistent with the first 8 layers of change mentioned in the paper, or do I make a low-level code understanding mistake?

Again, this is insignificant. I just want to know if you have a unique understanding and whether the open-source pre-trained HairMapper is also trained in this way.

How to test other images?

Dear authors, in the step1 of Testing, whether I can only use the align code in the link you provide (image align code) ? I use the code in your link to crop my real images, but for some real images shot from specular angles, the part of head would be cut off. If I use other align code, whether it will affect the HairMapper?

Bald should work on full image

Hi, There!

          The bald should work on full body images but NOT only on cropped faces. I'm aware that you would have trained only on cropped faces. The thing here is, All the contributors worked on only cropped faces. It doesn't really excite on the output.

Could you let me know how to make workable for bald on full image?

Thankyou.

id_loss is not active

Hi, Thanks for your nice work!

I would like to ask why did u comment out id_loss during optimization (diffuse). Are Pixel-wise reconstruction loss and Perceptual loss enough to preserve identity?

About the latent space of stylegan2 and stylegan2-ada.

Thank you for your outstanding work!
I noticed that e4e is trained on stylegan2 and the bald latent code output by hairMapper feeds into stylegan2-ada. Are the potential spaces of these two generators the same, or does hairMapper implicitly do the migration of the two potential spaces? Can you please tell me why you are using stylegan2- ada instead of stylegan2?
I ask because I want to test the pre-trained hairMapper directly on the stylegan2 generator, however, I haven't gotten around to trying it yet.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.