3

Adobe Photoshopで行われているように、アンシャープマスキングを実装しようとしています。インタレントについてたくさんの情報を集めましたが、何かが足りないのかわかりません。コードは次のとおりです。

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でまったく同じパラメータを試してみると、はるかに良い結果が得られます。私自身のコードはノイズの多い画像につながります。私は何を間違っているのですか。

2番目の質問は、RGB画像にアンシャープマスキングを適用するにはどうすればよいですか?3つのチャネルのそれぞれをアンシャープマスクする必要がありますか、それとも別の色空間でより適切ですか?これらのことはPhotoshopでどのように行われますか?

ご協力いただきありがとうございます!

4

4 に答える 4

1

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).

于 2014-04-27T13:13:09.817 に答える
0

@Royi への応答として、2 倍の乗数は、次の式でクランプがないと仮定した結果です。

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

于 2021-05-08T21:12:27.660 に答える
-1

これが私が行ったコードです。このコードを使用して Unsharp Mask を実装していますが、うまく機能しています。お役に立てば幸いです。

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);
        }
    }

}
于 2016-07-04T02:55:20.483 に答える