建模程序 多个定时程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

368 lines
12 KiB

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)
人种