OpenCV and Unsharp Masking Like Adobe Photoshop

前端 未结 3 1971
挽巷
挽巷 2021-02-06 19:11

I am trying to implement unsharp masking like it\'s done in Adobe Photoshop. I gathered a lot of information on the interent but I\'m not sure if I\'m missing something. Here\'s

相关标签:
3条回答
  • 2021-02-06 19:26

    According to docs:

    C++: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )

    4th parameter is not "radius" it is "sigma" - gaussian kernel standard deviation. Radius is rather "ksize". Anyway Photoshop is not open source, hence we can not be sure they use the same way as OpenCV to calculate radius from sigma.

    Channels

    Yes you should apply sharp to any or to all channels, it depends on your purpose. Sure you can use any space: if you want sharp only brightness-component and don't want to increase color noise you can covert it to HSL or Lab-space and sharp L-channel only (Photoshop has all this options too).

    0 讨论(0)
  • 2021-02-06 19:28

    Here's the code what I have done. I am using this code to implement Unsharp Mask and it is working well for me. Hope it is useful for you.

    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);
            }
        }
    
    }
    
    0 讨论(0)
  • 2021-02-06 19:31

    I'm trying to replicate Photoshop's Unsharp Mask as well. Let's ignore the Threshold for a second.

    I will show you how to replicate Photoshop's Unsharp Mask using its Gaussian Blur.

    Assuming O is the original image layer.

    Create a new layer GB which is a Gaussian Blur applied on O.
    Create a new layer which is O - GB (Using Apply Image).
    Create a new layer by inverting GB - invGB.
    Create a new layer which is O + invGB using Image Apply.
    Create a new layer which is inversion of the previous layer, namely inv(O + invGB).
    Create a new layer which is O + (O - GB) - inv(O + invGB).

    When you do that in Photoshop you'll get a perfect reproduction of the Unsharp Mask.

    If you do the math recalling that inv(L) = 1 - L you will get that the Unsharp Mask is USM(O) = 3O - 2B.

    Yet when I do that directly in MATLAB I don't get Photoshop's results.

    Hopefully someone will know the exact math.

    Update

    OK,
    I figured it out.
    In Photoshop USM(O) = O + (2 * (Amount / 100) * (O - GB))
    Where GB is a Gaussian Blurred version of O.

    Yet, in order to replicate Photoshop's results you must do the steps above and clip the result of each step into [0, 1] as done in Photoshop.

    0 讨论(0)
提交回复
热议问题