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 < 50: adjusted = apply_curve(image_bgr, lut) adjusted2 = apply_curve(adjusted, lut) adjusted3 = apply_curve(adjusted2, lut) cv2.imwrite(result_path, adjusted3) 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 > 50: 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) """ DreamTech,PS动作F7两次+Shift F7一次 F7:::加暗*2+1 Shift F7 公仔*1 公仔: 加暗,加暗,加饱和度上色,白位加白,锐化 ps版本2020 """