なんとか破損していて、バックアップイメージを失った約1,400のJPEGがあります。それらはすべて、それぞれに同じグリッド線のパターンがあるように見えます(つまり、グリッド線は画像間で移動しません。
これらの画像の1つは次のようになります。
このグリッドパターンを削除または平滑化する、Matlab固有の画像フィルタリング技術などはありますか?
なんとか破損していて、バックアップイメージを失った約1,400のJPEGがあります。それらはすべて、それぞれに同じグリッド線のパターンがあるように見えます(つまり、グリッド線は画像間で移動しません。
これらの画像の1つは次のようになります。
このグリッドパターンを削除または平滑化する、Matlab固有の画像フィルタリング技術などはありますか?
回答:
標準の修復アルゴリズムを使用できます。これらのアルゴリズムは、画像内のマークされたピクセルを、これらのマークされたピクセルを囲むピクセル値に置き換えます。ここでの課題は、グリッドを検出することです(私のテストでは、完全に通常のグリッドではないようです)。だから、私はこの解決策を思いつきました:
from PIL import Image
import requests
from io import BytesIO
import cv2
url = "http://i.stack.imgur.com/Ahrnl.jpg"
response = requests.get(url)
img = Image.open(BytesIO(response.content))
plt.imshow(img)
A = np.array(img)
A2 = A.copy()
A_gray = cv2.cvtColor(A, cv2.COLOR_RGB2GRAY)
# Do some rough edge detection to find the grid
sX = cv2.Sobel(A_gray, cv2.CV_64F, 1, 0, ksize=3)
sY = cv2.Sobel(A_gray, cv2.CV_64F, 0, 1, ksize=3)
sX[sX<0] = 0
sY[sY<0] = 0
plt.subplot(221)
plt.imshow(sX)
plt.subplot(222)
plt.imshow(sY)
plt.subplot(223)
# the sum operation projects the edges to the X or Y-axis.
# The 0.2 damps the high peaks a little
eX = (sX**.2).sum(axis=0)
eX = np.roll(eX, -1) # correct for the 1-pixel offset due to Sobel filtering
plt.plot(eX)
plt.subplot(224)
eY = (sY**.2).sum(axis=1)
eY = np.roll(eY, -1)
plt.plot(eY)
mask = np.zeros(A2.shape[:2], dtype=np.uint8)
mask[eY>480,:] = 1
mask[:, eX>390] = 1
A2[mask.astype(bool),:] = 255
plt.figure()
plt.subplot(221)
plt.imshow(A)
plt.subplot(222)
plt.imshow((A2))
restored = cv2.inpaint(A, mask, 1, cv2.INPAINT_NS)
plt.subplot(223)
plt.imshow(restored)
プログラムの出力は次のとおりです。
グリッドを検出するために、私は迅速かつ汚いソリューションを行いました。かなり改善できますが、それは最初のアイデアを示しています。一般的なフローは次のとおりです。
インペイントには、OpenCV インペイント操作を使用しました。グリッドを検出するために、ソーベルフィルターを使用してXおよびY方向のエッジ検出を実行しました。次に、X方向とY方向のすべてのエッジ値を追加して、グリッド線があるピークを見つけます。次に、グリッド線が推定される座標として、最も高いピークを選択します。これは完全に機能しているわけではありません(たとえば、画像の強いエッジがグリッドラインとして誤って検出されるなど)が、それはアイデアを示しています。たとえば、ラインを見つけるためのハフ変換、非常に強いエッジの蹴り出しなどによって改善できます。
または、グリッドがすべての画像で本当に同じである場合、すべての画像でグリッド検出を同時に実行できます。これにより、はるかに優れた精度が得られます(上記の手法を実行するだけですが、ピークを選択する前に、からの結果を合計します。すべての写真)。より詳細には、すべての画像のeXを計算し、これらすべてのeXを1つのベクトルに追加します。このベクトルは、より明確なピーク構造を持ち、しきい値処理をより簡単に行うことができます。
その画像のRチャネルとGチャネルで3x3メディアンフィルターを実行するという非常に単純なアルゴリズムを試してみましたが、非常にうまく機能しました。 Pythonコードは本当にシンプルです。
import scipy.signal as sp
from scipy import ndimage
image = ndimage.imread('Ahrnl.jpg', flatten=False)
image_filtered = np.array(image)
for i in range(2) :
image_filtered[:,:,i] = sp.medfilt2d(image[:,:,i])
または、この質問で説明されているように、周波数ドメインフィルタリングを使用することもできます。
画像のフーリエ変換は、この周期的なノイズに対応するスペクトル内のいくつかの「ドット」の繰り返しを明確に示しています。
Maximilianが指摘したように、この後者の方法は、ノイズが完全に周期的である場合にのみうまく機能しますが、ここではそうではないようです。
私はxとyの両方の方向で9の倍数を中心とする5x5平方の周波数ビンをゼロにして、ノイズを抑制しますがノイズを含まない場所にアーティファクトを導入する本当に愚かなフィルターを実行してみました(たとえば、空)。
おそらく、FFTビンを直接ゼロにする(実際には絶対に行わないでください)代わりに注意深くノッチフィルターを設計し、ノイズが存在する画像の領域にのみフィルターを適用する(つまり、空をフィルターしない)ことで、より良い結果が得られます。