天天看點

Python-OpenCV 圖像權重混合(濾色, 疊加, 柔光, 強光)

OpenCV 圖像混合模式

  • ​​一、圖像混合原理​​
  • ​​1.1 濾色模式​​
  • ​​1.2 疊加模式​​
  • ​​1.3 柔光模式​​
  • ​​1.4 強光模式​​
  • ​​二、線性混合(相加)​​

一、圖像混合原理

1.1 濾色模式

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

  • 通常執行濾色模式後的顔色都較淺:

    任何顔色和黑色執行濾色,原色不受影響;

    任何顔色和白色執行濾色得到的是白色;

    而與其他顔色執行濾色會産生漂白的效果。

  • Screen 濾色

    也可以寫成 1-C=(1-A)*(1-B)

    該模式和上一個模式剛好相反,上下層像素的标準色彩值反相後相乘後輸出,輸出結果比兩者的像素值都将要亮(就好像兩台投影機分别對其中一個圖層進行投影後,然後投射到同一個螢幕上)。從第二個公式中我們可以看出,如果兩個圖層反相後,采用Multiply模式混合,則将和對這兩個圖層采用 Screen模式混合後反相的結果完全一樣。

1.2 疊加模式

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

  • 底色的顔色沒有被取代,而是和繪圖色混合來展現原圖的亮部和暗部。

    使用此模式可使底色的圖像的飽和度及對比度得到相應的提高,使圖像看起來更加鮮亮。

  • Overlay 疊加

    依據下層色彩值的不同,該模式可能是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 柔光(疊加時去除灰色調)

    混合色 <=128:結果色 = 基色 + (2 * 混合色 - 255) * (基色 - 基色 * 基色 / 255) / 255;

    混合色 >128: 結果色 = 基色 + (2 * 混合色 - 255) * (Sqrt(基色/255)*255 - 基色)/255。

    該模式類似上層以Gamma值範圍為2.0到0.5的方式來調制下層的色彩值。結果将是一個非常柔和的組合。

1.4 強光模式
  • 根據繪圖色來決定是執行“正片疊底”還是“濾色”模式。

    當繪圖色比50%的灰要亮 時,則底色變亮,就執行“濾色”模式一樣,這對增加圖像的高光非常有幫助;

    當繪圖色比50%的灰要暗時,則底色變暗,就執行“正片疊底”模式一樣,可增加 圖像的暗部。

    當繪圖色是純白色或黑色時得到的是純白色和黑色。此效果與耀眼的聚光燈照在圖像上相似。

  • Hard Light 強光

    該模式完全相對應于Overlay模式下,兩個圖層進行次序交換的情況。如過上層的顔色高于50%灰,則下層越亮,反之越暗。

二、線性混合(相加)

簡而言之:矩陣表達式為 dst = src1 * alpha + src2 * beta + gamma

"""
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..()。
"""      
import cv2
import numpy as np

def img_filter(img):                   #計算圖像梯度(高反差像素)
    x=cv2.Sobel(img,cv2.CV_16S,1,0)
    y=cv2.Sobel(img,cv2.CV_16S,0,1)

    absx=cv2.convertScaleAbs(x)
    absy=cv2.convertScaleAbs(y)
    dist=cv2.addWeighted(absx,0.5,absy,0.5,0)
    return dist

def addImage(img1, img2,alpha):
    h, w, _ = img1.shape
    """
        函數要求兩張圖必須是同一個size
        alpha,beta,gamma可調
    """
    img2 = cv2.resize(img2, (w, h), interpolation=cv2.INTER_AREA)

    beta = 1 - alpha
    gamma = 0
    img_add = cv2.addWeighted(img1, alpha, img2, beta, gamma)
    return img_add


if __name__ == '__main__':
    img1=cv2.imread('R_channel.png',cv2.IMREAD_COLOR)  # 以彩色圖的形式讀入
    dist_img = img_filter(img1)                        # 執行高通過濾
    for i in range(1,10):                              # 循環執行(不同的alpha):顯示疊加圖,寫入處理後的圖像
        IMG_Add = addImage(img1,dist_img,i*0.1)        # alpha,beta,gamma可調
        cv2.imshow('img_add_'+ str(i), IMG_Add)
        cv2.imwrite('img_add_'+ str(i)+".png", IMG_Add)
        cv2.imshow("img1",img1)
        # cv2.waitKey()
        # cv2.destroyAllWindows()      

繼續閱讀