mirror of
https://github.com/iperov/DeepFaceLab.git
synced 2025-08-22 22:34:25 -07:00
Fixes RCT and sets it as the color transfer algorithm
Fixes a bug in RCT where uint8 (1-255) images were passed in, but cv.cvtColor expects a float32 (0-1) Changes the Sample Processor to use RCT for it's random color transfer feature
This commit is contained in:
parent
0f0df28b9f
commit
36b623d5ef
3 changed files with 44 additions and 21 deletions
|
@ -327,10 +327,9 @@ class ConverterMasked(Converter):
|
||||||
cv2.BORDER_TRANSPARENT), 0, 1.0)]
|
cv2.BORDER_TRANSPARENT), 0, 1.0)]
|
||||||
|
|
||||||
prd_face_bgr = imagelib.reinhard_color_transfer(
|
prd_face_bgr = imagelib.reinhard_color_transfer(
|
||||||
np.clip((prd_face_bgr * 255).astype(np.uint8), 0, 255),
|
prd_face_bgr,
|
||||||
np.clip((dst_face_bgr * 255).astype(np.uint8), 0, 255),
|
dst_face_bgr,
|
||||||
source_mask=prd_face_mask_a, target_mask=prd_face_mask_a)
|
source_mask=prd_face_mask_a, target_mask=prd_face_mask_a)
|
||||||
prd_face_bgr = np.clip(prd_face_bgr.astype(np.float32) / 255.0, 0.0, 1.0)
|
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
debugs += [np.clip(cv2.warpAffine(prd_face_bgr, face_output_mat, img_size,
|
debugs += [np.clip(cv2.warpAffine(prd_face_bgr, face_output_mat, img_size,
|
||||||
|
@ -444,10 +443,9 @@ class ConverterMasked(Converter):
|
||||||
cv2.BORDER_TRANSPARENT), 0, 1.0)]
|
cv2.BORDER_TRANSPARENT), 0, 1.0)]
|
||||||
|
|
||||||
new_out_face_bgr = imagelib.reinhard_color_transfer(
|
new_out_face_bgr = imagelib.reinhard_color_transfer(
|
||||||
np.clip((out_face_bgr * 255).astype(np.uint8), 0, 255),
|
out_face_bgr,
|
||||||
np.clip((dst_face_bgr * 255).astype(np.uint8), 0, 255),
|
dst_face_bgr,
|
||||||
source_mask=face_mask_blurry_aaa, target_mask=face_mask_blurry_aaa)
|
source_mask=face_mask_blurry_aaa, target_mask=face_mask_blurry_aaa)
|
||||||
new_out_face_bgr = np.clip(new_out_face_bgr.astype(np.float32) / 255.0, 0.0, 1.0)
|
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
debugs += [np.clip(cv2.warpAffine(new_out_face_bgr, face_output_mat, img_size,
|
debugs += [np.clip(cv2.warpAffine(new_out_face_bgr, face_output_mat, img_size,
|
||||||
|
|
|
@ -11,16 +11,21 @@ def reinhard_color_transfer(target, source, clip=False, preserve_paper=False, so
|
||||||
This implementation is (loosely) based on to the "Color Transfer
|
This implementation is (loosely) based on to the "Color Transfer
|
||||||
between Images" paper by Reinhard et al., 2001.
|
between Images" paper by Reinhard et al., 2001.
|
||||||
|
|
||||||
|
Title: "Super fast color transfer between images"
|
||||||
|
Author: Adrian Rosebrock
|
||||||
|
Date: June 30. 2014
|
||||||
|
Url: https://www.pyimagesearch.com/2014/06/30/super-fast-color-transfer-images/
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
-------
|
-------
|
||||||
source: NumPy array
|
source: NumPy array
|
||||||
OpenCV image in BGR color space (the source image)
|
OpenCV image (w, h, 3) in BGR color space (float32) 0-1
|
||||||
target: NumPy array
|
target: NumPy array (float32)
|
||||||
OpenCV image in BGR color space (the target image)
|
OpenCV image (w, h, 3) in BGR color space (float32), 0-1
|
||||||
clip: Should components of L*a*b* image be scaled by np.clip before
|
clip: Should components of L*a*b* image be scaled by np.clip before
|
||||||
converting back to BGR color space?
|
converting back to BGR color space?
|
||||||
If False then components will be min-max scaled appropriately.
|
If False then components will be min-max scaled appropriately.
|
||||||
Clipping will keep target image brightness truer to the input.
|
Clipping will keep target image brightness truer to the input.30
|
||||||
Scaling will adjust image brightness to avoid washed out portions
|
Scaling will adjust image brightness to avoid washed out portions
|
||||||
in the resulting color transfer that can be caused by clipping.
|
in the resulting color transfer that can be caused by clipping.
|
||||||
preserve_paper: Should color transfer strictly follow methodology
|
preserve_paper: Should color transfer strictly follow methodology
|
||||||
|
@ -33,14 +38,17 @@ def reinhard_color_transfer(target, source, clip=False, preserve_paper=False, so
|
||||||
Returns:
|
Returns:
|
||||||
-------
|
-------
|
||||||
transfer: NumPy array
|
transfer: NumPy array
|
||||||
OpenCV image (w, h, 3) NumPy array (uint8)
|
OpenCV image (w, h, 3) NumPy array (float32)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
np.clip(source, 0, 1, out=source)
|
||||||
|
np.clip(target, 0, 1, out=target)
|
||||||
|
|
||||||
# convert the images from the RGB to L*ab* color space, being
|
# convert the images from the RGB to L*ab* color space, being
|
||||||
# sure to utilizing the floating point data type (note: OpenCV
|
# sure to utilizing the floating point data type (note: OpenCV
|
||||||
# expects floats to be 32-bit, so use that instead of 64-bit)
|
# expects floats to be 32-bit, so use that instead of 64-bit)
|
||||||
source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB).astype(np.float32)
|
source = cv2.cvtColor(source.astype(np.float32), cv2.COLOR_BGR2LAB)
|
||||||
target = cv2.cvtColor(target, cv2.COLOR_BGR2LAB).astype(np.float32)
|
target = cv2.cvtColor(target.astype(np.float32), cv2.COLOR_BGR2LAB)
|
||||||
|
|
||||||
# compute color statistics for the source and target images
|
# compute color statistics for the source and target images
|
||||||
src_input = source if source_mask is None else source * source_mask
|
src_input = source if source_mask is None else source * source_mask
|
||||||
|
@ -77,10 +85,10 @@ def reinhard_color_transfer(target, source, clip=False, preserve_paper=False, so
|
||||||
b = _scale_array(b, clip=clip)
|
b = _scale_array(b, clip=clip)
|
||||||
|
|
||||||
# merge the channels together and convert back to the RGB color
|
# merge the channels together and convert back to the RGB color
|
||||||
# space, being sure to utilize the 8-bit unsigned integer data
|
# space
|
||||||
# type
|
|
||||||
transfer = cv2.merge([l, a, b])
|
transfer = cv2.merge([l, a, b])
|
||||||
transfer = cv2.cvtColor(transfer.astype(np.uint8), cv2.COLOR_LAB2BGR)
|
transfer = cv2.cvtColor(transfer, cv2.COLOR_LAB2BGR)
|
||||||
|
np.clip(transfer, 0, 1, out=transfer)
|
||||||
|
|
||||||
# return the color transferred image
|
# return the color transferred image
|
||||||
return transfer
|
return transfer
|
||||||
|
@ -92,6 +100,11 @@ def linear_color_transfer(target_img, source_img, mode='pca', eps=1e-5):
|
||||||
using a linear transform.
|
using a linear transform.
|
||||||
Images are expected to be of form (w,h,c) and float in [0,1].
|
Images are expected to be of form (w,h,c) and float in [0,1].
|
||||||
Modes are chol, pca or sym for different choices of basis.
|
Modes are chol, pca or sym for different choices of basis.
|
||||||
|
|
||||||
|
Title: "NeuralImageSynthesis / ExampleNotebooks / ScaleControl.ipynb"
|
||||||
|
Author: Leon Gatys
|
||||||
|
Date: December 14, 2016
|
||||||
|
Url: https://github.com/leongatys/NeuralImageSynthesis/blob/master/ExampleNotebooks/ScaleControl.ipynb
|
||||||
"""
|
"""
|
||||||
mu_t = target_img.mean(0).mean(0)
|
mu_t = target_img.mean(0).mean(0)
|
||||||
t = target_img - mu_t
|
t = target_img - mu_t
|
||||||
|
@ -125,6 +138,22 @@ def linear_color_transfer(target_img, source_img, mode='pca', eps=1e-5):
|
||||||
return matched_img
|
return matched_img
|
||||||
|
|
||||||
|
|
||||||
|
def lab_linear_color_transform(target_img, source_img, eps=1e-5, mode='pca'):
|
||||||
|
np.clip(source_img, 0, 1, out=source_img)
|
||||||
|
np.clip(target_img, 0, 1, out=target_img)
|
||||||
|
|
||||||
|
# convert the images from the RGB to L*ab* color space, being
|
||||||
|
# sure to utilizing the floating point data type (note: OpenCV
|
||||||
|
# expects floats to be 32-bit, so use that instead of 64-bit)
|
||||||
|
source_img = cv2.cvtColor(source_img.astype(np.float32), cv2.COLOR_BGR2LAB)
|
||||||
|
target_img = cv2.cvtColor(target_img.astype(np.float32), cv2.COLOR_BGR2LAB)
|
||||||
|
|
||||||
|
target_img = linear_color_transfer(target_img, source_img, mode=mode, eps=eps)
|
||||||
|
target_img = cv2.cvtColor(target_img, cv2.COLOR_LAB2BGR)
|
||||||
|
np.clip(target_img, 0, 1, out=target_img)
|
||||||
|
return target_img
|
||||||
|
|
||||||
|
|
||||||
def lab_image_stats(image):
|
def lab_image_stats(image):
|
||||||
# compute the mean and standard deviation of each channel
|
# compute the mean and standard deviation of each channel
|
||||||
(l, a, b) = cv2.split(image)
|
(l, a, b) = cv2.split(image)
|
||||||
|
|
|
@ -223,11 +223,7 @@ class SampleProcessor(object):
|
||||||
if apply_ct and ct_sample is not None:
|
if apply_ct and ct_sample is not None:
|
||||||
if ct_sample_bgr is None:
|
if ct_sample_bgr is None:
|
||||||
ct_sample_bgr = ct_sample.load_bgr()
|
ct_sample_bgr = ct_sample.load_bgr()
|
||||||
|
img_bgr = imagelib.reinhard_color_transfer(img_bgr, ct_sample_bgr, clip=True)
|
||||||
# ct_sample_bgr_resized = cv2.resize(ct_sample_bgr, (resolution, resolution), cv2.INTER_LINEAR)
|
|
||||||
|
|
||||||
img_bgr = imagelib.reinhard_color_transfer(img_bgr, ct_sample_bgr[..., 0:3])
|
|
||||||
img_bgr = np.clip(img_bgr, 0.0, 1.0)
|
|
||||||
|
|
||||||
if normalize_std_dev:
|
if normalize_std_dev:
|
||||||
img_bgr = (img_bgr - img_bgr.mean((0, 1))) / img_bgr.std((0, 1))
|
img_bgr = (img_bgr - img_bgr.mean((0, 1))) / img_bgr.std((0, 1))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue