试图翻译混合模式的公式

信息处理 图像处理 计算机视觉 图片 opencv
2022-02-16 16:44:40

我正在使用 OpenCV C++ 来制作像 in 一样的混合模式photoshop,我想在其中制作覆盖模式。我在 OpenCV 中搜索了它的替代方法,我在其中找到了这种混合方式,但它不是覆盖,因为我想在其中使用覆盖方法。

本文档中的叠加方法公式

(Target > 0.5) * (1 - (1-2*(Target-0.5)) * (1-Blend)) +
(Target <= 0.5) * ((2*Target) * Blend)

谁能解释一下这个在 OpenCV C++ 中实现的公式,我如何能很容易地理解它的实现,或者是否有任何已经内置的函数或任何其他简单的方法。

3个回答

您可以在 Internet 上找到许多现成的解决方案。例如,这里给出了以下宏:

#define ChannelBlend_Overlay(A,B)    ((uint8)((B < 128) ? (2 * A * B / 255):(255 - 2 * (255 - A) * (255 - B) / 255)))

此外,您可能想查看这个包:blImage的源代码,因为您可以很容易地翻译它。我相信你会找到你正在寻找的东西。

感谢大家的回答和兴趣,但由于我没有完全按照我的问题找到答案,我更新了我自己的解决方案,我从这里得到

首先,您提供的链接的作者假设像素颜色为 0 和 1 之间的值。

想象一下,您想要混合 2 个图像 img1 和 img2。该公式表示,如果 img1 中的像素作为值Target > 0.5,则结果值(1 - (1-2*(Target-0.5)) * (1-Blend))适用于混合图像,其中 Blend 是 img2 像素的值。

另一方面,如果Target <= 0.5生成的颜色值为((2*Target) * Blend).

您需要为每个像素执行此操作。

此链接提供与 OpenCV 的叠加混合功能。

这是一个灰度图像的例子。对于 RGB 图像,您需要为每个通道执行此操作。当然img1img2必须有相同的大小。也许有一种更快的方法可以用 OpenCV 做到这一点。

Mat img1;
Mat img2;
img1 = imread("img1.jpg", CV_LOAD_IMAGE_GRAYSCALE);
img2 = imread("img2.jpg", CV_LOAD_IMAGE_GRAYSCALE);
Mat result(img1.size(), CV_32F);

for(int i = 0; i < img1.size().height; ++i){
    for(int j = 0; j < img1.size().width; ++j){
        float target = float(img1.at<uchar>(i, j)) / 255;
        float blend = float(img2.at<uchar>(i, j)) / 255;
        if(target > 0.5){
            result.at<float>(i, j) = (1 - (1-2*(target-0.5)) * (1-blend));
        }
        else{
            result.at<float>(i, j) = ((2*target) * blend);
        }
    }
}

行。让我们把它分成几块:

(Target > 0.5) * (1 - (1-2*(Target-0.5)) * (1-Blend)) + (Target <= 0.5) * ((2*Target) * Blend)

有两个部分正在混合:

(Target > 0.5) * (1 - (1-2*(Target-0.5))
(Target <= 0.5) * (2*Target)

其中第一个是确保Target > 0.5仅选择强度大于 0.5 ( ) 的像素,其余的 ( Target <= 0.5) 转到另一个图像。因此,第二个被限制为 0-0.5 值,正在缩放到 0-1。为了获得第一组像素的相似范围,正在使用拉伸算法:1-(1-2*(Target-0.5)).

正如文档中提到的,这是乘法和屏幕的组合——乘以小于或等于 0.5 的像素,其余的为屏幕。

谈到 OpenCV 实施,您将需要以下方法:

  1. 混合 ( I1 *(1-b) + I2 *b)

  2. 加法 ( I1 + I2,当然还有标准化)

  3. 反转 ( I2 = 1 - I1)

  4. 阈值 ( I2 = I1 > a/b)

我遵循了使用 1 作为最大强度的文档约定,您可以使用浮点类型图像坚持这一点,也可以适当缩放以使用其他格式。