OpenCVで画像をシャープにする方法を教えてください。


122

OpenCVを使用して画像をシャープにする方法を教えてください。

滑らかにする方法やぼかす方法はたくさんありますが、シャープにする方法はありません。

回答:


160

一般的な手順の1つは、ウィキペディアのアンシャープマスキングに関する記事に記載されています。

ガウス平滑化フィルターを使用して、元の画像から平滑化されたバージョンを減算します(一定の領域の値が一定に保たれるように重み付けされた方法で)。

frameintoのシャープバージョンを取得するにはimage:(両方cv::Mat

cv::GaussianBlur(frame, image, cv::Size(0, 0), 3);
cv::addWeighted(frame, 1.5, image, -0.5, 0, image);

パラメータには、自分で調整する必要があるものがあります。

ラプラシアンシャープニングもあります。グーグルすると、その上に何かを見つけるはずです。


1
アンシャープマスクの結果をPhotoshopで再現する方法はありますか?
Royi 14

@Drazickそれは複製することができないのであなたは尋ねていますか?ウィキペディアへのリンクは上記に記載されています。digital_unsharp_maskingを具体化
tilaprimera 2014年

@ tilaprimera、PhotoshopのUSMは「クラシック」USMとは異なるため、私は尋ねています。
Royi

50

簡単なカーネルfilter2D関数を試すことができます。例:Python:

kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
im = cv2.filter2D(im, -1, kernel)

Wikipediaにはカーネルの優れた概要があり、ここにいくつかの例があります-https://en.wikipedia.org/wiki/Kernel_(image_processing)

画像処理では、カーネル、畳み込み行列、またはマスクは小さな行列です。ぼかし、シャープ、エンボス、エッジ検出などに使用されます。これは、カーネルとイメージの間でたたみ込みを行うことによって実現されます。


14

OpenCV Documentationで、「アンシャープマスク」アルゴリズムを使用して画像をシャープにするサンプルコードを見つけることができます。

値を変更sigmathresholdamount異なる結果が得られます。

// sharpen image using "unsharp mask" algorithm
Mat blurred; double sigma = 1, threshold = 5, amount = 1;
GaussianBlur(img, blurred, Size(), sigma, sigma);
Mat lowContrastMask = abs(img - blurred) < threshold;
Mat sharpened = img*(1+amount) + blurred*(-amount);
img.copyTo(sharpened, lowContrastMask);

美しいです!
ルーズベルト

12

アンシャープマスクを使用して画像をシャープにすることができます。アンシャープマスキングの詳細については、こちらをご覧ください。そして、OpenCVを使用したPython実装は次のとおりです。

import cv2 as cv
import numpy as np

def unsharp_mask(image, kernel_size=(5, 5), sigma=1.0, amount=1.0, threshold=0):
    """Return a sharpened version of the image, using an unsharp mask."""
    blurred = cv.GaussianBlur(image, kernel_size, sigma)
    sharpened = float(amount + 1) * image - float(amount) * blurred
    sharpened = np.maximum(sharpened, np.zeros(sharpened.shape))
    sharpened = np.minimum(sharpened, 255 * np.ones(sharpened.shape))
    sharpened = sharpened.round().astype(np.uint8)
    if threshold > 0:
        low_contrast_mask = np.absolute(image - blurred) < threshold
        np.copyto(sharpened, image, where=low_contrast_mask)
    return sharpened

def example():
    image = cv.imread('my-image.jpg')
    sharpened_image = unsharp_mask(image)
    cv.imwrite('my-sharpened-image.jpg', sharpened_image)

これはかなり便利なバージョンのようです。パラメータについてもう少し情報を追加してください。カーネルサイズとシグマはopencvで検索できますが、量としきい値はどうですか?ありがとう!
チョイス

2
@choise amountは、シャープの量です。たとえばamount、2.0の場合、デフォルト値の1.0に比べて画像がよりシャープになります。threshold低コントラストマスクのしきい値です。言い換えると、入力画像とぼやけた画像の差がそれよりも小さいピクセルthresholdは変更されません。
Soroush

10

任意の画像は、さまざまな周波数の信号の集まりです。高い周波数はエッジを制御し、低い周波数は画像コンテンツを制御します。エッジは、隣接するセルの0や255のように、あるピクセル値から別のピクセル値への急激な遷移があるときに形成されます。明らかに、急激な変化があり、エッジと高周波数があります。画像をシャープにするために、これらの遷移をさらに強化できます。

1つの方法は、自作のフィルターカーネルと画像を畳み込むことです。

    import cv2
    import numpy as np

    image = cv2.imread('images/input.jpg')
    kernel = np.array([[-1,-1,-1], 
                       [-1, 9,-1],
                       [-1,-1,-1]])
    sharpened = cv2.filter2D(image, -1, kernel) # applying the sharpening kernel to the input image & displaying it.
    cv2.imshow('Image Sharpening', sharpened)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

明るいバージョンの画像からぼやけたバージョンの画像を差し引く別の方法があります。これは画像をシャープにするのに役立ちます。ただし、ピクセル値を増やすだけなので、注意して行う必要があります。グレースケールピクセル値190を想像してください。これに2の重みを掛けると380になりますが、最大許容ピクセル範囲のため、255でトリミングされます。これは情報の損失であり、画像が色あせます。

    addWeighted(frame, 1.5, image, -0.5, 0, image);

5

このトピックを明確にするために、いくつかのポイントを実際に作成する必要があります。

  1. 画像をシャープにすることは不適切な問題です。つまり、ぼかしは不可逆な操作であり、ぼかしから戻ることは一般的に不可能です。

  2. 単一の画像を鮮明にするためには、どういう画像にするか、どのようにぼかすようにするかについて、何らかの方法で制約(仮定)を追加する必要があります。これは自然画像統計の領域です。鮮明化を行うアプローチは、これらの統計をアルゴリズムに明示的または暗黙的に保持します(ディープラーニングが最も暗黙的にコード化されたものです)。DOGまたはラプラシアンピラミッド分解のいくつかのレベルをアップウェイトする一般的なアプローチは、ブライアンバーンズの回答を一般化したもので、ガウスぼかしにより画像が破損し、ウェイト付けがどのように行われたかが、まずは画像で。

  3. 他の情報源は、問題を適切にシャープにすることができます。このような一般的な情報源は、動いているオブジェクトのビデオ、またはマルチビュー設定です。その設定でのシャープニングは、通常、超解像と呼ばれます(これは非常に悪い名前ですが、学界で立ち往生しています)。ありましたOpenCVの中に超解像法の実際の問題は、最後のウェルのために、私はそれらをチェックアウトすることを、彼らは通常、いけない仕事が....長い時間以来。ここでもディープラーニングが素晴らしい結果を生んでいると思います。多分誰かがそこに価値があるものについてのコメントを投稿するでしょう。


3

画像をシャープにするために、フィルターを使用できます(以前の多くの回答と同様)。

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel /= denominator * kernel

分母が1のときに最も多くなり、増加すると減少します(2.3 ..)

最もよく使用されるのは、分母が3の場合です。

以下は実装です。

kernel = np.array([[-1, -1, -1],[-1, 8, -1],[-1, -1, 0]], np.float32) 

kernel = 1/3 * kernel

dst = cv2.filter2D(image, -1, kernel)

「一番だろう」の近くに欠けているようです。
Peter Mortensen

うんピーター、ありがとう!
kaustubhd9

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.