Open Pin-Jiun opened 1 year ago
功能列表
# ------ My photoshop Release notes ------ # # ver3.0 (2020.10.12) 1. 優化整體程式穩定度 2. 新增油漆工具 (位於 "My color panel" 視窗,可自選色) 3. 新增新視窗 "My control panel",為所有調整的主控版 (之前的調整功能也移至這裡) 4. 同上,同時移除主畫面 "My photoshop" 的所有調整功能 5. 新增可調整RGB分量功能 6. 新增可調整色溫功能 (冷色系、暖色系) 7. 新增銳化功能 8. 新增4種不同模糊功能 9. 新增22種不同 colormap 10. 新增視窗自動調整大小的功能 11. 新增自動將視窗移動至固定位置的功能,以後不用自己移動視窗了! # ver2.0 (2020.10.11) 1. 新增視窗 "My histogram",可以隨時查看現在圖片的 RGB直方圖 2. 新增視窗 "My color panel",可以自己選顏色、自己畫點 # ver1.0 (2020.10.10) 1. 新增儲存檔案功能 2. 離開應用程式的穩定優化 3. 新增關閉程式的文字提示 4. 新增調整光線、對比度功能 5. 新增調整明度、飽和度功能 6. 新增旋轉圖片功能 7. 新增可增加圖片噪點的功能,相當於增加圖片顆粒感
https://www.wongwonggoods.com/all-posts/python/python_opencv/opencv-my-photoshop-v3/
import cv2 import glob import time import math import io import PIL from IPython.display import clear_output import matplotlib import matplotlib.pyplot as plt import numpy as np def modify_colormap(img, case = 0): if case == 0: return img img = cv2.applyColorMap(img, case-1) return img def averaging_Blur(image, kernel_size=5): if kernel_size <= 0: return image try: blurred = cv2.blur(image, (kernel_size, kernel_size)) return blurred except: return image def gaussian_Blur(image, kernel_size=5): if kernel_size <= 0: return image try: blurred = cv2.GaussianBlur(image, (kernel_size, kernel_size), 0) return blurred except: return image def median_Blur(image, kernel_size=5): if kernel_size <= 0: return image try: blurred = cv2.medianBlur(image, kernel_size) return blurred except: return image def Bilateral_Filter(image, kernel_size=5): if kernel_size <= 0: return image try: blurred = cv2.bilateralFilter(image, kernel_size, 75, 75) return blurred except: return image def modify_color_temperature(img, Bvalue=0, Gvalue=0, Rvalue=0): if Bvalue == 0 and Gvalue == 0 and Rvalue == 0: return img # 1.計算三個通道的平均值,並依照平均值調整色調 imgB = img[:, :, 0] imgG = img[:, :, 1] imgR = img[:, :, 2] # 調整色調請調整這邊~~ # 白平衡 -> 三個值變化相同 # 冷色調(增加b分量) -> 除了b之外都增加 # 暖色調(增加r分量) -> 除了r之外都增加 bAve = cv2.mean(imgB)[0] + Bvalue gAve = cv2.mean(imgG)[0] + Gvalue rAve = cv2.mean(imgR)[0] + Rvalue aveGray = (int)(bAve + gAve + rAve) / 3 # 2. 計算各通道增益係數,並使用此係數計算結果 bCoef = aveGray / bAve gCoef = aveGray / gAve rCoef = aveGray / rAve imgB = np.floor((imgB * bCoef)) # 向下取整 imgG = np.floor((imgG * gCoef)) imgR = np.floor((imgR * rCoef)) # 3. 變換後處理 # 將原文第3部分的演算法做修改版,加快速度 imgb = imgB imgb[imgb > 255] = 255 imgg = imgG imgg[imgg > 255] = 255 imgr = imgR imgr[imgr > 255] = 255 final_rgb = np.dstack((imgb, imgg, imgr)).astype(np.uint8) return final_rgb def resize_img(img, scale_percent): # percent of original size width = int(img.shape[1] * scale_percent / 100) height = int(img.shape[0] * scale_percent / 100) dim = (width, height) resize_img = cv2.resize(img, dim, interpolation = cv2.INTER_AREA) return resize_img def rotate_img(img, rotation=0): (h, w, d) = img.shape center = (w // 2, h // 2) # 第一個參數旋轉中心,第二個參數旋轉角度(-順時針/+逆時針),第三個參數縮放比例 M = cv2.getRotationMatrix2D(center, rotation, 1.0) # 第三個參數變化後的圖片大小 rotate_img = cv2.warpAffine(img, M, (w, h)) return rotate_img def gaussian_noise(img, mean=0, sigma=0.1): if sigma == 0: return img # int -> float (標準化) img = img / 255.0 # 隨機生成高斯 noise (float + float) noise = np.random.normal(mean, sigma, img.shape) # noise + 原圖 gaussian_out = img + noise # 所有值必須介於 0~1 之間,超過1 = 1,小於0 = 0 gaussian_out = np.clip(gaussian_out, 0, 1) # 原圖: float -> int (0~1 -> 0~255) gaussian_out = np.uint8(gaussian_out*255) # noise: float -> int (0~1 -> 0~255) noise = np.uint8(noise*255) return gaussian_out def modify_contrast_and_brightness(img, brightness=0 , contrast=0): if brightness == 0 and contrast == 0: return img B = brightness / 255.0 c = contrast / 255.0 k = math.tan((45 + 44 * c) / 180 * math.pi) img = (img - 127.5 * (1 - B)) * k + 127.5 * (1 + B) # 所有值必須介於 0~255 之間,超過255 = 255,小於 0 = 0 img = np.clip(img, 0, 255).astype(np.uint8) return img def modify_lightness_saturation(img, lightness = 0, saturation = 0): if lightness == 0 and saturation == 0: return img # lightness 調整為 "1 +/- 幾 %" # saturation 調整為 "1 +/- 幾 %" origin_img = img # 圖像歸一化,且轉換為浮點型 fImg = img.astype(np.float32) fImg = fImg / 255.0 # 顏色空間轉換 BGR -> HLS hlsImg = cv2.cvtColor(fImg, cv2.COLOR_BGR2HLS) hlsCopy = np.copy(hlsImg) # 亮度調整 hlsCopy[:, :, 1] = (1 + lightness / 100.0) * hlsCopy[:, :, 1] hlsCopy[:, :, 1][hlsCopy[:, :, 1] > 1] = 1 # 應該要介於 0~1,計算出來超過1 = 1 # 飽和度調整 hlsCopy[:, :, 2] = (1 + saturation / 100.0) * hlsCopy[:, :, 2] hlsCopy[:, :, 2][hlsCopy[:, :, 2] > 1] = 1 # 應該要介於 0~1,計算出來超過1 = 1 # 顏色空間反轉換 HLS -> BGR result_img = cv2.cvtColor(hlsCopy, cv2.COLOR_HLS2BGR) result_img = ((result_img * 255).astype(np.uint8)) return result_img def show_histogram(img): fig, ax = plt.subplots() # 畫出 RGB 三種顏色的分佈圖 color = ('b','g','r') # plt.ion() plt.style.use('dark_background') for idx, color in enumerate(color): histogram = cv2.calcHist([img],[idx],None,[256],[0, 256]) ax.plot(histogram, color = color) # ax.xlim([0, 256]) # fig.canvas.tostring_rgb() # plt.savefig("plot_histogram.jpg") # plot_histogram = cv2.imread('plot_histogram.jpg') s, (width, height) = fig.canvas.print_to_buffer() # Option 2a: Convert to a NumPy array. plot_histogram = np.frombuffer(s, np.uint8).reshape((height, width, 4)) # print(plot_histogram.shape) # 顯示調整後的效果 cv2.imshow("My histogram", plot_histogram) cv2.resizeWindow("My histogram", 400, 300) cv2.moveWindow("My histogram", 1000, 600) def modify_sharpen(img, sigma=1): if sigma == 0: return img # sigma = 5、15、25 blur_img = cv2.GaussianBlur(img, (0, 0), sigma) usm = cv2.addWeighted(img, 1.5, blur_img, -0.5, 0) return usm def color_panel(img_copy): def mouse_handler(event, x, y, flags, data): if event == cv2.EVENT_LBUTTONDOWN: if data['painter'] == 1: loDiff=40 upDiff=30 seed = (x,y) h, w = data['img'].shape[:2] mask = np.zeros([h+2, w+2], np.uint8) cv2.floodFill(data['img'], mask, seed, (data['b'], data['g'], data['r']), (loDiff, loDiff, loDiff), (upDiff, upDiff, upDiff), cv2.FLOODFILL_FIXED_RANGE) print("FloodFill at (x, y) = ({}, {})".format(x, y)) # elif data['line'] == 1 and data['line_drawing'] == False: # data['line_drawing'] = True # data['line_x'] = x # data['line_y'] = y # print("Start draw line at (x, y) = ({}, {})".format(x, y)) # for i in range(1000000): # print("\r{}".format(i), end="") # if event == cv2.EVENT_LBUTTONUP: # break # if data['line'] == 1 and data['line_drawing'] == True: # data['line_drawing'] = False # cv2.line(data['img'], (data['line_x'], data['line_y']), (x,y), (data['b'], data['g'], data['r']), 16) # print("End draw line at (x, y) = ({}, {})".format(x, y)) elif data['points'] == 1: # 標記點位置 cv2.circle(data['img'], (x,y), 3, (data['b'], data['g'], data['r']), 5, 16) # 顯示修改的 (x,y) 位置 print("change points: (x, y) = ({}, {})".format(x, y)) else: pass # do nothing data = {} data['img'] = img_copy.copy() data['r'] = cv2.getTrackbarPos('R','My color panel') data['g'] = cv2.getTrackbarPos('G','My color panel') data['b'] = cv2.getTrackbarPos('B','My color panel') data['points'] = cv2.getTrackbarPos('Points','My color panel') # data['line'] = cv2.getTrackbarPos('Line','My color panel') # data['line_drawing'] = False # data['line_x'] = 0 # data['line_y'] = 0 data['painter'] = cv2.getTrackbarPos('Painter','My color panel') color_rgb = np.zeros((300,400,3), np.uint8) color_rgb[:] = [data['b'], data['g'], data['r']] # 利用滑鼠回傳值,資料皆保存於 data dict中 cv2.setMouseCallback("My photoshop", mouse_handler, data) # 改變顯示 window 的內容 # cv2.imshow("My photoshop", data['img']) cv2.imshow('My color panel', color_rgb) cv2.resizeWindow("My color panel", 400, 300) return data['img'] def control_panel(img_copy): rotation = cv2.getTrackbarPos('rotation', 'My control panel') - 180 lightness = cv2.getTrackbarPos('lightness', 'My control panel') - half_MAX_VALUE saturation = cv2.getTrackbarPos('saturation', 'My control panel') - half_BIG_MAX_VALUE brightness = cv2.getTrackbarPos('brightness', 'My control panel') - half_MAX_VALUE contrast = cv2.getTrackbarPos('contrast', 'My control panel') - half_BIG_MAX_VALUE coldvalue = cv2.getTrackbarPos('cold temp', 'My control panel') warmvalue = cv2.getTrackbarPos('warm temp', 'My control panel') Rvalue = cv2.getTrackbarPos('R value', 'My control panel') + coldvalue Gvalue = cv2.getTrackbarPos('G value', 'My control panel') + coldvalue + warmvalue Bvalue = cv2.getTrackbarPos('B value', 'My control panel') + warmvalue sharpen = cv2.getTrackbarPos('sharpen', 'My control panel') noise = cv2.getTrackbarPos('noise', 'My control panel') # every kinds of blur avg_blur = cv2.getTrackbarPos('avg Blur', 'My control panel') gau_blur = cv2.getTrackbarPos('gaussian', 'My control panel') med_blur = cv2.getTrackbarPos('medianBlur', 'My control panel') bil_blur = cv2.getTrackbarPos('Bilateral', 'My control panel') colormap_mode = cv2.getTrackbarPos('Colormap', 'My control panel') # ---------- modify the image ---------- # img_copy = rotate_img(img_copy, rotation) img_copy = modify_lightness_saturation(img_copy, lightness, saturation) img_copy = modify_contrast_and_brightness(img_copy, brightness , contrast) img_copy = modify_color_temperature(img_copy, Bvalue, Gvalue, Rvalue) img_copy = modify_sharpen(img_copy, sigma=sharpen/10) img_copy = gaussian_noise(img_copy, mean=0, sigma=noise/100) img_copy = averaging_Blur(img_copy, avg_blur) img_copy = gaussian_Blur(img_copy, gau_blur) img_copy = median_Blur(img_copy, med_blur) img_copy = Bilateral_Filter(img_copy, bil_blur) img_copy = modify_colormap(img_copy, colormap_mode) return img_copy # 讀取彩色圖像 img = cv2.imread('./testdata/cat.jpg', cv2.IMREAD_COLOR) h, w, dim = img.shape # control analysis size if h>=1000 or w>=1000: img = resize_img(img, scale_percent=30) h, w, dim = img.shape half_MAX_VALUE = 100 half_BIG_MAX_VALUE = 255 window_flags = cv2.WINDOW_AUTOSIZE # WINDOW_AUTOSIZE # 修圖主視窗 cv2.namedWindow("My photoshop", window_flags) # cv2.WINDOW_NORMAL) cv2.resizeWindow("My photoshop", 1280, 720) cv2.moveWindow("My photoshop", 0, 0) # 直方圖視窗 cv2.namedWindow("My histogram", window_flags) # cv2.WINDOW_NORMAL) cv2.resizeWindow("My histogram", 400, 300) cv2.moveWindow("My histogram", 1000, 600) # 控制顏色 cv2.namedWindow("My color panel", window_flags) # cv2.WINDOW_NORMAL) cv2.resizeWindow("My color panel", 400, 300) cv2.moveWindow("My color panel", 1000, 0) # 主控台視窗 cv2.namedWindow("My control panel", window_flags) # cv2.WINDOW_NORMAL) cv2.resizeWindow("My control panel", 400, 800) cv2.moveWindow("My control panel", 1500, 0) def nothing(*arg): pass # create trackbars for color change cv2.createTrackbar('R','My color panel', 0, 255, nothing) cv2.createTrackbar('G','My color panel', 0, 255, nothing) cv2.createTrackbar('B','My color panel', 0, 255, nothing) cv2.createTrackbar('Points','My color panel', 0, 1, nothing) # cv2.createTrackbar('Line','My color panel', 0, 1, nothing) cv2.createTrackbar('Painter','My color panel', 0, 1, nothing) # 滑動塊 cv2.createTrackbar("rotation", "My control panel", 180, 2*180, nothing) cv2.createTrackbar("brightness", "My control panel", half_MAX_VALUE, 2*half_MAX_VALUE, nothing) # 亮度 cv2.createTrackbar("contrast", "My control panel", half_BIG_MAX_VALUE, 2*half_BIG_MAX_VALUE, nothing) # 對比 cv2.createTrackbar("lightness", "My control panel", half_MAX_VALUE, 2*half_MAX_VALUE, nothing) # 亮度 cv2.createTrackbar("saturation", "My control panel", half_BIG_MAX_VALUE, 2*half_BIG_MAX_VALUE, nothing) # 飽和度 cv2.createTrackbar("R value", "My control panel", 0, half_MAX_VALUE, nothing) # 色溫 R cv2.createTrackbar("G value", "My control panel", 0, half_MAX_VALUE, nothing) # 色溫 G cv2.createTrackbar("B value", "My control panel", 0, half_MAX_VALUE, nothing) # 色溫 B cv2.createTrackbar("cold temp", "My control panel", 0, half_MAX_VALUE, nothing) # 色溫 cold cv2.createTrackbar("warm temp", "My control panel", 0, half_MAX_VALUE, nothing) # 色溫 warm cv2.createTrackbar("sharpen", "My control panel", 0, half_MAX_VALUE, nothing) # 銳化 cv2.createTrackbar("noise", "My control panel", 0, half_MAX_VALUE, nothing) # 顆粒點 # every kinds of blur cv2.createTrackbar("avg Blur", "My control panel", 0, half_MAX_VALUE, nothing) cv2.createTrackbar("gaussian", "My control panel", 0, half_MAX_VALUE, nothing) cv2.createTrackbar("medianBlur", "My control panel", 0, half_MAX_VALUE, nothing) cv2.createTrackbar("Bilateral", "My control panel", 0, half_MAX_VALUE, nothing) cv2.createTrackbar("Colormap", "My control panel", 0, 22, nothing) # colormap # 調整飽和度和亮度 while True: # time.sleep(0.001) # for better memory use # h, w, dim = img_copy.shape # My color panel (some will change and no reverse) img = color_panel(img) img_copy = np.copy(img) # My color panel (some will change and can reverse) img_copy = control_panel(img_copy) show_histogram(img_copy) ch = cv2.waitKey(5) if ch == 27: # 按 ESC 鍵退出 break elif ch == ord('s'): # 按 s 鍵保存結果並退出 cv2.imwrite("result.jpg", img_copy) break # add message msg = "Press ESC to exit, or press S to save and exit." img_copy = cv2.putText(img_copy, msg, (10, h-10), cv2.FONT_HERSHEY_COMPLEX, 0.5, (255, 255, 255), 1, cv2.LINE_AA) # 顯示調整後的效果 cv2.imshow("My photoshop", img_copy) # 關閉所有的窗口 cv2.destroyAllWindows()
功能列表
https://www.wongwonggoods.com/all-posts/python/python_opencv/opencv-my-photoshop-v3/