建模程序 多个定时程序
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.
 
 

469 lines
15 KiB

import os.path
import shutil
import time
import argparse
import cv2
import numpy as np
from scipy.interpolate import CubicSpline
import sys, os
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from fix_up_color_two_a import remove_gray_and_sharpening
from ps_image_shadow_up_ag_two_a import photoshop_actions_emulation
# def perceptual_adjustment(img, threshold=220, reduction=0.5):
# hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# h, s, v = cv2.split(hsv)
#
# saturation_weights = 1 - (s.astype(np.float32) / 255 * 0.01)
#
# adjusted_v = np.where(
# v > threshold,
# threshold + (v - threshold) * (1 - reduction * saturation_weights),
# v
# )
#
# return cv2.cvtColor(cv2.merge([h, s, adjusted_v.astype(np.uint8)]), cv2.COLOR_HSV2BGR)
# def perceptual_smooth_adjustment(img, threshold=220, reduction=0.5,margin=5, saturation_sensitivity=0.3):
# """
# 感知式亮度压制 + 过渡区平滑(防止硬边)
#
# 参数:
# - threshold: 高光压制起点
# - margin: 过渡带宽度(像素值差)
# - reduction: 压制比例(1 表示最多降低100%)
# - saturation_sensitivity: 饱和度影响权重
# """
# hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# h, s, v = cv2.split(hsv)
#
# v = v.astype(np.float32)
# s = s.astype(np.float32)
#
# # 1. 饱和度感知权重(饱和度越高,压制越弱)
# sat_weight = 1.0 - (s / 255.0 * saturation_sensitivity)
# sat_weight = np.clip(sat_weight, 0.0, 1.0)
#
# # 2. 构建平滑过渡权重(根据 V 值)
# transition_mask = np.zeros_like(v, dtype=np.float32)
# transition_mask[v <= threshold] = 0.0
# transition_mask[v >= threshold + margin] = 1.0
#
# # 线性过渡区域
# in_between = (v > threshold) & (v < threshold + margin)
# transition_mask[in_between] = (v[in_between] - threshold) / margin
#
# # 3. 计算最终压制权重(融合过渡 + 饱和度感知)
# weight = reduction * transition_mask * sat_weight
#
# # 4. 应用压制
# v_adjusted = v - (v - threshold) * weight
# v_adjusted = np.clip(v_adjusted, 0, 255).astype(np.uint8)
#
# # 5. 合成并返回
# adjusted_hsv = cv2.merge([h, s.astype(np.uint8), v_adjusted])
# result_bgr = cv2.cvtColor(adjusted_hsv, cv2.COLOR_HSV2BGR)
#
# return result_bgr
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 perceptual_smooth_adjustment(img, threshold=220, reduction=0.5, margin=10, saturation_sensitivity=0.3, blur_radius=3):
# """
# 感知式亮度压制 + 平滑过渡 + 边缘柔化
#
# 参数:
# - threshold: 开始压制的亮度阈值
# - reduction: 最大压制比例(1 表示压到底)
# - margin: 过渡宽度(单位是亮度值差)
# - saturation_sensitivity: 饱和度越高,压制越弱
# - blur_radius: 最终压制结果边缘模糊程度(建议 3)
# """
# # 转 HSV 获取亮度与饱和度
# hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# h, s, v = cv2.split(hsv)
#
# v = v.astype(np.float32)
# s = s.astype(np.float32)
#
# # 1. 饱和度影响(越高压制越少)
# sat_weight = 1.0 - (s / 255.0 * saturation_sensitivity)
# sat_weight = np.clip(sat_weight, 0.0, 1.0)
#
# # 2. 构造更平滑的过渡权重(使用 smootherstep)
# 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 # 完全压制区域
#
# # 3. 亮度压制权重
# weight = reduction * transition * sat_weight
#
# # 4. 应用压制
# v_new = v - (v - threshold) * weight
# v_new = np.clip(v_new, 0, 255).astype(np.uint8)
#
# # 5. 合并回 HSV 并转回 BGR
# adjusted_hsv = cv2.merge([h, s.astype(np.uint8), v_new])
# result = cv2.cvtColor(adjusted_hsv, cv2.COLOR_HSV2BGR)
#
# # 6. 进一步边缘模糊(仅作用于过渡区域)
# blur_mask = (transition > 0.0) & (transition < 1.0)
# blur_mask = blur_mask.astype(np.uint8) * 255
# blur_mask = cv2.GaussianBlur(blur_mask, (blur_radius|1, blur_radius|1), 0)
#
# # 创建模糊版本
# blurred = cv2.GaussianBlur(result, (blur_radius|1, blur_radius|1), 0)
#
# # 混合:边缘模糊区域取模糊图,其他保持原图
# blur_mask = blur_mask.astype(np.float32) / 255.0
# result = result.astype(np.float32)
# blurred = blurred.astype(np.float32)
#
# final = result * (1 - blur_mask[..., None]) + blurred * blur_mask[..., None]
# 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)
count=0
while True:
# image_path="/data/datasets_20t/Downloads_google/correct_show_obj/265340/265340Tex1.jpg"
# result_path = "/data/datasets_20t/Downloads_google/correct_show_obj/265340/265340Tex1_new.jpg"
if os.path.exists(result_path):
image_bgr = cv2.imread(result_path)
else:
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)
h_mean = np.mean(h)
s_mean = np.mean(s)
v_mean = np.mean(v)
print(f"v_mean{v_mean}")
if v_mean<60:
adjusted = apply_curve(image_bgr, lut)
cv2.imwrite(result_path, adjusted)
time.sleep(1)
count=count+1
else:
break
if count>=1:
cv2.imwrite(result_path, adjusted)
time.sleep(1)
break
if os.path.exists(result_path):
return result_path
else:
return None
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)
count = 0
while True:
# image_path="/data/datasets_20t/Downloads_google/correct_show_obj/265340/265340Tex1.jpg"
# result_path = "/data/datasets_20t/Downloads_google/correct_show_obj/265340/265340Tex1_new.jpg"
if os.path.exists(result_path):
image_bgr = cv2.imread(result_path)
else:
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)
h_mean = np.mean(h)
s_mean = np.mean(s)
v_mean = np.mean(v)
print(f"v_mean{v_mean}")
if v_mean > 110:
adjusted = apply_curve(image_bgr, lut)
cv2.imwrite(result_path, adjusted)
time.sleep(1)
count=count+1
else:
break
if count >= 1:
cv2.imwrite(result_path, adjusted)
time.sleep(1)
break
if os.path.exists(result_path):
return result_path
else:
return None
def correct_texture_image(input_path,image_result_dir,output_path):
""""""
#input_path = os.path.join(image_in_dir, image_name)
params = {
'threshold': 220,
'reduction': 0.6
}
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)
if input_path_cure_up:
input_path_cure_down = input_path_cure_up
else:
input_path_cure_down = input_path
input_path_cure_down_result = apply_curve_down_image(input_path_cure_down,image_cache_dir)
if input_path_cure_down_result:
input_path_correct = input_path_cure_down_result
else:
input_path_correct = input_path_cure_down
print("input_path_correct", input_path_correct)
#image_name = input_path_correct.split("/")[-1]
#out_put_path = os.path.join(image_cache_dir, image_name)
image_light_down_fix_up_path = remove_gray_and_sharpening(input_path_correct, image_cache_dir)
shadow_up_path = image_light_down_fix_up_path.replace(".jpg", "_shadow_up.jpg")
photoshop_actions_emulation(image_light_down_fix_up_path, shadow_up_path)
output_light_up_path = shadow_up_path.replace(".jpg", "_light_down.jpg")
process_image(shadow_up_path, output_light_up_path, **params)
#output_result_image_path=correct_light_again_hsv(output_light_up_path)
shutil.copy(output_light_up_path,output_path)
time.sleep(1)
try:
shutil.rmtree(image_cache_dir)
except:
print("删除文件错误")
return output_light_up_path
if __name__ == "__main__":
arg = argparse.ArgumentParser()
arg.add_argument("-i","--image_path", type=str, default="")
args = arg.parse_args()
image_result_dir=os.path.dirname(args.image_path)
os.makedirs(image_result_dir, exist_ok=True)
start_time= time.time()
correct_texture_image(args.image_path,image_result_dir,args.image_path)
end_time = time.time()
total_time = round(end_time - start_time, 2)
print(f"处理成功,耗时 {total_time} 秒,")
"""
1、暗部提亮->白色提纯(220)->高光压暗->二次亮度调整
"""