【画像強調 – 7 つのシャープネス手法の原理と実装 (C++、Python、シェーダー GLSL)】

研ぐ

画像鮮明化アルゴリズムは、画像の細部とエッジを強調するために使用される技術です。これらの方法はすべて画像の鮮明化に使用できます。つまり、シャープ化とは、エッジの差 (エッジとは何か、画像エッジ検出などを参照) を強調して、エッジ周囲のピクセル間の色の輝度値を強調することです。

エッジ検出は画像のエッジ情報、つまり画素が大きく変化する箇所を見つけ、その微分値の勾配値を計算するもので、主に1階微分と2階微分を計算する方法が一般的に使われています。 -次数の微分。具体的には、ニーズに応じて適切な方法を選択する必要があります。

方法

Good detection results: エッジの誤検出率が低く、真のエッジを検出しながら誤ったエッジの検出を回避します。マーカーのエッジ位置は、画像上の実際のエッジ位置にできるだけ近くなければなりません。

(画素間の変化の強さ)を計算する場合gradient of the image、1次元データの差分導出とは異なり、主に2次元以上の配列に対して畳み込み計算が使用されます(畳み込み計算とは、自己探索、最近ではデューティと呼ばれています)深層学習ネットワークの火に)、一般的な画像鮮明化アルゴリズムのいくつかを次に示します。

研ぎのレビュー

画像鮮明化アルゴリズムは、画像の細部とエッジを強調するために使用される技術です。これらの方法はすべて画像の鮮明化に使用できます。つまり、シャープ化とは、エッジ上の差異を強調し (エッジ検出とは何ですか、画像エッジ検出などを参照できます)、エッジ周囲のピクセル間の色の輝度値を強調表示します。

エッジ検出とは画像のエッジ情報、つまり画素が大きく変化する箇所を見つけること、つまり微分値の勾配値を計算することであり、主に1次微分や2次微分などの計算が一般的に用いられます-次数差具体的には、ニーズに応じて適切な方法を選択する必要があります。

好的检测结果: エッジの誤検出率が低いため、実際のエッジを検出する際は誤検出を避け、画像上の実際のエッジ位置にできるだけ近いマーキングエッジ位置を設定してください。

(画素間の変化の強さ)を計算する場合图像的梯度、1次元データの差分導出とは異なり、主に2次元以上の配列に対して畳み込み演算が使用されます(畳み込み演算とは何か、自分で調べてください、最近知られるようになりました)ディープ ラーニング ネットワークの火災のため、皆様にお知らせします)、以下にいくつかの一般的な画像鮮明化アルゴリズムを示します。

1. ラプラシアンシャープ化:

ラプラスは 2 次微分計算です。元の画像にラプラシアン フィルターを適用して画像のエッジと詳細を強調すると、エッジの位置が正確になり、ノイズの影響を非常に受けやすくなります。
派生ラプラシアン カーネルの 2 つの一般的な例は次のとおりです。ラプラシアン コンボリューション カーネルの中心値は比較的大きいため、計算では画像の現在のピクセル値が大きな重みを占めます。シャープニング時に周囲のピクセルとの差を大きくするために、周囲のピクセル値が小さいです。コンボリューション カーネルでは、中心ピクセル値は 9 です。これは、中心ピクセルの強度値が増加し、周囲のピクセルの強度値が減少することを意味します。こうすることで、シャープ化された画像のエッジが強調され、細部がより鮮明になります。これにより、計算後に急激に変化するピクセルがより目立ち、ゆっくりと変化するピクセルは相対的に弱められます。

ここに画像の説明を挿入

ラプラシアン

ここに画像の説明を挿入

元の画像

ここに画像の説明を挿入

ラプラス

(滑らかではありませんが、目立ちます)

短所: この方法では、画像ノイズが増加し、エッジ方向情報の一部が失われ、検出されたエッジが不連続になる可能性があります。利点: 方向に関係なく、x 方向と y 方向の両方が考慮されるため、ステップ エッジ検出が非常に正確になります。

2. ガウス ラプラシアン オペレーター シャープニング (LoG):

この方法は、ラプラシアン アルゴリズムよりも優れたエッジ検出器です。ガウスぼかしスムーザーとラプラシアン シャープニングを組み合わせ、最初にガウス カーネルを使用して画像の平滑化とノイズ除去を行い、次にラプラシアン カーネルを使用して画像のエッジ検出とシャープニングを実行します。
コンボリューションカーネルの中心の重みは非常に大きく、周囲の重み係数は距離が増加するにつれて徐々に減少します。2 つのガウス ラプラス コンボリューション カーネルの例は次のとおりです。

(右はUsharpeマスキング法)

ここに画像の説明を挿入

元の画像

ここに画像の説明を挿入

LoG(中間オペレーター)

(ラプラス効果より滑らか)

ここに画像の説明を挿入

Usharpe マスキング (右側の演算子)

(ラプラス効果より滑らか)

利点: 主に、ガウス平滑化を考慮したラプラシアン オペレーターの最適化のため、ラプラシアン オペレーターのノイズ抑制能力が低いという問題が軽減されます。短所: しかし同時に、一部の鋭い高周波特徴がある程度平滑化されることは避けられず、ガウス畳み込みの分散パラメータがエッジ検出効果に一定の影響を与えます。

3. Roberts 演算子のシャープ化:

斜めずれ点の勾配計算方法であり、勾配の大きさはエッジの強さを表し、勾配の方向はエッジの方向と直交する。畳み込みカーネルは次のとおりです。

ロバーツオペレーター

ここに画像の説明を挿入

元の画像

ここに画像の説明を挿入

ロバーツ (左オペレーター)

ここに画像の説明を挿入

ロバーツ (右オペレーター)

短所: 対角線の減算、比較的高い位置決めが行われますが、スムージングがなく、直接の減算で、エッジの一部が失われやすく、ノイズに耐性がありません。利点: ただし、エッジが急峻でノイズが少ない画像には適しています。

4. ソーベル演算子のシャープ化:

元の画像にソーベル オペレータを適用すると、画像の水平エッジと垂直エッジを強調できます。この方法は、ラプラシアン シャープニングよりも滑らかです。畳み込みカーネルは次のとおりです。

ソーベル演算子

ここに画像の説明を挿入

元の画像

ここに画像の説明を挿入

ソーベル (左オペレーター)

ここに画像の説明を挿入

ソーベル (右オペレーター)

短所: ノイズを滑らかにして抑制する一定の能力がありますが、誤ったエッジ検出が発生し、マルチピクセルのエッジ幅を検出するのが簡単です。

5. プレウィットアルゴリズム:

Prewitt アルゴリズムは、畳み込みカーネルの重み値が異なることを除いて、sobel アルゴリズムに似ています。Prewitt アルゴリズムのコンボリューション カーネル テンプレートは、周囲のピクセルの中央位置のピクセルの重みが 2 辺の重みと同じであるため、周囲の 3 つの隣接するピクセルが現在のピクセルに同じ影響を与えます。畳み込みカーネルは次のとおりです。

プレウィット演算子

ここに画像の説明を挿入

元の画像

ここに画像の説明を挿入

プレウィット (左オペレーター)

ここに画像の説明を挿入

プレウィット (オペレーター)

6. Canny オペレーターのシャープ化:

Canny オペレーター シャープニングは、より実際のエッジを維持しながらノイズを低減する多段階エッジ検出アルゴリズムです。Canny の出力はバイナリデータ (エッジ、非エッジ) であるため、シャープニングでは現時点ではこの方法は考慮されていません。

Canny エッジ検出アルゴリズムには主に次の 5 つのステップが含まれます。

  • 画像をガウス フィルターしてノイズを除去します。
  • 画像の勾配の大きさと方向を計算します。
  • 勾配の大きさの非最大抑制。
  • デュアルしきい値処理を使用したエッジ トラッキング。
  • ノイズを除去してエッジを接続します。

Canny エッジ検出の特定の GLSL 実装については、リンク (代替) を参照してください。

7. アンシャープマスキングのシャープ化:

アンシャープ マスキングは、一般的に使用される画像強調技術でもあり、元の画像をガウスぼかし、元の画像から減算し、その結果に強化されたシャープニング フィルターを適用することにより、画像の細部とエッジを強調します。
元々は暗室写真で使用されていました。この名前は、このテクニックがぼやけた、または「鮮明でない」ネガティブ画像を使用して元の画像のマスクを作成するという事実に由来しています。次に、アンシャープ マスクを元のポジ画像と組み合わせて、元の画像よりもぼやけの少ない画像を作成します。結果として得られる画像は鮮明ではありますが、画像の主題の表現の精度が低くなる可能性があります。
畳み込みカーネルは次のとおりですその計算プロセスは次のとおりです。

これはガウス ラプラシアン演算子の一種であり、その効果は次のとおりです。

ここに画像の説明を挿入

元の画像

ここに画像の説明を挿入

アンシャープ マスキング (LoG オペレーター)

コード実装ルーチン:

主にC++Pythonシェーダ GLSLによって実現されます。

(1)。OpenCV(C++):

#include <opencv2/opencv.hpp>
using namespace cv;

int main() {
// 读取图像
Mat img = imread("image.jpg");
// 定义锐化卷积核(以拉普拉斯算子为例)
Mat kernel = (Mat_<float>(3,3) << -1,-1,-1,
                                   -1, 9,-1,
                                   -1,-1,-1);

// 应用锐化卷积核
Mat sharp_img;
filter2D(img, sharp_img, -1, kernel);

// 显示原图和锐化后的图像
namedWindow("Original Image");
namedWindow("Sharpened Image");
imshow("Original Image", img);
imshow("Sharpened Image", sharp_img);
waitKey(0);
destroyAllWindows();

return 0;
}

(2)。OpenCV(Python):

import cv2
import numpy as np

# 读取图像
img = cv2.imread('image.jpg')

# 定义锐化卷积核(以拉普拉斯算子为例)
kernel = np.array([[-1,-1,-1],
                   [-1, 9,-1],
                   [-1,-1,-1]])

# 应用锐化卷积核
sharp_img = cv2.filter2D(img, -1, kernel)

# 显示原图和锐化后的图像
cv2.imshow('Original Image', img)
cv2.imshow('Sharpened Image', sharp_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

(3). GLSL バージョン (フラグメント シェーダー):

varying vec2 vv2_Texcoord;   // 纹理坐标
uniform sampler2D m_texture; // 原图片

vec3 mtexSample(const float x, const float y)
{
    vec2 uv = vv2_Texcoord + vec2(x / 1280.0, y / 720.0); // 纹理分辨率:1280,720
    lowp vec3 textureColor = texture2D(m_texture, uv);    // 图像纹理采样
    return textureColor;
}

vec3 sharpen(vec2 fragCoord, float strength)
{
    //卷积核 (以拉普拉斯算子为例)
    vec3 f =
        mtexSample(-1.0, -1.0) * -1.0 +
        mtexSample(0.0, -1.0) * -1.0 +
        mtexSample(1.0, -1.0) * -1.0 +

        mtexSample(-1.0, 0.0) * -1.0 +
        mtexSample(0.0, 0.0) * 9.0 +
        mtexSample(1.0, 0.0) * -1.0 +

        mtexSample(-1.0, 1.0) * -1.0 +
        mtexSample(0.0, 1.0) * -1.0 +
        mtexSample(1.0, 1.0) * -1.0;

    return mix(vec4(mtexSample(0.0, 0.0), 1.0), vec4(f, 1.0), strength).rgb;
}

void main()
{
    vec3 sharpened = sharpen(vv2_Texcoord, 1.0);
    gl_FragColor = vec4(sharpened, 1.0);
}

おすすめ

転載: blog.csdn.net/sCs12321/article/details/129459772