OpENCV和UNSHARP屏蔽如Adobe Photoshop

OpenCV and Unsharp Masking Like Adobe Photoshop

本文关键字:Adobe Photoshop 屏蔽 UNSHARP OpENCV      更新时间:2023-10-16

我试图像在Adobe Photoshop中一样实现Unshap掩盖。我收集了很多有关间歇性的信息,但我不确定是否缺少某些内容。这是代码:

void unsharpMask( cv::Mat* img, double amount, double radius, double threshold ) {
// create blurred img
cv::Mat img32F, imgBlur32F, imgHighContrast32F, imgDiff32F, unsharpMas32F, colDelta32F, compRes, compRes32F, prod;
double r = 1.5;
img->convertTo( img32F, CV_32F );
cv::GaussianBlur( img32F, imgBlur32F, cv::Size(0,0), radius );
cv::subtract( img32F, imgBlur32F, unsharpMas32F );
// increase contrast( original, amount percent ) 
imgHighContrast32F = img32F * amount / 100.0f;
cv::subtract( imgHighContrast32F, img32F, imgDiff32F );
unsharpMas32F /= 255.0f;
cv::multiply( unsharpMas32F, imgDiff32F, colDelta32F );
cv::compare( cv::abs( colDelta32F ), threshold, compRes, cv::CMP_GT );
compRes.convertTo( compRes32F, CV_32F );
cv::multiply( compRes32F, colDelta32F, prod );
cv::add( img32F, prod, img32F );
img32F.convertTo( *img, CV_8U );
}

目前我正在使用灰度图像进行测试。如果我在Photoshop中尝试完全相同的参数,则结果会更好。我自己的代码会导致嘈杂的图像。我在做什么错。

第二个问题是,如何在RGB图像上应用Unsharp屏蔽?我是否必须取消掩盖3个通道中的每个频道,或者在另一个颜色空间中会更好?这些事情在Photoshop中如何完成?

感谢您的帮助!

我也试图复制Photoshop的Unsharp mask。让我们忽略阈值一秒钟。

我将向您展示如何使用其高斯模糊来复制Photoshop的Unshap面膜。

假设O是原始图像层。

创建一个新的GB,它是在O上应用的高斯模糊。
创建一个新层O -GB(使用应用图像)。
通过反转GB -INVGB。
创建新层创建一个使用图像应用的新图层,该层是O Invgb。
创建一个新图层,该层是对上一层的反转,即Inv(O InvgB)。
创建一个新图层,即O (O -GB) - INV(O INVGB)。

当您在Photoshop中这样做时,您将获得UNSHARP面具的完美再现。

如果您进行数学召回,Inv(l)= 1 -L您会得到Unsharp mask是USM(O)= 3O -2B。

但是,当我直接在Matlab中这样做时,我没有得到Photoshop的结果。

希望有人会知道确切的数学。

更新

好,
我发现了。
在Photoshop usm(o)= o (2 *(量/100) *(o -gb))
其中gb是o。

的高斯模糊版本

然而,为了复制Photoshop的结果,您必须执行上述步骤,并将每个步骤的结果夹在[0,1]中。

在Photoshop中完成。

根据文档:

c :void gaussianblur(inputArray src,outputarray dst,size ksize, double sigmax,double sigmay = 0,int bordertype = border_default)

第四参数不是"半径",而是" sigma" - 高斯内核标准偏差。半径相当" ksize"。无论如何,Photoshop不是开源的,因此我们不能确定它们与OpenCV相同的方式来计算Sigma的半径。

频道

是的,您应该向所有渠道施加敏锐的申请,这取决于您的目的。当然,您可以使用任何空间:如果您只需要锐利的亮度组件,并且不想增加颜色噪声,则可以将其掩盖到HSL或实验室空间和锋利的L通道(Photoshop也具有所有这些选项)。<<<<<<<<<<<<

响应@Royi,2x乘法器假设在此公式中没有夹紧:

USM(Original) = Original + Amount / 100 * ((Original - GB) - (1 - (Original + (1 - GB))))

忽略夹具错误地减少到:

USM(Original) = Original + 2 * Amount / 100 * (Original - GB) 

但是,正如您还指出的那样,(Original - GB)(Original + inv(GB))被夹紧到[0,1]:

USM(Original) = Original + Amount / 100 *
   (Max(0, Min(1, Original - GB)) - (1 - (Max(0, Min(1, Original + (1 - GB))))))

正确简化为:

USM(Original) = Original + Amount / 100 * (Original - GB)

这是一个示例,说明了原因:

https://legacy.imagemagick.org/discourse-server/viewtopic.php?p=133597#p133597

这是我所做的代码。我正在使用此代码来实现Unsharp面具,并且对我来说很好。希望它对您有用。

void USM(cv::Mat &O, int d, int amp, int threshold)
{
    cv::Mat GB;
    cv::Mat O_GB;
    cv::subtract(O, GB, O_GB);
    cv::Mat invGB = cv::Scalar(255) - GB;
    cv::add(O, invGB, invGB);
    invGB = cv::Scalar(255) - invGB;
    for (int i = 0; i < O.rows; i++)
    {
        for (int j = 0; j < O.cols; j++)
        {
            unsigned char o_rgb = O.at<unsigned char>(i, j);
            unsigned char d_rgb = O_GB.at<unsigned char>(i, j);
            unsigned char inv_rgb = invGB.at<unsigned char>(i, j);
            int newVal = o_rgb;
            if (d_rgb >= threshold)
            {
                newVal = o_rgb + (d_rgb - inv_rgb) * amp;
                if (newVal < 0)      newVal = 0;
                if (newVal > 255)    newVal = 255;
            }
            O.at<unsigned char>(i, j) = unsigned char(newVal);
        }
    }
}