1. 程式人生 > >Python-OpenCV 影象加權混合(濾色, 疊加, 柔光, 強光)

Python-OpenCV 影象加權混合(濾色, 疊加, 柔光, 強光)

一、影象混合原理

1.1 濾色模式:

作用結果和正片疊底剛好相反,它是將兩個顏色的互補色的畫素值相乘,然後除以255得到的最終色的畫素值。

  • 通常執行濾色模式後的顏色都較淺: 任何顏色和黑色執行濾色,原色不受影響; 任何顏色和白色執行濾色得到的是白色; 而與其他顏色執行濾色會產生漂白的效果。
  • Screen 濾色 C=1(1A)×(1B)C=1-(1-A)×(1-B) 也可以寫成 1-C=(1-A)*(1-B) 該模式和上一個模式剛好相反,上下層畫素的標準色彩值反相後相乘後輸出,輸出結果比兩者的畫素值都將要亮(就好像兩臺投影機分別對其中一個圖層進行投影后,然後投射到同一個螢幕上)。從第二個公式中我們可以看出,如果兩個圖層反相後,採用Multiply模式混合,則將和對這兩個圖層採用 Screen模式混合後反相的結果完全一樣。
1.2 疊加模式:

在保留底色明暗變化的基礎上使用“正片疊底”或“濾色”模式,繪圖的顏色被疊加到底色上,但保留底色的高光和陰影部分。

  • 底色的顏色沒有被取代,而是和繪圖色混合來體現原圖的亮部和暗部。 使用此模式可使底色的影象的飽和度及對比度得到相應的提高,使影象看起來更加鮮亮。
  • Overlay 疊加 B0.5:C=2×A×BB \leqslant 0.5: C=2×A×B B>0.5:C=12×(1A)×(1B)B>0.5: C=1-2×(1-A)×(1-B) 依據下層色彩值的不同,該模式可能是Multiply,也可能是Screen模式。上層決定了下層中間色調偏移的強度。
    • 如果上層為50%灰,則結果將完全為下層畫素的值。
    • 如果上層比50%灰暗,則下層的中間色調的將向暗地方偏移, 對於上層比50%灰暗,下層中間色調以下的色帶變窄(原來為0~2*0.4*0.5,現在為0~2*0.3*0.5),中間色調以上的色帶變寬(原來為20.40.5~1,現在為2*0.3*0.5~1)。反之亦然。
    • 如果上層比50%灰亮,則下層的中間色調的將向亮地方偏移。
1.3 柔光模式:
  • 根據繪圖色的明暗程度來決定最終色是變亮還是變暗: 當繪圖色比50%的灰要亮時,則 底色影象變亮。 當繪圖色比50%的灰要暗時,則底色影象就變暗。 如果繪圖色有純黑色或純白色,最終色不是黑色或白色,而是稍微變暗或變亮。 如果底色是純白色或純黑色,不產生任何效果。此效果與發散的聚光燈照在影象上相似。
  • Soft Light 柔光(疊加時去除灰色調) A0.5:C=(2A1)(BBB)+BA \leqslant 0.5: C=(2*A-1)*(B-B*B)+B A>0.5:C=(2A1)(sqrt(B)B)+BA>0.5 : C=(2*A-1)*(sqrt(B)-B)+B 該模式類似上層以Gamma值範圍為2.0到0.5的方式來調製下層的色彩值。結果將是一個非常柔和的組合。
1.4 強光模式:
  • 根據繪圖色來決定是執行“正片疊底”還是“濾色”模式。 當繪圖色比50%的灰要亮 時,則底色變亮,就執行“濾色”模式一樣,這對增加影象的高光非常有幫助; 當繪圖色比50%的灰要暗時,則底色變暗,就執行“正片疊底”模式一樣,可增加 影象的暗部。 當繪圖色是純白色或黑色時得到的是純白色和黑色。此效果與耀眼的聚光燈照在影象上相似。
  • Hard Light 強光 A0.5:C=2ABA\leqslant0.5: C=2*A*B A>0.5:C=12(1A)(1B)A>0.5: C=1-2*(1-A)*(1-B) 該模式完全相對應於Overlay模式下,兩個圖層進行次序交換的情況。如過上層的顏色高於50%灰,則下層越亮,反之越暗。

二、線性混合

簡而言之:矩陣表示式為 dst = src1 * alpha + src2 * beta + gamma g(x)=(1α)f0(x)+αf1(x)g(x) = (1-\alpha)f_0(x)+\alpha f_1(x)

"""
cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst
	src1  – 輸入圖片1.
	alpha – 圖片1的權重
	src2  – 輸入圖片2(image.shape & channel 相同)
	beta  – 圖片2的權重
	dst   – 目標圖片
	gamma – 標量求和.
	dtype – 輸出圖片陣列深度,當兩個輸入陣列具有相同的深度時,
	        可以將dtype設定為-1,這相當於src1..()。
"""
def addImage(img1_path, img2_path):
    img1 = cv2.imread(img1_path)
    img = cv2.imread(img2_path)
    h, w, _ = img1.shape
    # 函式要求兩張圖必須是同一個size
    img2 = cv2.resize(img, (w,h), interpolation=cv2.INTER_AREA)
    
    #alpha,beta,gamma可調
    alpha = 0.7
    beta = 1-alpha
    gamma = 0
    img_add = cv2.addWeighted(img1, alpha, img2, beta, gamma)
    cv2.imshow('img_add',img_add)
    
    cv2.waitKey()
    cv2.destroyAllWindows()