如何在 OpenCV 中的两个图像之间应用 SoftLight 混合器?

How to apply SoftLight blender between two images in OpenCV?

关于 this post on Whosebug (and this too) 我正在拍摄一张正常的花朵图像,然后是一张白色图像,然后应用柔光。

这些是图像(白色图像):

结果应该与我在 GIMP 中得到的结果类似:

但它最终是 白色图像

我修改了代码以便将其放入函数中,这是我的代码:

// function
uint convSoftLight(int A, int B) {

    return ((uint)((B < 128)?(2*((A>>1)+64))*((float)B/255):(255-(2*(255-((A>>1)+64))*(float)(255-B)/255))));
}

void function() {
    Mat flower = imread("/Users/rafaelruizmunoz/Desktop/flower.jpg");
    Mat white_flower = Mat::zeros(Size(flower.cols, flower.rows), flower.type());
    Mat mix = Mat::zeros(Size(flower.cols, flower.rows), flower.type());

    for (int i = 0; i < white_flower.rows; i++) {
        for (int j = 0; j < white_flower.cols; j++) {
            white_flower.at<Vec3b>(i,j) = Vec3b(255,255,255);
        }
    }

    imshow("flower", flower);
    imshow("mask_white", white_flower);

    for (int i = 0; i < mix.rows; i++) {
        for (int j = 0; j < mix.cols; j++) {
            Vec3b vec = flower.at<Vec3b>(i,j);
            vec[0] = convSoftLight(vec[0], 255); // 255 or just the white_flower pixel at (i,j)
            vec[1] = convSoftLight(vec[1], 255); // 255 or just the white_flower pixel at (i,j)
            vec[2] = convSoftLight(vec[2], 255); // 255 or just the white_flower pixel at (i,j)
            mix.at<Vec3b>(i,j) = vec;
        }
    }


    imshow("mix", mix);
}

我做错了什么?

谢谢。


编辑:我尝试翻转顺序(convSoftLight(B,A); 而不是 convSoftLight(A,B)),但什么也没发生(黑色图像)

基于blender definitions:我重写了我的函数:

uint convSoftLight(int A, int B) {

    float a = (float)A / 255;
    float b = (float)B / 255;
    float result = 0;

    if (b < 0.5)
        result = 2 * a * b + pow(a,2) * (1 - 2*b);
    else
        result = 2 * a * (1-b) + sqrt(a) * (2*b - 1);

    return (uint)255* result;
}

以下是如何在 Python(使用 OpenCV 和 NumPy)中实现柔光:

import numpy as np

def applySoftLight(bottom, top, mask):
    """ Apply soft light blending
    """

    assert all(image.dtype == np.float32 for image in [bottom, top, mask])

    blend = np.zeros(bottom.shape, dtype=np.float32)

    low = np.where((top < 0.5) & (mask > 0))
    blend[low] = 2 * bottom[low] * top[low] + bottom[low] * bottom[low] * (1 - 2 * top[low])

    high = np.where((top >= 0.5) & (mask > 0))
    blend[high] = 2 * bottom[high] * (1 - top[high]) + np.sqrt(bottom[high]) * (2 * top[high] - 1)

    # alpha blending accroding to mask
    result = bottom * (1 - mask) + blend * mask

    return result

所有矩阵必须是单通道二维矩阵转换成np.float32类型。掩码是"layer mask" GIMP/Photoshop.