Browse Source

dreamTeach 贴图处理

master
dongchangxi 6 months ago
parent
commit
dcf79e3f6d
  1. 30
      apps/auto_convert3d_new.py
  2. 368
      apps/ps_image_shadow_up_ag_two_d.py
  3. 492
      apps/ps_image_white_add_white_d.py
  4. 354
      apps/remove_light_fix_up_shadow_dream_tech.py

30
apps/auto_convert3d_new.py

@ -3,7 +3,7 @@ import os, oss2, time, redis, requests, shutil, sys, subprocess, json, platform
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from retrying import retry from retrying import retry
import atexit,platform import atexit,platform
import white_purification_v4,white_purification import white_purification_v4,white_purification,remove_light_fix_up_shadow_dream_tech
if platform.system() == 'Windows': if platform.system() == 'Windows':
sys.path.append('e:\\libs\\') sys.path.append('e:\\libs\\')
import common import common
@ -121,12 +121,28 @@ def team_check(r):
print(res.text) print(res.text)
pid = res.json()['data']['pid'] pid = res.json()['data']['pid']
orderId = res.json()['data']['order_id'] orderId = res.json()['data']['order_id']
shopId = res.json()['data']['shop_id']
pid = str(pid) pid = str(pid)
orderId = str(orderId) orderId = str(orderId)
shopId = str(shopId)
#print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} repair_id:{repair_id} 生成团队审核模型 start model:IndependentRepairTeamcheckGLBQueue', ) #print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'pid:{pid} repair_id:{repair_id} 生成团队审核模型 start model:IndependentRepairTeamcheckGLBQueue', )
ossPath = down_obj_fromoss(pid,orderId) ossPath = down_obj_fromoss(pid,orderId)
#对文件进行白色提纯处理
imagePath = os.path.join(workdir, 'print', pid,orderId,pid+"Tex1.jpg")
print("开始处理白色提纯")
#white_purification.white_purification_utils(imagePath)
if shopId == "240":
os.system(f'python D:\\make2\\apps\\remove_light_fix_up_shadow_dream_tech.py -input_path {imagePath} -output_path {imagePath}')
else:
os.system(f'python D:\\make2\\apps\\white_purification.py -i {imagePath}')
print("贴图文件白色提纯完成",imagePath)
#提纯完重新上传提纯图片
ossImagePath = os.path.join("objs/print", pid,ossPath,"texture","process_"+pid+"Tex1.jpg")
oss_client.put_object_from_file(f"objs/print/{pid}/{ossPath}/texture/process_{pid}Tex1.jpg",imagePath)
print("白色提纯上传图片路径-",ossImagePath,imagePath)
obj_filename = f'{pid}.obj' obj_filename = f'{pid}.obj'
glb_filename = f'{orderId}.glb' glb_filename = f'{orderId}.glb'
@ -150,17 +166,7 @@ def team_check(r):
oss_client.put_object_from_file(f'glbs/print/order_id/{glb_filename}', os.path.join(workdir, "print", pid,orderId, glb_filename)) oss_client.put_object_from_file(f'glbs/print/order_id/{glb_filename}', os.path.join(workdir, "print", pid,orderId, glb_filename))
#对文件进行白色提纯处理
imagePath = os.path.join(workdir, 'print', pid,orderId,pid+"Tex1.jpg")
print("开始处理白色提纯")
#white_purification.white_purification_utils(imagePath)
os.system(f'python D:\\make2\\apps\white_purification_v4.py -i {imagePath}')
print("贴图文件白色提纯完成",imagePath)
#提纯完重新上传提纯图片
ossImagePath = os.path.join("objs/print", pid,ossPath,"texture","process_"+pid+"Tex1.jpg")
oss_client.put_object_from_file(f"objs/print/{pid}/{ossPath}/texture/process_{pid}Tex1.jpg",imagePath)
print("白色提纯上传图片路径-",ossImagePath,imagePath)

368
apps/ps_image_shadow_up_ag_two_d.py

@ -0,0 +1,368 @@
import os.path
import numpy as np
from scipy.interpolate import CubicSpline
import cv2
import argparse
from ps_image_white_add_white_d import photoshop_add_white
def adjust_levels_image(img):
""""""
img = img.astype(np.float32)
img = 255 * ((img - 20) / (241 - 20))
img[img < 0] = 0
img[img > 255] = 255
img = 255 * np.power(img / 255.0, 1.0 / 1.34)
img = (img / 255) * (255- 0) + 0
img[img < 0] = 0
img[img > 255] = 255
img = img.astype(np.uint8)
return img
def photoshop_style_feather(image, mask, radius=150):
"""
"""
if mask.dtype != np.uint8:
mask = (mask * 255).astype(np.uint8)
if len(mask.shape) > 2:
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
kernel_size = max(3, int(2 * np.ceil(2 * radius) + 1))
expanded_size = (mask.shape[0] + 2 * radius, mask.shape[1] + 2 * radius)
expanded_mask = np.zeros(expanded_size, dtype=np.uint8)
center_y, center_x = radius, radius
expanded_mask[center_y:center_y + mask.shape[0],
center_x:center_x + mask.shape[1]] = mask
blurred_expanded_mask = cv2.GaussianBlur(
expanded_mask,
(kernel_size, kernel_size),
sigmaX=radius,
sigmaY=radius,
borderType=cv2.BORDER_REFLECT_101
)
feathered_mask = blurred_expanded_mask[center_y:center_y + mask.shape[0],
center_x:center_x + mask.shape[1]]
feathered_mask = feathered_mask.astype(np.float32) / 255.0
feathered_mask = np.power(feathered_mask, 1.1) # 轻微增强对比度
feathered_mask = np.clip(feathered_mask * 255, 0, 255).astype(np.uint8)
return feathered_mask
def calculate_luminance(img):
""""""
if len(img.shape) == 3:
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
return ycrcb[:, :, 0].astype(np.float32) / 255.0
else:
return img.astype(np.float32) / 255.0
def photoshop_feather_blend(adjusted_img, original_img, mask, feather_radius=150, brightness_factor=0.95):
"""
"""
if mask.dtype != np.uint8:
mask = (mask * 255).astype(np.uint8)
if len(mask.shape) > 2:
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
# plt.figure(figsize=(10, 8))
# plt.imshow(mask, cmap='gray')
# plt.title("Feathered Mask")
# plt.axis('off')
# plt.colorbar(label='Opacity')
# plt.show()
feathered_mask = photoshop_style_feather(original_img, mask, feather_radius)
# plt.figure(figsize=(10, 8))
# plt.imshow(feathered_mask, cmap='gray')
# plt.title("Feathered Mask")
# plt.axis('off')
# plt.colorbar(label='Opacity')
# plt.show()
feathered_mask_float = feathered_mask.astype(np.float32) / 255.0
if len(original_img.shape) == 3 and len(feathered_mask_float.shape) == 2:
feathered_mask_float = np.stack([feathered_mask_float] * 3, axis=-1)
def to_linear(img):
img_linear = img.astype(np.float32) / 255.0
return np.where(img_linear <= 0.04045,
img_linear / 12.92,
((img_linear + 0.055) / 1.055) ** 2.4)
def to_srgb(img_linear):
return np.where(img_linear <= 0.0031308,
img_linear * 12.92,
1.055 * (img_linear ** (1 / 2.4)) - 0.055)
adjusted_linear = to_linear(adjusted_img)
original_linear = to_linear(original_img)
luminance_adjustment = np.mean(original_linear, axis=-1, keepdims=True) * (1.0 - brightness_factor)
adjusted_linear_corrected = adjusted_linear - luminance_adjustment
blended_linear = (adjusted_linear_corrected * feathered_mask_float +
original_linear * (1 - feathered_mask_float))
blended_srgb = to_srgb(blended_linear)
blended_img = np.clip(blended_srgb * 255, 0, 255).astype(np.uint8)
return blended_img
def rgb2lab_image(rgb_img):
""""""
rgb = rgb_img.astype(np.float32) / 255.0
mask = rgb > 0.04045
rgb = np.where(mask,
np.power((rgb + 0.055) / 1.055, 2.4),
rgb / 12.92)
XYZ = np.dot(rgb, [
[0.436052025, 0.222491598, 0.013929122],
[0.385081593, 0.716886060, 0.097097002],
[0.143087414, 0.060621486, 0.714185470]
])
XYZ *= np.array([100.0, 100.0, 100.0]) / [96.4221, 100.0, 82.5211]
epsilon = 0.008856
kappa = 903.3
XYZ_norm = np.where(XYZ > epsilon,
np.power(XYZ, 1 / 3),
(kappa * XYZ + 16) / 116)
L = 116 * XYZ_norm[..., 1] - 16
a = 500 * (XYZ_norm[..., 0] - XYZ_norm[..., 1])
b = 200 * (XYZ_norm[..., 1] - XYZ_norm[..., 2])
return np.stack([L, a, b], axis=-1)
def photoshop_lab_color_range_optimized(bgr_img, target_lab, tolerance=59, anti_alias=True):
""""""
rgb_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB)
lab_img = rgb2lab_image(rgb_img)
L, a, b = lab_img[:, :, 0], lab_img[:, :, 1], lab_img[:, :, 2]
target_L, target_a, target_b = target_lab
diff_L = np.abs(L - target_L)
diff_a = np.abs(a - target_a)
diff_b = np.abs(b - target_b)
dark_boost = np.ones_like(L)
dark_mask = L <40
dark_boost[dark_mask] = 1.2
weighted_diff = np.sqrt(
0.25 * (diff_L / 100) ** 2 +
0.75 * ((diff_a + diff_b) / 255) ** 2
) * 100
weighted_diff = weighted_diff / dark_boost
threshold = 1.6 * (100 - tolerance) / 100 * 23
normalized_diff = weighted_diff / threshold
mask = 0.5 * (np.tanh(4 * (1 - normalized_diff)) + 1)
if anti_alias:
mask = cv2.GaussianBlur(mask, (5, 5), 0)
return mask
def generate_curve_lut(x_points, y_points):
"""
输入采样点生成 256 长度的查找表LUT
"""
cs = CubicSpline(x_points, y_points, bc_type='natural')
x = np.arange(256)
y = cs(x)
y = np.clip(y, 0, 255).astype(np.uint8)
return y
def apply_curve(img, lut):
"""
对图像的每个通道应用曲线 LUT复合通道
"""
result = cv2.LUT(img, lut)
return result
def add_color_image(img):
""""""
# x_points = [0, 131, 255]
# y_points = [0, 124, 255]
x_points = [6, 184, 255]
y_points = [0, 191, 255]
lut = generate_curve_lut(x_points, y_points)
adjusted = apply_curve(img, lut)
return adjusted
def unsharp_mask(image, radius=5.0, amount=1.5, threshold=10):
"""
对图像应用 Unsharp Mask 锐化
参数:
- image: 输入图像必须是3通道BGR格式
- radius: 高斯模糊半径标准差
- amount: 锐化强度
- threshold: 差异阈值仅大于该值的区域会被增强
"""
if len(image.shape) != 3 or image.shape[2] != 3:
raise ValueError("输入必须是3通道BGR图像")
if max(image.shape[:2]) > 20000:
return unsharp_mask_blockwise(image, radius, amount, threshold)
img_float = image.astype(np.float32) if image.dtype != np.float32 else image
blurred = cv2.GaussianBlur(img_float, (0, 0), radius)
diff = img_float - blurred
mask = np.abs(diff) > threshold
sharpened = img_float.copy()
sharpened[mask] = img_float[mask] + diff[mask] * amount
return np.clip(sharpened, 0, 255).astype(np.uint8)
def unsharp_mask_blockwise(image, radius=5.0, amount=1.5, threshold=10, block_size=1024):
"""
分块执行 Unsharp Mask适用于超大图像防止内存爆炸
"""
h, w = image.shape[:2]
output = np.zeros_like(image)
for y in range(0, h, block_size):
for x in range(0, w, block_size):
block = image[y:y + block_size, x:x + block_size]
output[y:y + block_size, x:x + block_size] = unsharp_mask(block, radius, amount, threshold)
return output
def add_shadow_image(img):
""""""
x_points = [0, 131, 255]
y_points = [0, 124, 255]
lut = generate_curve_lut(x_points, y_points)
adjusted = apply_curve(img, lut)
return adjusted
def create_red_mask(img):
"""使用 Lab 空间中的 A 通道提取红色区域,返回 (h, w, 1) 掩码"""
lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
a = lab[..., 1].astype(np.float32)
red_score = np.clip((a - 128) / 50.0, 0, 1) # A 通道 > 128 表示偏红
red_score = cv2.GaussianBlur(red_score, (9, 9), sigmaX=4)
return red_score[..., np.newaxis] # 变成 (h, w, 1)
def cmyk_to_rgb(cmyk):
"""CMYK → RGB,模拟Photoshop近似"""
c, m, y, k = cmyk[..., 0], cmyk[..., 1], cmyk[..., 2], cmyk[..., 3]
r = (1 - c) * (1 - k)
g = (1 - m) * (1 - k)
b = (1 - y) * (1 - k)
return np.clip(np.stack([r, g, b], axis=-1) * 255, 0, 255)
def rgb_to_cmyk(rgb):
"""RGB → CMYK,模拟Photoshop近似"""
r, g, b = rgb[..., 0] / 255.0, rgb[..., 1] / 255.0, rgb[..., 2] / 255.0
k = 1 - np.maximum.reduce([r, g, b])
k_safe = np.where(k == 1, 1, k)
c = np.where(k == 1, 0, (1 - r - k) / (1 - k_safe))
m = np.where(k == 1, 0, (1 - g - k) / (1 - k_safe))
y = np.where(k == 1, 0, (1 - b - k) / (1 - k_safe))
return np.stack([c, m, y, k], axis=-1)
def selective_color_adjustment(img, target_color, cmyk_adjustments, relative=True):
if target_color != 'red':
raise NotImplementedError("当前只支持 red")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB).astype(np.float32)
mask = create_red_mask(img)
cmyk = rgb_to_cmyk(img_rgb)
# 应用 CMYK 调整
for channel, value in cmyk_adjustments.items():
idx = {'cyan': 0, 'magenta': 1, 'yellow': 2, 'black': 3}.get(channel)
if idx is None:
continue
original = cmyk[..., idx]
v = value / 100.0
if relative:
# 非线性相对调整,更接近 Photoshop 曲线(经验公式)
adjusted = original * (1 + v) ** 1.35 # gamma 可调
else:
adjusted = original + v
cmyk[..., idx] = np.clip(adjusted, 0, 1)
# 转换回 RGB 并混合
adjusted_rgb = cmyk_to_rgb(cmyk)
output_rgb = img_rgb * (1 - mask) + adjusted_rgb * mask
output_rgb = np.clip(output_rgb, 0, 255).astype(np.uint8)
return cv2.cvtColor(output_rgb, cv2.COLOR_RGB2BGR)
def reduce_red_black_relative(img):
"""模拟 Photoshop:红色 → 黑色 -8%,相对模式"""
return selective_color_adjustment(
img,
target_color='red',
cmyk_adjustments={'black': -8},
relative=True
)
def photoshop_actions_emulation(input_path, output_path):
""""""
original_img = cv2.imread(input_path)
# 加暗
shadow_image1=add_shadow_image(original_img)
shadow_image2 = add_shadow_image(shadow_image1)
# output_down_path= output_path.replace(".jpg","down.jpg")
# cv2.imwrite(output_down_path, shadow_image2)
original_img_color=add_color_image(shadow_image2)
# output_color_path= output_path.replace(".jpg","add_color.jpg")
# cv2.imwrite(output_color_path, original_img_color)
#白位加白
result_white_image= photoshop_add_white(original_img_color)
# output_white_path= output_color_path.replace(".jpg","white.jpg")
# cv2.imwrite(output_white_path, result_white_image)
#锐化
result_usm = unsharp_mask(result_white_image, radius=2, amount=0.4, threshold=10)
cv2.imwrite(output_path, result_usm)
if __name__ == '__main__':
arg = argparse.ArgumentParser()
arg.add_argument('--image_name', type=str, default='274351Tex1_adjusted060518_2_221.jpg')
arg.add_argument('--image_name_new', type=str, default='274351Tex1_adjusted060518_2_221_999999.jpg')
arg.add_argument('--in_dir', type=str, default='/data/datasets_20t/fsdownload/image_color_timing/output/')
arg.add_argument('--out_dir', type=str, default='/data/datasets_20t/fsdownload/image_color_timing/shadow_up/')
args = arg.parse_args()
os.makedirs(args.out_dir,exist_ok=True)
input_path = os.path.join(args.in_dir,args.image_name)
output_path = os.path.join(args.out_dir,args.image_name_new)
photoshop_actions_emulation(input_path, output_path)
人种

492
apps/ps_image_white_add_white_d.py

@ -0,0 +1,492 @@
import os.path
import numpy as np
from PIL import Image
from scipy.ndimage import gaussian_filter
import matplotlib.pyplot as plt
from skimage import io, color
from PIL import Image
import cv2
from skimage.exposure import match_histograms
from skimage.color import rgb2lab, lab2rgb
import time
def rgb_to_lab_photoshop(rgb):
"""
RGB 转换为 LAB使用 Photoshop 中的转换公式
"""
# 线性化 RGB
r, g, b = rgb[..., 0] / 255.0, rgb[..., 1] / 255.0, rgb[..., 2] / 255.0
r = np.where(r <= 0.04045, r, ((r + 0.055) / 1.055) ** 2.4)
g = np.where(g <= 0.04045, g, ((g + 0.055) / 1.055) ** 2.4)
b = np.where(b <= 0.04045, b, ((b + 0.055) / 1.055) ** 2.4)
x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375
y = r * 0.2126729 + g * 0.7151522 + b * 0.0721750
z = r * 0.0193339 + g * 0.1191920 + b * 0.9503041
# 白点 D65 归一化
x = x / 0.95047
y = y / 1.00000
z = z / 1.08883
# XYZ 到 LAB 转换
epsilon = 0.008856
kappa = 903.3
x = np.where(x > epsilon, x ** (1 / 3), (kappa * x + 16) / 116)
y = np.where(y > epsilon, y ** (1 / 3), (kappa * y + 16) / 116)
z = np.where(z > epsilon, z ** (1 / 3), (kappa * z + 16) / 116)
l = 116 * y - 16
a = 500 * (x - y)
b = 200 * (y - z)
return np.stack([l, a, b], axis=-1)
def create_mask_from_lab(lab_image, target_L, target_a, target_b, tolerance_L=5, tolerance_a=5, tolerance_b=5):
"""
根据给定的 L, a, b 值范围生成一个掩膜
参数
lab_image: 输入的 LAB 图像
target_L: 目标 L
target_a: 目标 a
target_b: 目标 b
tolerance_L: L 值的容差范围
tolerance_a: a 值的容差范围
tolerance_b: b 值的容差范围
返回
mask: 生成的掩膜1 表示符合条件0 表示不符合
"""
mask = (
(np.abs(lab_image[..., 0] - target_L) <= tolerance_L) &
(np.abs(lab_image[..., 1] - target_a) <= tolerance_a) &
(np.abs(lab_image[..., 2] - target_b) <= tolerance_b)
).astype(np.uint8)
return mask
def filter_contours_by_enclosing_circle(mask, min_diameter=50):
"""
"""
cleaned_mask = np.zeros_like(mask)
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for contour in contours:
# 计算最小外接圆
(x, y), radius = cv2.minEnclosingCircle(contour)
diameter = 2 * radius
# 判断是否能放下指定直径的圆
if diameter >= min_diameter:
cv2.drawContours(cleaned_mask, [contour], -1, 255, thickness=cv2.FILLED)
return cleaned_mask
# def adjust_levels_image(img):
# """"""
# img = img.astype(np.float32)
# img = 255 * ((img - 20) / (241 - 20))
# img[img < 0] = 0
# img[img > 255] = 255
# img = 255 * np.power(img / 255.0, 1.0 / 1.34)
# img = (img / 255) * (255- 0) + 0
# img[img < 0] = 0
# img[img > 255] = 255
# img = img.astype(np.uint8)
# return img
def normalize_coeffs(coeffs):
median_val = sorted(coeffs)[1]
return np.array([coef - median_val for coef in coeffs])
def img_bgr2rgb(img):
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = img.astype(np.float32) / 255.0
img = img.copy()
return img
def highlight_handle(img, highlight_coeffs):
highlights_alpha = 0.003923 * normalize_coeffs(highlight_coeffs)
a = np.diag(np.maximum(highlights_alpha, 0)) * np.eye(3)
b = np.diag(-np.minimum(highlights_alpha, 0)) * (1 - np.eye(3))
highlights_alpha = np.sum(a + b, axis=0)
img = img / (1 - highlights_alpha.reshape(1, 1, 3))
return img
def shadow_handle(img, shadows_coef):
shadows_alpha = 0.003923 * normalize_coeffs(shadows_coef)
a = np.diag(-np.minimum(shadows_alpha, 0)) * np.eye(3)
b = np.diag(np.maximum(shadows_alpha, 0)) * (1 - np.eye(3))
shadows_alpha = np.sum(a + b, axis=0)
img = (img - shadows_alpha.reshape(1, 1, 3)) / (1 - shadows_alpha.reshape(1, 1, 3))
return img
def mid_tone_handle(img, mid_tone_coeffs):
mid_tone_alpha = -0.0033944 * normalize_coeffs(mid_tone_coeffs)
f = np.diag(mid_tone_alpha) * (2 * np.eye(3) - 1)
mid_tone_gamma = np.exp(np.sum(f, axis=0))
img = np.power(img, mid_tone_gamma.reshape(1, 1, 3))
return img
def img_rgb2bgr(img):
img = cv2.normalize(img, None, 0, 255, cv2.NORM_MINMAX)
img = img.astype(np.uint8)
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
return img
def adjust_color_balance( image,
shadow_coefficients,
mid_tone_coefficients,
highlight_coefficients):
""""""
image = img_bgr2rgb(image)
image = highlight_handle(image, highlight_coefficients)
image = shadow_handle(image, shadow_coefficients)
image = mid_tone_handle(image, mid_tone_coefficients)
image = np.clip(image, 0, 1)
image = img_rgb2bgr(image)
cv2.imwrite('/data/datasets_20t/fsdownload/image_color_timing/white_add_white/9999999999999.jpg', image)
return image
def apply_gamut_mapping(values):
"""防止颜色溢出的色域映射函数"""
# 压缩高光区域以防止过曝
values = np.where(values > 0.9, 0.9 + (values - 0.9) * 0.5, values)
# 提亮阴影区域以防止死黑
values = np.where(values < 0.1, 0.1 * (values / 0.1) ** 0.7, values)
return np.clip(values, 0, 1)
# def match_colors(source, target, mask):
# """
# """
# matched = match_histograms(source, target, channel_axis=-1)
# mask_3ch = cv2.merge([mask] * 3) if len(mask.shape) == 2 else mask
# return source * (1 - mask_3ch) + matched * mask_3ch
# def match_colors(source, target, mask, strength):
# """
# :param source: 源图像 (H,W,3)
# :param target: 目标图像 (H,W,3)
# :param mask: 遮罩 (H,W) 或 (H,W,3), 值范围 0~1
# :param strength: 颜色匹配强度 (0~1)
# """
# matched = match_histograms(source, target, channel_axis=-1)
# mask_3ch = cv2.merge([mask] * 3) if len(mask.shape) == 2 else mask
# mask_weighted = mask_3ch * strength # 控制强度
# return source * (1 - mask_weighted) + matched * mask_weighted
def match_colors(source, target, mask, strength, brightness_scale=0.9):
matched = match_histograms(source, target, channel_axis=-1)
matched = matched * brightness_scale # 降低亮度
mask_3ch = cv2.merge([mask] * 3) if len(mask.shape) == 2 else mask
mask_weighted = mask_3ch * strength
return source * (1 - mask_weighted) + matched * mask_weighted
def apply_feathering(mask, radius):
""""""
mask_float = mask.astype(np.float32) / 255.0
blurred = cv2.GaussianBlur(mask_float, (0, 0), sigmaX=radius / 3, sigmaY=radius / 3)
return blurred
def photoshop_style_feather(image, mask, radius=150):
"""
实现接近Photoshop效果的羽化功能
参数:
image: 输入图像 (numpy array)
mask: 选区蒙版 (numpy array, 值范围0-255)
radius: 羽化半径 (像素)
返回:
羽化后的蒙版
"""
# 确保蒙版是uint8类型和单通道
if mask.dtype != np.uint8:
mask = (mask * 255).astype(np.uint8)
if len(mask.shape) > 2:
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
# 计算高斯核大小 (必须是奇数)
kernel_size = max(3, int(2 * np.ceil(2 * radius) + 1))
# 创建扩展的蒙版以模拟Photoshop的边界处理
expanded_size = (mask.shape[0] + 2 * radius, mask.shape[1] + 2 * radius)
expanded_mask = np.zeros(expanded_size, dtype=np.uint8)
# 将原始蒙版放置在扩展蒙版中央
center_y, center_x = radius, radius
expanded_mask[center_y:center_y + mask.shape[0],
center_x:center_x + mask.shape[1]] = mask
# 应用高斯模糊 (使用reflect边界处理,类似Photoshop)
blurred_expanded_mask = cv2.GaussianBlur(
expanded_mask,
(kernel_size, kernel_size),
sigmaX=radius,
sigmaY=radius,
borderType=cv2.BORDER_REFLECT_101
)
# 提取中央部分作为最终蒙版
feathered_mask = blurred_expanded_mask[center_y:center_y + mask.shape[0],
center_x:center_x + mask.shape[1]]
# 应用Photoshop特有的蒙版曲线调整
feathered_mask = feathered_mask.astype(np.float32) / 255.0
feathered_mask = np.power(feathered_mask, 1.1) # 轻微增强对比度
feathered_mask = np.clip(feathered_mask * 255, 0, 255).astype(np.uint8)
return feathered_mask
def calculate_luminance(img):
"""计算图像的亮度通道(YCbCr色彩空间的Y通道)"""
if len(img.shape) == 3:
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
return ycrcb[:, :, 0].astype(np.float32) / 255.0
else:
return img.astype(np.float32) / 255.0
def photoshop_feather_blend(adjusted_img, original_img, mask, feather_radius=150, brightness_factor=0.95):
"""
使用改进的羽化蒙版融合两张图像更接近Photoshop效果解决偏亮问题
参数:
adjusted_img: 调整后的图像
original_img: 原始图像
mask: 选区蒙版 (范围0-255)
feather_radius: 羽化半径
brightness_compensation: 亮度补偿因子 (0.0-1.0)值越小补偿越多
返回:
融合后的图像
"""
if mask.dtype != np.uint8:
mask = (mask * 255).astype(np.uint8)
if len(mask.shape) > 2:
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
# plt.figure(figsize=(10, 8))
# plt.imshow(mask, cmap='gray')
# plt.title("Feathered Mask")
# plt.axis('off')
# plt.colorbar(label='Opacity')
# plt.show()
feathered_mask = photoshop_style_feather(original_img, mask, feather_radius)
# plt.figure(figsize=(10, 8))
# plt.imshow(feathered_mask, cmap='gray')
# plt.title("Feathered Mask")
# plt.axis('off')
# plt.colorbar(label='Opacity')
# plt.show()
feathered_mask_float = feathered_mask.astype(np.float32) / 255.0
# 扩展蒙版维度以匹配图像通道数
if len(original_img.shape) == 3 and len(feathered_mask_float.shape) == 2:
feathered_mask_float = np.stack([feathered_mask_float] * 3, axis=-1)
# 改进的混合算法,解决亮度提升问题
# 1. 将图像转换到线性空间(模拟sRGB到线性RGB的转换)
def to_linear(img):
img_linear = img.astype(np.float32) / 255.0
# 简单的gamma校正近似
return np.where(img_linear <= 0.04045,
img_linear / 12.92,
((img_linear + 0.055) / 1.055) ** 2.4)
# 2. 将图像转回sRGB空间
def to_srgb(img_linear):
return np.where(img_linear <= 0.0031308,
img_linear * 12.92,
1.055 * (img_linear ** (1 / 2.4)) - 0.055)
# 3. 在线性空间中执行混合
adjusted_linear = to_linear(adjusted_img)
original_linear = to_linear(original_img)
# 4. 应用亮度校正因子
luminance_adjustment = np.mean(original_linear, axis=-1, keepdims=True) * (1.0 - brightness_factor)
adjusted_linear_corrected = adjusted_linear - luminance_adjustment
# 5. 在线性空间中进行混合
blended_linear = (adjusted_linear_corrected * feathered_mask_float +
original_linear * (1 - feathered_mask_float))
# 6. 转回sRGB空间并转换回uint8
blended_srgb = to_srgb(blended_linear)
blended_img = np.clip(blended_srgb * 255, 0, 255).astype(np.uint8)
return blended_img
def rgb2lab_image(rgb_img):
"""将 RGB 图像转换为 Photoshop 风格的 Lab"""
rgb = rgb_img.astype(np.float32) / 255.0
mask = rgb > 0.04045
rgb = np.where(mask,
np.power((rgb + 0.055) / 1.055, 2.4),
rgb / 12.92)
XYZ = np.dot(rgb, [
[0.436052025, 0.222491598, 0.013929122],
[0.385081593, 0.716886060, 0.097097002],
[0.143087414, 0.060621486, 0.714185470]
])
XYZ *= np.array([100.0, 100.0, 100.0]) / [96.4221, 100.0, 82.5211]
epsilon = 0.008856
kappa = 903.3
XYZ_norm = np.where(XYZ > epsilon,
np.power(XYZ, 1 / 3),
(kappa * XYZ + 16) / 116)
L = 116 * XYZ_norm[..., 1] - 16
a = 500 * (XYZ_norm[..., 0] - XYZ_norm[..., 1])
b = 200 * (XYZ_norm[..., 1] - XYZ_norm[..., 2])
return np.stack([L, a, b], axis=-1)
def photoshop_lab_color_range_optimized(bgr_img, target_lab, tolerance=59, anti_alias=True):
"""优化的色彩范围选择算法,提供更精确的选择"""
rgb_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB)
lab_img = rgb2lab_image(rgb_img)
# 分离通道
L, a, b = lab_img[:, :, 0], lab_img[:, :, 1], lab_img[:, :, 2]
target_L, target_a, target_b = target_lab
# 计算各通道差异
diff_L = np.abs(L - target_L)
diff_a = np.abs(a - target_a)
diff_b = np.abs(b - target_b)
# 暗部区域增强处理
dark_boost = np.ones_like(L)
dark_mask = L <40 # 只对较暗区域增强
dark_boost[dark_mask] = 1.2 # 增加暗部区域的敏感度
# 改进的加权差异计算,加入暗部增强
weighted_diff = np.sqrt(
0.25 * (diff_L / 100) ** 2 + # 进一步降低亮度权重
0.75 * ((diff_a + diff_b) / 255) ** 2 # 进一步增加颜色权重
) * 100
# 应用暗部增强
weighted_diff = weighted_diff / dark_boost
# 优化的容差转换公式
threshold = 1.6 * (100 - tolerance) / 100 * 23
# 应用更精确的 S 曲线,使用双曲正切函数提供更陡峭的过渡
normalized_diff = weighted_diff / threshold
mask = 0.5 * (np.tanh(4 * (1 - normalized_diff)) + 1)
# 抗锯齿处理
if anti_alias:
mask = cv2.GaussianBlur(mask, (5, 5), 0)
return mask
def photoshop_add_white(original_img, ):
""""""
#original_img = cv2.imread(input_path)
target_lab = np.array([89.06, 0.59, 6.66], dtype=np.float32)
tol= 85
mask = photoshop_lab_color_range_optimized(original_img, target_lab, tol)
# plt.figure(figsize=(10, 8))
# plt.imshow(mask, cmap='gray')
# plt.title("Feathered Mask")
# plt.axis('off')
# plt.colorbar(label='Opacity')
# plt.show()
mask_uint8 = (mask * 255).astype(np.uint8)
# adjusted_img = adjust_levels_image(original_img)
adjusted_img = adjust_color_balance(original_img,
shadow_coefficients=[0, 0, 0],
mid_tone_coefficients=[-20, 0, 5],
highlight_coefficients=[0, 0, 12],)
#cv2.imwrite('/data/datasets_20t/fsdownload/image_color_timing/white_add_white/9999999999999.jpg', adjusted_img)
#h, w = adjusted_img.shape[:2]
#mask = cv2.resize(mask_uint8, (w, h))
result = photoshop_feather_blend(adjusted_img, original_img, mask_uint8,
feather_radius=15, brightness_factor=0.9999)
#output_path="/data/datasets_20t/Downloads_google/correct_show_obj_dream_tech/290082/cache/290082Tex1_o_white.jpg"
return result
def photoshop_add_white3(input_path, ):
""""""
original_img = cv2.imread(input_path)
target_lab = np.array([89.06, 0.59, 6.66], dtype=np.float32)
tol= 85
mask = photoshop_lab_color_range_optimized(original_img, target_lab, tol)
# plt.figure(figsize=(10, 8))
# plt.imshow(mask, cmap='gray')
# plt.title("Feathered Mask")
# plt.axis('off')
# plt.colorbar(label='Opacity')
# plt.show()
mask_uint8 = (mask * 255).astype(np.uint8)
# adjusted_img = adjust_levels_image(original_img)
adjusted_img = adjust_color_balance(original_img,
shadow_coefficients=[0, 0, 0],
mid_tone_coefficients=[-20, 0, 5],
highlight_coefficients=[0, 0, 12],)
#cv2.imwrite('/data/datasets_20t/fsdownload/image_color_timing/white_add_white/9999999999999.jpg', adjusted_img)
#h, w = adjusted_img.shape[:2]
#mask = cv2.resize(mask_uint8, (w, h))
result = photoshop_feather_blend(adjusted_img, original_img, mask_uint8,
feather_radius=15, brightness_factor=0.99)
output_path="/data/datasets_20t/Downloads_google/correct_show_obj_dream_tech/290082/cache/290082Tex1_o_white.jpg"
cv2.imwrite(output_path, result)
return result
if __name__ == '__main__':
start_time = time.time()
# image_name="858408_272249Tex1_4_220.jpg"
# image_name_new= image_name.replace(".jpg","_999999.jpg")
# in_dir = "/data/datasets_20t/fsdownload/image_color_timing/output/"
# out_dir = "/data/datasets_20t/fsdownload/image_color_timing/white_add_white/"
# os.makedirs(out_dir,exist_ok=True)
input_path = "/data/datasets_20t/Downloads_google/correct_show_obj_dream_tech/290082/cache/290082Tex1_o.jpg"
photoshop_add_white3(input_path, )
print(f"程序运行时间: {time.time() - start_time:.2f}")
"""
百位加白
"""

354
apps/remove_light_fix_up_shadow_dream_tech.py

@ -0,0 +1,354 @@
import os.path
import shutil
import time
import argparse
import cv2
import numpy as np
from scipy.interpolate import CubicSpline
import sys, os
from PIL import Image, ImageEnhance
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from ps_image_shadow_up_ag_two_d import photoshop_actions_emulation
def smootherstep(x):
"""五次平滑插值函数:更加平滑过渡"""
return x**3 * (x * (x * 6 - 15) + 10)
def perceptual_smooth_adjustment_color_blend(img, threshold=220, reduction=0.5, margin=10, saturation_sensitivity=0.3, blur_radius=5, color_blend_strength=0.5):
"""
更平滑颜色融合感知亮度压制
- threshold: 压制起始亮度V 通道
- reduction: 压制强度0-1
- margin: 阈值过渡区间像素亮度差
- saturation_sensitivity: 饱和度高时减弱压制
- blur_radius: 用于颜色融合的模糊半径
- color_blend_strength: 颜色融合程度0~1
"""
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
v = v.astype(np.float32)
s = s.astype(np.float32)
# 饱和度感知压制减弱
sat_weight = 1.0 - (s / 255.0 * saturation_sensitivity)
sat_weight = np.clip(sat_weight, 0.0, 1.0)
# 平滑压制权重计算
delta = v - threshold
transition = np.zeros_like(v, dtype=np.float32)
in_range = (delta > 0) & (delta < margin)
transition[in_range] = smootherstep(delta[in_range] / margin)
transition[delta >= margin] = 1.0
# 压制权重融合
weight = reduction * transition * sat_weight
# 应用压制
v_new = v - (v - threshold) * weight
v_new = np.clip(v_new, 0, 255).astype(np.uint8)
# 合成压制后的图像
adjusted_hsv = cv2.merge([h, s.astype(np.uint8), v_new])
adjusted = cv2.cvtColor(adjusted_hsv, cv2.COLOR_HSV2BGR)
# -------------------
# 融合原图模糊版 → 减少颜色突兀
# -------------------
blurred = cv2.GaussianBlur(img, (blur_radius | 1, blur_radius | 1), 0)
# 构建融合权重 mask,仅对过渡区域起作用
color_blend_mask = np.clip(weight, 0, 1) * color_blend_strength
color_blend_mask = color_blend_mask[..., None] # 扩展为 (H,W,1) 用于通道融合
# 将融合区域混合模糊
final = adjusted.astype(np.float32) * (1 - color_blend_mask) + blurred.astype(np.float32) * color_blend_mask
final = np.clip(final, 0, 255).astype(np.uint8)
return final
def process_image(input_path, output_path, threshold=210, reduction=0.6):
"""
"""
try:
img = cv2.imread(input_path)
if img is None:
raise ValueError("无法读取图像,请检查路径是否正确")
#result = perceptual_adjustment(img, threshold, reduction)
result = perceptual_smooth_adjustment_color_blend(img, threshold, reduction)
cv2.imwrite(output_path, result)
print(f"处理成功,结果已保存到: {output_path}")
return True
except Exception as e:
print(f"处理失败: {str(e)}")
return False
def sigmoid(x, center=0.0, slope=10.0):
return 1 / (1 + np.exp(-slope * (x - center)))
def reduce_highlights_lab_advanced_hsvmask(
img,
highlight_thresh=220,
strength=30,
sigma=15,
detail_boost=1.0,
preserve_local_contrast=True
):
"""
LAB高光压制 + HSV感知蒙版 + 细节保留
"""
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
V = hsv[:, :, 2].astype(np.float32)
# 1. 生成高光 mask,过渡平滑
mask = sigmoid(V, center=highlight_thresh, slope=0.05)
mask = np.clip(mask, 0, 1)
mask = cv2.GaussianBlur(mask, (0, 0), sigmaX=2)
mask_vis = (mask * 255).astype(np.uint8)
# 2. LAB 空间亮度压制
img_lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
L, a, b = cv2.split(img_lab)
L = L.astype(np.float32)
# 3. 模糊和细节
L_blur = cv2.GaussianBlur(L, (0, 0), sigma)
L_detail = L - L_blur
# 4. 替代方案:压制 L,但融合方式更柔和
L_target = L_blur - strength * mask
L_target = np.clip(L_target, 0, 255)
if preserve_local_contrast:
# 保留细节 + 局部对比度(避免过度平滑)
L_new = L_target + detail_boost * L_detail
else:
# 单纯压制亮度
L_new = L_target
L_new = np.clip(L_new, 0, 255).astype(np.uint8)
# 5. 合成回去
lab_new = cv2.merge([L_new, a, b])
result = cv2.cvtColor(lab_new, cv2.COLOR_Lab2BGR)
return result, mask_vis
def suppress_highlights_keep_texture(image_bgr, v_thresh=225, target_v=215, sigma=1):
""""""
image_hsv = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(image_hsv)
v = v.astype(np.float32)
v_blur = cv2.GaussianBlur(v, (0, 0), sigmaX=sigma)
detail = v - v_blur
# 构建 soft mask(0~1),用于动态压制
mask = (v_blur > v_thresh).astype(np.float32)
# weight 越大压得越狠
weight = np.clip((v_blur - v_thresh) / 20.0, 0, 1) * mask # 20 是压制带宽
#weight =weight*1.2
# 将亮度压到 target_v 的线性混合:
v_compress = v_blur * (1 - weight) + target_v * weight
v_new = v_compress + detail
v_new = np.clip(v_new, 0, 255).astype(np.uint8)
hsv_new = cv2.merge([h, s, v_new])
result_bgr = cv2.cvtColor(hsv_new, cv2.COLOR_HSV2BGR)
return result_bgr
def correct_light_again_hsv(image_path):
img = cv2.imread(image_path)
result, mask_vis = reduce_highlights_lab_advanced_hsvmask(
img,
highlight_thresh=225,
strength=15,
sigma=10,
detail_boost=1.2
)
result_bgr= suppress_highlights_keep_texture(result)
output_image_path = image_path.replace(".jpg", "_light02.jpg")
cv2.imwrite(
output_image_path,
result_bgr
)
return output_image_path
def generate_curve_lut(x_points, y_points):
"""
输入采样点生成 256 长度的查找表LUT
"""
cs = CubicSpline(x_points, y_points, bc_type='natural')
x = np.arange(256)
y = cs(x)
y = np.clip(y, 0, 255).astype(np.uint8)
return y
def apply_curve(img, lut):
"""
对图像的每个通道应用曲线 LUT复合通道
"""
result = cv2.LUT(img, lut)
return result
def apply_curve_up_image(image_path,image_cache_dir):
"""提亮"""
x_points = [0, 124, 255]
y_points = [0, 131, 255]
lut = generate_curve_lut(x_points, y_points)
#adjusted = apply_curve(img, lut)
image_name_result = image_path.split("/")[-1].replace(".jpg", "_up.jpg")
result_path= os.path.join(image_cache_dir,image_name_result)
image_bgr = cv2.imread(image_path)
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
image_hsv = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2HSV).astype(np.float32)
h, s, v = cv2.split(image_hsv)
v_mean = np.mean(v)
print(f"v_mean{v_mean}")
if v_mean < 60:
adjusted = apply_curve(image_bgr, lut)
adjusted2 = apply_curve(adjusted, lut)
cv2.imwrite(result_path, adjusted2)
return result_path
else:
image_name_result = image_path.split("/")[-1].replace(".jpg", "_o.jpg")
result_original_path = os.path.join(image_cache_dir, image_name_result)
shutil.copy(image_path,result_original_path)
return result_original_path
def apply_curve_down_image(image_path,image_cache_dir):
"""压暗"""
x_points = [0, 131, 255]
y_points = [0, 124, 255]
lut = generate_curve_lut(x_points, y_points)
# adjusted = apply_curve(img, lut)
image_name_result = image_path.split("/")[-1].replace(".jpg", "_down.jpg")
result_path= os.path.join(image_cache_dir,image_name_result)
image_bgr = cv2.imread(image_path)
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
image_hsv = cv2.cvtColor(image_rgb, cv2.COLOR_RGB2HSV).astype(np.float32)
h, s, v = cv2.split(image_hsv)
v_mean = np.mean(v)
print(f"v_mean{v_mean}")
if v_mean > 110:
adjusted = apply_curve(image_bgr, lut)
adjusted2 = apply_curve(adjusted, lut)
cv2.imwrite(result_path, adjusted2)
return result_path
else:
image_name_result = image_path.split("/")[-1].replace(".jpg", "_o.jpg")
result_original_path = os.path.join(image_cache_dir, image_name_result)
shutil.copy(image_path, result_original_path)
return result_original_path
def sharpen_image(image_path, output_path):
"""
修复颜色问题的锐化处理函数
"""
# 1. 读取图片并确保RGB格式
image = cv2.imread(image_path)
if image is None:
raise ValueError("无法读取图片,请检查路径是否正确")
# 2. 转换为RGB并保持一致性
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 3. 使用PIL处理时不再转换
pil_img = Image.fromarray(rgb_image)
# 3.1 锐化处理
enhancer = ImageEnhance.Sharpness(pil_img)
sharpened = enhancer.enhance(2.0)
# 3.2 对比度增强
contrast_enhancer = ImageEnhance.Contrast(sharpened)
final_image = contrast_enhancer.enhance(1.2)
# 4. 转换回numpy数组
cv_image = np.array(final_image)
# 5. 修复颜色问题的非锐化掩蔽
# 先分离通道,分别处理,再合并
b, g, r = cv2.split(cv_image)
def unsharp_channel(channel):
blurred = cv2.GaussianBlur(channel, (0, 0), 3)
return cv2.addWeighted(channel, 1.5, blurred, -0.5, 0)
b_sharp = unsharp_channel(b)
g_sharp = unsharp_channel(g)
r_sharp = unsharp_channel(r)
# 合并通道
sharpened_cv = cv2.merge([b_sharp, g_sharp, r_sharp])
# 6. 保存结果(保持BGR格式)
cv2.imwrite(output_path, cv2.cvtColor(sharpened_cv, cv2.COLOR_RGB2BGR))
def correct_texture_image(input_path,image_result_dir,output_path):
""""""
image_cache_dir= os.path.join(image_result_dir,"cache")
os.makedirs(image_cache_dir, exist_ok=True)
input_path_cure_up = apply_curve_up_image(input_path,image_cache_dir)
input_path_cure_down_result = apply_curve_down_image(input_path_cure_up,image_cache_dir)
print("input_path_correct", input_path_cure_down_result)
shadow_up_path = input_path_cure_down_result.replace(".jpg", "_shadow_shadow_add_color_white_unsharp.jpg")
photoshop_actions_emulation(input_path_cure_down_result, shadow_up_path)
shutil.copy(shadow_up_path,output_path)
time.sleep(1)
try:
shutil.rmtree(image_cache_dir)
except:
print("删除文件错误")
return shadow_up_path
if __name__ == "__main__":
arg = argparse.ArgumentParser()
arg.add_argument('--input_path', type=str, default=f"")
arg.add_argument('--output_path', type=str, default=f"")
args = arg.parse_args()
image_result_dir=os.path.dirname(args.output_path)
os.makedirs(image_result_dir, exist_ok=True)
start_time= time.time()
correct_texture_image(args.input_path,image_result_dir,args.output_path)
end_time = time.time()
total_time = round(end_time - start_time, 2)
"""
DreamTechPS动作F7两次+Shift F7一次
F7加暗*2
Shift F7 公仔*1
公仔 加暗加暗加饱和度上色白位加白锐化
"""
Loading…
Cancel
Save