欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python 圖像處理之顏色遷移(reinhard VS welsh)

 更新時間:2021年12月08日 08:57:40   作者:watersink  
這篇文章主要介紹了分別利用reinhard算法和welsh算法實現(xiàn)圖像的顏色遷移,并對二者算法的效果進行了對比,感興趣的小伙伴可以了解一下

前言

reinhard算法:Color Transfer between Images,作者Erik Reinhard

welsh算法:Transferring Color to Greyscale Images,作者Tomihisa Welsh

應(yīng)用場景

人像圖換膚色,風景圖顏色遷移

出發(fā)點

  1. RGB三通道有很強的關(guān)聯(lián)性,而做顏色的改變同時恰當?shù)馗淖內(nèi)ǖ辣容^困難。
  2. 需要尋找三通道互不相關(guān)的也就是正交的顏色空間,作者想到了Ruderman等人提出的lαβ顏色空間。三個軸向正交意味著改變?nèi)魏我粋€通道都不影響其他通道,從而能夠較好的保持原圖的自然效果。三個通道分別代表:亮度,黃藍通道,紅綠通道。

reinhard算法流程

  1. 輸入變換圖,顏色參考圖,將其都從bgr空間轉(zhuǎn)化為lab空間
  2. 分別計算變換圖,參考圖在lab空間的均值,方差
  3. (變換圖lab - 變換圖均值)/變換圖方差 *參考圖方差 + 參考圖均值
  4. 變換圖lab空間轉(zhuǎn)化為bgr空間,輸出結(jié)果

welsh算法流程

  1. 輸入變換圖,顏色參考圖,將其都從bgr空間轉(zhuǎn)化為lab空間
  2. 定義隨機參考點個數(shù)segment,領(lǐng)域空間大小window_size,加權(quán)系數(shù)ratio。從參考圖片中隨機選擇segment個樣本點,將這些樣本點的像素亮度值L和L空間window_size領(lǐng)域內(nèi)得方差σ保存起來,求這2個的加權(quán)W,W = L* ratio+ σ*(1-ratio)。這樣就可以得到segment個W,以及與其一一對應(yīng)的a通道,b通道對應(yīng)位置的數(shù)值。
  3. 對變換圖的L通道基于顏色參考圖的L通道進行亮度重映射,保證后續(xù)的像素匹配正確進行
  4. 對變換圖進行逐像素掃描,對每個像素,計算其權(quán)值W,計算方式和上面一樣。然后在第二步得到的樣本點中找到與其權(quán)值最接近的參考點,并將該點的a通道和b通道的值賦給變換圖的a通道和b通道。
  5. 將變換圖從Lab空間轉(zhuǎn)化到bgr空間。

Reinhard VS welsh

  1. Reinhard 操作簡單,高效,速度快很多。
  2. welsh算法涉及到了參考圖的W的計算,如果是參考圖固定且已知的場景,這一步可以放入初始化中。如果不是這樣的場景,那么這一步的計算也是很費時的。
  3. welsh整體速度慢很多,主要由于求方差造成。
  4. welsh的輸出效果,受隨機參考點個數(shù)以及位置的影響,每次的結(jié)果都會有差異。
  5. welsh的效果會有種涂抹不均勻的感覺,Reinhard 則沒有這種問題。

代碼實現(xiàn)

Reinhard

def color_trans_reinhard(in_img, ref_img, in_mask_lists=[None], ref_mask_lists=[None]):
    ref_img_lab = cv2.cvtColor(ref_img, cv2.COLOR_BGR2LAB)
    in_img_lab = cv2.cvtColor(in_img, cv2.COLOR_BGR2LAB)
 
    in_avg = np.ones(in_img.shape, np.float32)
    in_std = np.ones(in_img.shape, np.float32)
    ref_avg = np.ones(in_img.shape, np.float32)
    ref_std = np.ones(in_img.shape, np.float32)
 
    mask_all = np.zeros(in_img.shape, np.float32)
    for in_mask, ref_mask in zip(in_mask_lists, ref_mask_lists):
        #mask,取值為 0, 255, shape[height,width]
        in_avg_tmp, in_std_tmp = cv2.meanStdDev(in_img_lab, mask=in_mask)
        np.copyto(in_avg, in_avg_tmp.reshape(1,1,-1), where=np.expand_dims(in_mask,2)!=0) #numpy.copyto(destination, source)
        np.copyto(in_std, in_std_tmp.reshape(1,1,-1), where=np.expand_dims(in_mask,2)!=0) 
 
        ref_avg_tmp, ref_std_tmp = cv2.meanStdDev(ref_img_lab, mask=ref_mask)
        np.copyto(ref_avg, ref_avg_tmp.reshape(1,1,-1), where=np.expand_dims(in_mask,2)!=0) #numpy.copyto(destination, source)
        np.copyto(ref_std, ref_std_tmp.reshape(1,1,-1), where=np.expand_dims(in_mask,2)!=0) 
 
        #mask
        mask_all[in_mask!=0] = 1
 
    in_std[in_std==0] =1 #避免除數(shù)為0的情況
    transfered_lab = (in_img_lab - in_avg)/(in_std) *ref_std + ref_avg 
    transfered_lab[transfered_lab<0] = 0
    transfered_lab[transfered_lab>255] = 255
 
    out_img = cv2.cvtColor(transfered_lab.astype(np.uint8), cv2.COLOR_LAB2BGR)
 
    if in_mask_lists[0] is not None and ref_mask_lists[0] is not None:
        np.copyto(out_img, in_img, where=mask_all==0) 
        
    return out_img
 
 
"""
#img1 = cv2.imread("imgs/1.png")
#img2 = cv2.imread("imgs/2.png")
#img1 = cv2.imread("welsh22/1.png", 1)
#img2 = cv2.imread("welsh22/2.png", 1)
img1 = cv2.imread("welsh22/gray.jpg", 1)
img2 = cv2.imread("welsh22/consult.jpg", 1)
cv2.imwrite("out.jpg", color_trans_reinhard(img1, img2, [np.ones(img1.shape[:-1],np.uint8)*255], [np.ones(img2.shape[:-1],np.uint8)*255]))
"""
img1 = cv2.imread("ab.jpeg")
img2 = cv2.imread("hsy.jpeg")
mask1 = cv2.imread("ab_parsing.jpg", 0)
mask1[mask1<128]=0
mask1[mask1>=128]=255
mask2 = cv2.imread("hsy_parsing.jpg", 0)
mask2[mask2<128]=0
mask2[mask2>=128]=255
cv2.imwrite("out.jpg", color_trans_reinhard(img1, img2, [mask1], [mask2]))

Welsh代碼

改進點

  1. 主要是去掉for循環(huán)操作。
  2. 將計算一個領(lǐng)域內(nèi)的std,使用均值濾波+numpy實現(xiàn)近似替換。差別目測看不出。
  3. 修改參考圖的weight,全部int化,只保留不一樣的weight,實際測試大概150個左右的weight就可以。
  4. 修改最近weight查找思路,使用numpy減法操作+argmin,替換2分查找。
  5. 整體速度比原始代碼快18倍。
def get_domain_std(img_l, pixel, height, width, window_size):
    window_left = max(pixel[1] - window_size, 0)
    window_right = min(pixel[1] + window_size + 1, width)
    window_top = max(pixel[0] - window_size, 0)
    window_bottom = min(pixel[0] + window_size + 1, height)
 
    window_slice = img_l[window_top: window_bottom, window_left: window_right]
 
    return np.std(window_slice)
 
 
def get_weight_pixel(ref_img_l, ref_img_a, ref_img_b, ref_img_height, ref_img_width, segment, window_size, ratio, ref_mask_lists=[None]):
    weight_list = []
    pixel_a_list = []
    pixel_b_list = []
 
    ref_img_mask  = np.ones((ref_img_height, ref_img_width), np.uint8)
    if ref_mask_lists[0] is not None:
        for x in ref_mask_lists:
            ref_img_mask = np.bitwise_or(x, ref_img_mask)
 
    ref_img_l_mean = cv2.blur(ref_img_l, (window_size, window_size))
    ref_img_l_std = np.sqrt(cv2.blur(np.power((ref_img_l - ref_img_l_mean), 2),  (window_size, window_size)))
    for _ in range(segment):
        height_index = np.random.randint(ref_img_height)
        width_index = np.random.randint(ref_img_width)
 
            
        pixel = [height_index, width_index]  #[x,y]
 
        if ref_img_mask[pixel[0], pixel[1]] == 0:
            continue
 
        pixel_light = ref_img_l[pixel[0], pixel[1]]
        pixel_a = ref_img_a[pixel[0], pixel[1]]
        pixel_b = ref_img_b[pixel[0], pixel[1]]
 
        #pixel_std = get_domain_std(ref_img_l, pixel, ref_img_height, ref_img_width, window_size)
        pixel_std = ref_img_l_std[height_index, width_index]
 
        weight_value = int(pixel_light * ratio + pixel_std * (1 - ratio))
        if weight_value not in weight_list:
            weight_list.append(weight_value)
            pixel_a_list.append(pixel_a)
            pixel_b_list.append(pixel_b)                          
 
    return np.array(weight_list), np.array(pixel_a_list), np.array(pixel_b_list)
 
 
 
def color_trans_welsh(in_img, ref_img, in_mask_lists=[None], ref_mask_lists=[None]):
    start = time.time()
    #參考圖
    ref_img_height, ref_img_width, ref_img_channel = ref_img.shape
    window_size=5 #窗口大小
    segment= 10000#隨機點個數(shù)
    ratio=0.5     #求weight的比例系數(shù)
 
    ref_img_lab = cv2.cvtColor(ref_img, cv2.COLOR_BGR2Lab)
    ref_img_l, ref_img_a, ref_img_b = cv2.split(ref_img_lab)
 
    #計算參考圖weight
    ref_img_weight_array, ref_img_pixel_a_array, ref_img_pixel_b_array =  get_weight_pixel(ref_img_l, ref_img_a, ref_img_b, ref_img_height, ref_img_width, segment, window_size, ratio, ref_mask_lists)
 
    ref_img_max_pixel, ref_img_min_pixel = np.max(ref_img_l), np.min(ref_img_l)
 
 
    #輸入圖
    in_img_height, in_img_width, in_img_channel = in_img.shape
    in_img_lab = cv2.cvtColor(in_img, cv2.COLOR_BGR2LAB)
 
    # 獲取灰度圖像的亮度信息;
    in_img_l, in_img_a, in_img_b = cv2.split(in_img_lab)
 
    in_img_max_pixel, in_img_min_pixel = np.max(in_img_l), np.min(in_img_l)
    pixel_ratio = (ref_img_max_pixel - ref_img_min_pixel) / (in_img_max_pixel - in_img_min_pixel)
 
    # 把輸入圖像的亮度值映射到參考圖像范圍內(nèi);
    in_img_l = ref_img_min_pixel + (in_img_l - in_img_min_pixel) * pixel_ratio
    in_img_l = in_img_l.astype(np.uint8)
 
 
    in_img_l_mean = cv2.blur(in_img_l, (window_size, window_size))
    in_img_l_std = np.sqrt(cv2.blur(np.power((in_img_l - in_img_l_mean), 2),  (window_size, window_size)))
 
 
    in_img_weight_pixel = ratio * in_img_l + (1 - ratio) * in_img_l_std
 
    nearest_pixel_index = np.argmin(np.abs(ref_img_weight_array.reshape(1,1,-1) - np.expand_dims(in_img_weight_pixel, 2)), axis=2).astype(np.float32)
 
    in_img_a = cv2.remap(ref_img_pixel_a_array.reshape(1, -1), nearest_pixel_index, np.zeros_like(nearest_pixel_index, np.float32), interpolation=cv2.INTER_LINEAR)
    in_img_b = cv2.remap(ref_img_pixel_b_array.reshape(1, -1), nearest_pixel_index, np.zeros_like(nearest_pixel_index, np.float32), interpolation=cv2.INTER_LINEAR)
 
 
    merge_img = cv2.merge([in_img_l, in_img_a, in_img_b])
    bgr_img = cv2.cvtColor(merge_img, cv2.COLOR_LAB2BGR)
 
    
    mask_all = np.zeros(in_img.shape[:-1], np.int32)
    if in_mask_lists[0] is not None and ref_mask_lists[0] is not None:
        for x in in_mask_lists:
            mask_all = np.bitwise_or(x, mask_all)
        mask_all = cv2.merge([mask_all, mask_all, mask_all])
        np.copyto(bgr_img, in_img, where=mask_all==0) 
    
    end = time.time()
    print("time", end-start)
    return bgr_img
 
 
 
if __name__ == '__main__':
 
    # 創(chuàng)建參考圖像的分析類;
    #ref_img = cv2.imread("consult.jpg")
    #ref_img = cv2.imread("2.png")
    ref_img = cv2.imread("../imgs/2.png")
 
    # 讀取灰度圖像;opencv默認讀取的是3通道的,不需要我們擴展通道;
    #in_img = cv2.imread("gray.jpg")
    #in_img = cv2.imread("1.png")
    in_img = cv2.imread("../imgs/1.png")
 
    bgr_img = color_trans_welsh(in_img, ref_img)
    cv2.imwrite("out_ren.jpg", bgr_img)
    """
    ref_img = cv2.imread("../hsy.jpeg")
    ref_mask = cv2.imread("../hsy_parsing.jpg", 0)
    ref_mask[ref_mask<128] = 0
    ref_mask[ref_mask>=128] = 255
    in_img = cv2.imread("../ab.jpeg")
    in_mask = cv2.imread("../ab_parsing.jpg", 0)
    in_mask[in_mask<128] = 0
    in_mask[in_mask>=128] = 255
    bgr_img = color_trans_welsh(in_img, ref_img, in_mask_lists=[in_mask], ref_mask_lists=[ref_mask])
    cv2.imwrite("bgr.jpg", bgr_img)
    """

效果對比

從左到右,分別為原圖,參考圖,reinhard效果,welsh效果?

?從左到右,分別為原圖,原圖皮膚mask,參考圖,參考圖皮膚mask,reinhard效果,welsh效果??

以上就是Python 圖像處理之顏色遷移(reinhard VS welsh)的詳細內(nèi)容,更多關(guān)于Python 顏色遷移的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Django的分頁器實例(paginator)

    Django的分頁器實例(paginator)

    下面小編就為大家分享一篇Django的分頁器實例(paginator),具有很好的參考價值,希望對大家有所幫助
    2017-12-12
  • 解析django的csrf跨站請求偽造

    解析django的csrf跨站請求偽造

    本文主要介紹了解析django的csrf跨站請求偽造,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • Python實現(xiàn)數(shù)據(jù)可視化看如何監(jiān)控你的爬蟲狀態(tài)【推薦】

    Python實現(xiàn)數(shù)據(jù)可視化看如何監(jiān)控你的爬蟲狀態(tài)【推薦】

    今天主要是來說一下怎么可視化來監(jiān)控你的爬蟲的狀態(tài)。文中通過實例代碼給大家分析了Python實現(xiàn)數(shù)據(jù)可視化看如何監(jiān)控你的爬蟲狀態(tài),感興趣的朋友一起看看吧
    2018-08-08
  • Python中查找字符串之間差異位置

    Python中查找字符串之間差異位置

    本文主要介紹了Python中查找兩個字符串之間的差異位置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • matplotlib bar()實現(xiàn)百分比堆積柱狀圖

    matplotlib bar()實現(xiàn)百分比堆積柱狀圖

    這篇文章主要介紹了matplotlib bar()實現(xiàn)百分比堆積柱狀圖,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • python中使用正則表達式的后向搜索肯定模式(推薦)

    python中使用正則表達式的后向搜索肯定模式(推薦)

    這篇文章主要介紹了python里使用正則表達式的后向搜索肯定模式,本文通過代碼介紹的非常詳細,包括語法介紹,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-11-11
  • Python操作SQLite數(shù)據(jù)庫過程解析

    Python操作SQLite數(shù)據(jù)庫過程解析

    這篇文章主要介紹了Python操作SQLite數(shù)據(jù)庫過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Python 中Django驗證碼功能的實現(xiàn)代碼

    Python 中Django驗證碼功能的實現(xiàn)代碼

    驗證碼是一種區(qū)分用戶是計算機還是人的公共全自動程序,很多用戶登錄和注冊系統(tǒng)都提供了圖形驗證碼功能。這篇文章主要介紹了Python 中Django驗證碼功能的實現(xiàn)代碼,需要的朋友可以參考下
    2019-06-06
  • python實現(xiàn)textrank關(guān)鍵詞提取

    python實現(xiàn)textrank關(guān)鍵詞提取

    這篇文章主要為大家詳細介紹了python實現(xiàn)textrank關(guān)鍵詞提取,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Python繪制loss曲線和準確率曲線實例代碼

    Python繪制loss曲線和準確率曲線實例代碼

    pytorch雖然使用起來很方便,但在一點上并沒有tensorflow方便,就是繪制模型訓練時在訓練集和驗證集上的loss和accuracy曲線(共四條),下面這篇文章主要給大家介紹了關(guān)于Python繪制loss曲線和準確率曲線的相關(guān)資料,需要的朋友可以參考下
    2022-08-08

最新評論