使用 OpenCV 实现反锐化掩码

goo*_*dev 1 c++ photoshop opencv image-processing

我想像 Adob​​e Photoshop 一样应用不清晰的蒙版,我知道这个答案,但它不如 Photoshop 清晰。

Photoshop 在 Smart Sharpen 对话框中有 3 个参数:Amount、Radius、Reduce Noise;我想实现所有这些。 在此处输入图片说明

根据 SO 中的各种来源,这是我编写的代码。但是在某些阶段(“blurred”、“unsharpMask”、“highContrast”)结果很好,但在最后阶段(“retval”)结果不好。

我哪里错了,我应该改进什么?

是否可以在性能方面改进以下算法?

#include "opencv2/opencv.hpp"
#include "fstream"
#include "iostream"
#include <chrono>

using namespace std;
using namespace cv;

// from https://docs.opencv.org/3.4/d3/dc1/tutorial_basic_linear_transform.html
void increaseContrast(Mat img, Mat* dst, int amountPercent)
{
    *dst = img.clone();
    double alpha = amountPercent / 100.0;
    *dst *= alpha;
}

// from /sf/answers/41737041/
float luminanceAsPercent(Vec3b color)
{
    return (0.2126 * color[2]) + (0.7152 * color[1]) + (0.0722 * color[0]);
}

// from /sf/answers/205685581/
Mat usm(Mat original, int radius, int amountPercent, int threshold)
{
    // copy original for our return value
    Mat retval = original.clone();

    // create the blurred copy
    Mat blurred;
    cv::GaussianBlur(original, blurred, cv::Size(0, 0), radius);

    cv::imshow("blurred", blurred);
    waitKey();

    // subtract blurred from original, pixel-by-pixel to make unsharp mask
    Mat unsharpMask;
    cv::subtract(original, blurred, unsharpMask);

    cv::imshow("unsharpMask", unsharpMask);
    waitKey();

    Mat highContrast;
    increaseContrast(original, &highContrast, amountPercent);

    cv::imshow("highContrast", highContrast);
    waitKey();

    // assuming row-major ordering
    for (int row = 0; row < original.rows; row++) 
    {
        for (int col = 0; col < original.cols; col++) 
        {
            Vec3b origColor = original.at<Vec3b>(row, col);
            Vec3b contrastColor = highContrast.at<Vec3b>(row, col);

            Vec3b difference = contrastColor - origColor;
            float percent = luminanceAsPercent(unsharpMask.at<Vec3b>(row, col));

            Vec3b delta = difference * percent;

            if (*(uchar*)&delta > threshold) {
                retval.at<Vec3b>(row, col) += delta;
                //retval.at<Vec3b>(row, col) = contrastColor;
            }
        }
    }

    return retval;
}

int main(int argc, char* argv[])
{
    if (argc < 2) exit(1);
    Mat mat = imread(argv[1]);
    mat = usm(mat, 4, 110, 66);
    imshow("usm", mat);
    waitKey();
    //imwrite("USM.png", mat);
}
Run Code Online (Sandbox Code Playgroud)

原图: 在此处输入图片说明

模糊的舞台 - 看起来不错: 在此处输入图片说明

UnsharpMask 阶段 - 看起来不错: 在此处输入图片说明

高对比度阶段 - 看起来不错: 在此处输入图片说明

我的代码的结果阶段 - 看起来很糟糕! 在此处输入图片说明

来自Photoshop 的结果- 太棒了! 在此处输入图片说明

小智 6

首先,从 Photoshop 在花瓣边缘留下的人工制品来看,我会说它通过使用原始图像和蒙版之间的加权和来应用蒙版,如您首先尝试答案

我修改了你的代码来实现这个方案,我试图调整参数以接近 Photoshop 结果,但我不能不产生很多噪音。我不会试图猜测 Photoshop 到底在做什么(我绝对想知道),但是我发现通过在蒙版上应用一些过滤器来减少噪音,它是相当可重现的。算法方案是:

blurred = blur(image, Radius)
mask = image - blurred
mask = some_filter(mask)
sharpened = (mask < Threshold) ? image : image - Amount * mask
Run Code Online (Sandbox Code Playgroud)

我实现了这个并尝试在蒙版上使用基本过滤器(中值模糊、平均过滤器等),这是我可以获得的结果: 比较图

这比 Photoshop 图像有点嘈杂,但在我看来,已经足够接近你想要的了。

另一方面,这当然取决于您对滤镜的使用,但我认为您在 Photoshop 中使用的设置太强了(花瓣边界附近有很大的过冲)。这足以在肉眼下获得漂亮的图像,并且过冲有限: 比较图

最后,这是我用来生成上面两个图像的代码:

blurred = blur(image, Radius)
mask = image - blurred
mask = some_filter(mask)
sharpened = (mask < Threshold) ? image : image - Amount * mask
Run Code Online (Sandbox Code Playgroud)