ReportGeneratorLocal/tool/lighter.py

176 lines
7.1 KiB
Python
Raw Normal View History

import cv2
import numpy as np
# import rawpy
# from PIL import Image
# from tqdm import tqdm
# import tkinter as tk
#from tkinter import filedialog
#from concurrent.futures import ThreadPoolExecutor
#import argparse
#import os
#import torch
#from depth_anything_v2.dpt import DepthAnythingV2
#from utils import specify_name_group_blade,get_name
#parser = argparse.ArgumentParser(description='Depth Anything V2')
# parser.add_argument('--input-size', type=int, default=518)
# parser.add_argument('--encoder', type=str, default='vitl', choices=['vits', 'vitb', 'vitl', 'vitg'])
# args = parser.parse_args()
def extraction_win_lamina_mask(raw_image, depth_anything):
# 前面读的都是RGB图像深度估计需要BGR即下面是把RGB→BGR
raw_image = cv2.cvtColor(raw_image, cv2.COLOR_BGR2RGB)
depth = depth_anything.infer_image(raw_image)
depth = (depth - depth.min()) / (depth.max() - depth.min()) * 255.0
depth = depth.astype(np.uint8)
_, otsu_mask = cv2.threshold(depth, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
return otsu_mask
def check_overexposure(image, lamina_mask,threshold):
"""
检查图像中是否有过曝区域
:param image: 输入图像
:param threshold: 亮度值的阈值像素值超过该值则认为是过曝区域
:return: 一个二值图像过曝区域为白色其它区域为黑色
"""
# 转换为浮动数据类型并归一化
image_float = image.astype(np.float32)
# 获取每个像素的亮度值(可以使用 YUV 或 RGB 亮度)
gray_image = cv2.cvtColor(image_float, cv2.COLOR_BGR2GRAY)
# 标记过曝区域,亮度大于阈值的像素为过曝区域
overexposure_mask = gray_image > threshold
overexposure_mask = (lamina_mask == 255) & overexposure_mask #只取叶片的亮光区mask
overexposure_number = np.sum(overexposure_mask * 1)
overexposed_pixels = gray_image[overexposure_mask]
# 计算曝光区域的平均亮度
if overexposed_pixels.size > 0:
avg_overexposed_value = np.mean(overexposed_pixels)
else:
avg_overexposed_value = 0 # 如果没有曝光区域,返回 0
return overexposure_mask, avg_overexposed_value,overexposure_number
def check_shawn(image,lamina_mask, threshold):
"""
检查图像中是否有阴影区域
:param image: 输入图像
:param threshold: 亮度值的阈值像素值小于该值则认为是过阴影域
:return: 一个二值图像过曝区域为白色其它区域为黑色
"""
# 转换为浮动数据类型并归一化
image_float = image.astype(np.float32)
# 获取每个像素的亮度值(可以使用 YUV 或 RGB 亮度)
gray_image = cv2.cvtColor(image_float, cv2.COLOR_BGR2GRAY)
# 标记阴影区域,亮度小于阈值的像素为阴影区域
shawn_mask = gray_image < threshold
shawn_mask = (lamina_mask == 255) & shawn_mask
shawn_number = np.sum(shawn_mask * 1)
shawn_pixels = gray_image[shawn_mask]
# 计算阴影区域的平均亮度
if shawn_pixels.size > 0:
avg_shawn_value = np.mean(shawn_pixels)
else:
avg_shawn_value = 0
return shawn_mask, avg_shawn_value,shawn_number
def smooth_overexposed_regions(image, overexposure_mask, kernel_size=(15, 15)):
"""
对过曝区域进行平滑处理修复与周围区域的过渡
:param image: 输入图像
:param overexposure_mask: 过曝区域的掩码
:param kernel_size: 高斯核大小
:return: 平滑过曝区域后的图像
"""
# 使用高斯模糊平滑过曝区域和周围区域
smoothed_image = cv2.GaussianBlur(image, kernel_size, 0)
# 将平滑后的图像和原始图像合成,修复过曝区域
fixed_image = np.where(overexposure_mask[..., None] == 255, image,smoothed_image)
return fixed_image
def bilateral_filter_adjustment(image, high_light_mask, d=15, sigma_color=75, sigma_space=75):
"""
使用双边滤波器平滑高光区域与周围区域的过渡
:param image: 输入图像
:param high_light_mask: 高光区域的掩码
:param d: 邻域的直径
:param sigma_color: 颜色空间的标准差
:param sigma_space: 坐标空间的标准差
:return: 平滑后的图像
"""
# 对整个图像应用双边滤波
filtered_image = cv2.bilateralFilter(image, d, sigma_color, sigma_space)
# 合成平滑后的图像和原图,保留非高光部分
final_image = np.where(high_light_mask[..., None] == 0, image, filtered_image)
return final_image
def adjust_highlights_shadows(image, threshold_shawn,threshold, depth_anything):
lamina_mask = extraction_win_lamina_mask(image, depth_anything)
shawn_mask,avg_shawn_value,shawn_number = check_shawn(image,lamina_mask,threshold_shawn)
# 调整亮度gamma < 1 时变亮gamma > 1 时变暗
gamma = 1 - (threshold_shawn-avg_shawn_value)/255.0
# print('阴影区调整的gama: '+str(gamma))#+str('\n'))
lookup_table = np.array([((i / 255.0) ** gamma) * 255 for i in range(256)]).astype('uint8')
# 应用 gamma 校正
if shawn_number !=0:
image[shawn_mask == True] = cv2.LUT(image[shawn_mask == True], lookup_table)
gamma_corrected_image = image
else:
gamma_corrected_image = image
#gamma_corrected_image = cv2.LUT(image, lookup_table)
#寻找过爆区域
overexposure_mask,avg_overexposed_value,overexposure_number = check_overexposure(gamma_corrected_image,lamina_mask,threshold)
reduction_factor = 1-(avg_overexposed_value-threshold) / 255
#reduction_factor = (avg_overexposed_value/255)*scale
# print("降低曝光区比例:" + str(reduction_factor))
# 调整亮度gamma < 1 时变亮越小越亮gamma > 1 时变暗(越大越暗)
print((1+reduction_factor))
lookup_table = np.array([((i / 255.0) ** (1+reduction_factor)) * 255 for i in range(256)]).astype('uint8')
# 应用 gamma 校正
if overexposure_number !=0:
gamma_corrected_image[overexposure_mask == True] = cv2.LUT(gamma_corrected_image[overexposure_mask == True], lookup_table)
#gamma_corrected_image[overexposure_mask == True] = np.clip(gamma_corrected_image[overexposure_mask == True] * reduction_factor, 0, 255)
#smoothed_image = smooth_overexposed_regions(gamma_corrected_image, overexposure_mask)
#smoothed_image = bilateral_filter_adjustment(gamma_corrected_image, overexposure_mask, d=15, sigma_color=75, sigma_space=75)
return gamma_corrected_image
# path=r'/home/dtyx/下载/1_涂层损伤_叶尖3m_2m_一般_紧急_一般_尽快打磨维修.jpg'
# from time import time
# if __name__ == "__main__":
# # input_dir = input("请输入处理图片路径: ")
# # output_dir = input("请输入保存图片路径: ")
# time_start = time()
# imgpath = path
# img = cv2.imdecode(np.fromfile(imgpath, dtype=np.uint8), cv2.IMREAD_COLOR)
# cv2.imshow('img',cv2.resize(img,(800,600)))
# mask=adjust_highlights_shadows(img,180,253)
# mask=cv2.resize(mask,(800,600))
# time_end = time()
# print("Time used:", time_end - time_start)
# cv2.imshow('mask',mask)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# # gamma = float(input("请输入 gamma 值: "))