import cv2 import numpy as np import torch from PIL import Image import torchvision import functools import inspect # 套用裝飾器到現有函數 def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0): """使用OpenCV實現的Unsharp Mask銳化處理 參數: image: PIL.Image對象(RGB格式) kernel_size: 高斯模糊的核大小,必須是奇數 sigma: 高斯模糊的標準差 amount: 銳化程度,值越大效果越強 threshold: 邊緣檢測閾值,僅在邊緣處進行銳化 返回: 銳化後的PIL.Image對象 """ # 轉換PIL圖像為numpy數組 numpy_img = np.array(image, dtype=np.uint8) # 對原圖進行高斯模糊 blurred = cv2.GaussianBlur(numpy_img, kernel_size, sigma) # 計算銳化後的圖像 sharpened = cv2.addWeighted(numpy_img, 1 + amount, blurred, -amount, 0) # 如果設置了threshold,只在邊緣處應用銳化 if threshold > 0: low_contrast_mask = np.absolute(numpy_img - blurred) < threshold np.copyto(sharpened, numpy_img, where=low_contrast_mask) # 確保像素值在有效範圍內 sharpened = np.clip(sharpened, 0, 255).astype(np.uint8) # 轉回PIL圖像 return Image.fromarray(sharpened) def histogram_equalization(image): """GPU加速的一般直方圖等化 參數: image: PIL.Image對象(RGB格式) 返回: 直方圖等化後的PIL.Image對象 """ # 轉換為numpy數組並轉為PyTorch張量 numpy_img = np.array(image) tensor_img = torch.from_numpy(numpy_img).float().to('cuda') # 分離通道並進行直方圖等化 result = torch.zeros_like(tensor_img) for i in range(3): # 對RGB三個通道分別處理 channel = tensor_img[..., i] # 計算直方圖 hist = torch.histc(channel, bins=256, min=0, max=255) # 計算累積分布函數(CDF) cdf = torch.cumsum(hist, dim=0) cdf_normalized = ((cdf - cdf.min()) * 255) / (cdf.max() - cdf.min()) # 應用直方圖等化 result[..., i] = cdf_normalized[channel.long()] # 轉回CPU和numpy數組 result = torch.clamp(result, 0, 255).byte() result_np = result.cpu().numpy() return Image.fromarray(result_np) def Contrast_Limited_Adaptive_Histogram_Equalization(image, clip_limit=3.0, tile_size=(8, 8)): """使用OpenCV實現的對比度限制自適應直方圖均衡化(CLAHE) 參數: image: PIL.Image對象(RGB格式) clip_limit: 剪切限制,用於限制對比度增強的程度,較大的值會產生更強的對比度 tile_size: 圖像分塊大小的元組(height, width),較小的值會產生更局部的增強效果 返回: CLAHE處理後的PIL.Image對象 """ # 將PIL圖像轉換為OpenCV格式(BGR) numpy_img = np.array(image) bgr_img = cv2.cvtColor(numpy_img, cv2.COLOR_RGB2BGR) # 轉換到LAB色彩空間 lab_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2LAB) # 創建CLAHE對象 clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=tile_size) # 分離LAB通道 l, a, b = cv2.split(lab_img) # 對L通道應用CLAHE l_clahe = clahe.apply(l) # 合併處理後的L通道與原始的a和b通道 lab_output = cv2.merge([l_clahe, a, b]) # 將LAB轉回BGR,然後轉換為RGB bgr_output = cv2.cvtColor(lab_output, cv2.COLOR_LAB2BGR) rgb_output = cv2.cvtColor(bgr_output, cv2.COLOR_BGR2RGB) # 轉換為PIL圖像並返回 return Image.fromarray(rgb_output) def adaptive_histogram_equalization_without_limit(image, tile_size=(8, 8)): """使用OpenCV實現的自適應直方圖均衡化(AHE) 參數: image: PIL.Image對象(RGB格式) tile_size: 圖像分塊大小的元組(height, width),較小的值會產生更局部的增強效果 返回: AHE處理後的PIL.Image對象 """ # 將PIL圖像轉換為OpenCV格式(BGR) numpy_img = np.array(image) bgr_img = cv2.cvtColor(numpy_img, cv2.COLOR_RGB2BGR) # 轉換到LAB色彩空間 lab_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2LAB) # 分離LAB通道 l, a, b = cv2.split(lab_img) # 創建AHE對象(不設置clip limit) clahe = cv2.createCLAHE(clipLimit=None, tileGridSize=tile_size) # 對L通道應用AHE l_ahe = clahe.apply(l) # 合併處理後的L通道與原始的a和b通道 lab_output = cv2.merge([l_ahe, a, b]) # 將LAB轉回BGR,然後轉換為RGB bgr_output = cv2.cvtColor(lab_output, cv2.COLOR_LAB2BGR) rgb_output = cv2.cvtColor(bgr_output, cv2.COLOR_BGR2RGB) # 轉換為PIL圖像並返回 return Image.fromarray(rgb_output) def laplacian_sharpen(image): """ GPU加速的拉普拉斯銳化處理函數 參數: image: PIL.Image對象(RGB格式) 返回: 銳化後的PIL.Image對象 """ # 轉換為numpy數組並轉為PyTorch張量 numpy_img = np.array(image) tensor_img = torch.from_numpy(numpy_img).float().to('cuda') # 創建拉普拉斯算子 laplacian_kernel = torch.tensor([ [0, 1, 0], [1, -4, 1], [0, 1, 0] ], dtype=torch.float32, device='cuda').unsqueeze(0).unsqueeze(0) # 對每個通道進行處理 result = torch.zeros_like(tensor_img) for i in range(3): # RGB三個通道 channel = tensor_img[..., i] # 添加批次和通道維度 channel = channel.unsqueeze(0).unsqueeze(0) # 應用拉普拉斯算子 laplacian = torch.nn.functional.conv2d(channel, laplacian_kernel, padding=1) # 移除批次和通道維度 laplacian = laplacian.squeeze() # 銳化處理:原圖 - 拉普拉斯 result[..., i] = channel.squeeze() - laplacian # 確保像素值在合理範圍內 result = torch.clamp(result, 0, 255).byte() # 轉回CPU和numpy數組 result_np = result.cpu().numpy() return Image.fromarray(result_np) def adjust_hsv(image, v_adjustment=0): """調整圖像的HSV色彩空間中的H和V通道 參數: image: PIL.Image對象(RGB格式) v_adjustment: V通道的調整值,範圍建議在[-255, 255]之間 返回: HSV調整後的PIL.Image對象 """ # 將PIL圖像轉換為OpenCV格式(BGR) numpy_img = np.array(image) bgr_img = cv2.cvtColor(numpy_img, cv2.COLOR_RGB2BGR) # 轉換到HSV色彩空間 hsv_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV) # 調整V通道 hsv_img[..., 2] = np.clip(hsv_img[..., 2] + v_adjustment, 0, 255) # 將HSV轉回BGR,然後轉換為RGB bgr_output = cv2.cvtColor(hsv_img, cv2.COLOR_HSV2BGR) rgb_output = cv2.cvtColor(bgr_output, cv2.COLOR_BGR2RGB) # 轉換為PIL圖像並返回 return Image.fromarray(rgb_output) def gamma_correction(image, gamma=1.0): """對圖像進行伽馬校正 參數: image: PIL.Image對象(RGB格式) gamma: 伽馬值,gamma > 1 時圖像變暗,gamma < 1 時圖像變亮,gamma = 1 時保持不變 返回: 伽馬校正後的PIL.Image對象 """ # 將PIL圖像轉換為numpy數組 numpy_img = np.array(image) # 將像素值歸一化到[0, 1]範圍 normalized = numpy_img.astype(float) / 255.0 # 應用伽馬校正 corrected = np.power(normalized, gamma) # 將值縮放回[0, 255]範圍 output = np.clip(corrected * 255.0, 0, 255).astype(np.uint8) # 轉換回PIL圖像並返回 return Image.fromarray(output) def Hight_Light(image, Threshold): image = np.array(image) gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 使用閾值檢測高光點(白色液滴) _, thresh = cv2.threshold(gray, Threshold, 255, cv2.THRESH_BINARY) # 使用形態學操作(膨脹)來擴大遮罩區域 kernel = np.ones((5, 5), np.uint8) dilated = cv2.dilate(thresh, kernel, iterations=1) # 使用 inpaint 修復高光點 image_inpaint = cv2.inpaint(image, dilated, 3, cv2.INPAINT_TELEA) return Image.fromarray(image_inpaint) def median_filter(image: Image.Image, kernel_size: int = 3): """ 中值濾波(Median Filter)實現 參數: image: PIL.Image對象(RGB格式) kernel_size: 濾波核大小,必須是奇數 返回: 濾波後的PIL.Image對象 """ # 確保kernel_size是奇數 if kernel_size % 2 == 0: kernel_size += 1 # 轉換PIL圖像為numpy數組 numpy_img = np.array(image, dtype=np.uint8) # 對每個通道應用中值濾波 result = np.zeros_like(numpy_img) for i in range(3): # 對RGB三個通道分別處理 result[:, :, i] = cv2.medianBlur(numpy_img[:, :, i], kernel_size) # 確保像素值在有效範圍內 result = np.clip(result, 0, 255).astype(np.uint8) # 轉回PIL圖像 return Image.fromarray(result) def mean_filter(image: Image.Image, kernel_size: int = 3): """ 均質濾波(Mean Filter)實現 參數: image: PIL.Image對象(RGB格式) kernel_size: 濾波核大小,必須是奇數 返回: 濾波後的PIL.Image對象 """ # 確保kernel_size是奇數 if kernel_size % 2 == 0: kernel_size += 1 # 轉換PIL圖像為numpy數組 numpy_img = np.array(image, dtype=np.uint8) # 創建均質濾波核(所有元素都是1/(kernel_size*kernel_size)) kernel = np.ones((kernel_size, kernel_size), np.float32) / (kernel_size * kernel_size) # 對每個通道應用均質濾波 result = np.zeros_like(numpy_img) for i in range(3): # 對RGB三個通道分別處理 result[:, :, i] = cv2.filter2D(numpy_img[:, :, i], -1, kernel) # 確保像素值在有效範圍內 result = np.clip(result, 0, 255).astype(np.uint8) # 轉回PIL圖像 return Image.fromarray(result)