iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
1
Software Development

【錢不夠買ps的我,只好用OpenCV來修圖了!】系列 第 9

【沒錢ps,我用OpenCV!】Day 9 - 日系濾鏡6,運用 OpenCV 降低圖片的高光 reduce highlights

先來看看今天的結果圖

-> 為了凸顯本文效果,我有特別將效果加強,但實際使用還是要依個人喜好去調整

(可以看到高光源的地方都已經被模糊處理掉了!)

https://ithelp.ithome.com.tw/upload/images/20200920/20120424iHRfKWS0wS.png

-> 此篇文章的程式碼 github

Day09_降低高光_reduce_highlights.ipynb

前言

我們繼續製作屬於自己的日系濾鏡啦!
日系濾鏡的修圖過程,大致上有以下步驟:

文章 階段目標
【Day4】 1. 調亮光線 (調整光線)
【Day5】 2. 加強飽和度 (調整飽和度)
【Day6】 3. 將照片調成冷色調
【Day7】 4. 增添顆粒感
【Day8】 5. 降低對比
【Day9】 6. 降低高光

接下來的日子裡我們就來一個個用程式碼實現!

運用 OpenCV 降低圖片的高光

def reduce_highlights(img):
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 先轉成灰階處理
    ret, thresh = cv2.threshold(img_gray, 200, 255, 0)  # 利用 threshold 過濾出高光的部分,目前設定高於 200 即為高光
    contours, hierarchy  = cv2.findContours(thresh.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    img_zero = np.zeros(img.shape, dtype=np.uint8) 
    
#     print(len(contours))

    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour) 
        img_zero[y:y+h, x:x+w] = 255 
        mask = img_zero 

    print("Highlight part: ")
    show_img(mask)
    
    # alpha,beta 共同決定高光消除後的模糊程度
    # alpha: 亮度的缩放因子,默認是 0.2, 範圍[0, 2], 值越大,亮度越低
    # beta:  亮度缩放後加上的参数,默認是 0.4, 範圍[0, 2],值越大,亮度越低
    result = cv2.illuminationChange(img, mask, alpha=0.2, beta=0.4) 
    show_img(result)
        
    return result

我們實際上做了什麼事呢?

我們使用了 cv2.illuminationChange 這個函數,有模糊高光的效果,
在 OpenCV 中似乎是比較冷門的函數 (因為網路上資料超少......),
上面的程式碼也幾乎是我自己寫的......(網路上有C++版本,但沒有python版本)

簡單來說 cv2.illuminationChange 這個函數
cv2.illuminationChange(img, mask, alpha=0.2, beta=0.4)

  • 第一個參數放我們的圖片
  • 第二個參數放遮罩mask (也就是找到強光的地方,下面會再說明怎麼找)
  • 第三個參數 alpha,亮度的缩放因子,默認是 0.2, 範圍[0, 2], 值越大,亮度越低
  • 第四個參數 beta,亮度缩放後加上的参数,默認是 0.4, 範圍[0, 2],值越大,亮度越低

至於我們怎麼找到我們的遮罩(mask)呢?

我們使用了 cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 先將原圖轉成了灰階,
然後對灰階圖片使用 cv2.threshold(img_gray, 200, 255, 0)
我們利用了 threshold 過濾出高光的部分,目前設定高於 200 即認定為高光,
然後再使用 cv2.findContours 找出這些我們所要的輪廓。

cv2.findContours 找出的輪廓被儲存在 list 中,
我們必須將他讀出來並做圖,因此才有這一段程式碼,

for contour in contours:
    x, y, w, h = cv2.boundingRect(contour) 
    img_zero[y:y+h, x:x+w] = 255 
    mask = img_zero    

目的就是為了產生遮罩用的圖片,方便我們做 cv2.illuminationChange 這個函數的運算。

最後來看一下比較正常一點的結果

第一張圖片我所設的參數為 alpha=0.2, beta=0.4
但個人覺得他模糊高光的效果有點過頭了,
因此調了一下參數,產生了以下 alpha=0.2, beta=0.2 的版本。

https://ithelp.ithome.com.tw/upload/images/20200920/20120424JpvfC4TYJF.png

Reference

https://www.pythonf.cn/read/57067

https://kknews.cc/zh-tw/code/oka9mbm.html

https://blog.csdn.net/zh_jessica/article/details/77967650

https://www.cnblogs.com/lfri/p/10627595.html


上一篇
【沒錢ps,我用OpenCV!】Day 8 - 日系濾鏡5,運用 OpenCV 改變圖片的對比度 modify contrast (內含:網路上常見錯誤調整對比度方式的分析)
下一篇
【沒錢ps,我用OpenCV!】Day 10 - 日系濾鏡總集篇,運用 OpenCV 製作屬於自己的濾鏡吧 (內含可於網頁上直接完成濾鏡的 colab )
系列文
【錢不夠買ps的我,只好用OpenCV來修圖了!】30

尚未有邦友留言

立即登入留言