破損したjpegからグリッドパターンを削除するために適用できる画像フィルターはどれですか。


8

なんとか破損していて、バックアップイメージを失った約1,400のJPEGがあります。それらはすべて、それぞれに同じグリッド線のパターンがあるように見えます(つまり、グリッド線は画像間で移動しません。

これらの画像の1つは次のようになります。

ここに画像の説明を入力してください

このグリッドパターンを削除または平滑化する、Matlab固有の画像フィルタリング技術などはありますか?


2
これらの画像がどのようにして破損したのか、詳しい情報を教えてください。これは奇妙なパターンです。これは非常にピクセルローカルであり、周波数領域で高解像度を必要とするため、恐らくひどく壊れたJPEGエンコーダーを意味しますか?
MarcusMüller2017年

すみません、よくわかりません。画像は数回手を変えたデータベースの一部であり、人々は彼らが持っているべきであるほどに注意を払っていません(...学部生)。ピクセルローカルの問題に関しては、私は同意します。暗い水面を含むいくつかの写真では、グリッドパターンは非常に明るくなっています。
スティーブンE

@MarcusMüller:恐ろしく壊れたJPEG デコーダーは私にはより可能性が高いようですが、どちらの方法も可能だと思います。いずれにせよ、ラインの2のべき乗ではない不均一な間隔に基づいて、破損が発生した後、画像がおそらく拡大され、再エンコードされているように思えます。 DCTドメインはおそらく無駄です。以下のMaximilianMatthéによる修復ソリューションは、おそらくOPの最善の策です。
Ilmari Karonen 2017年

1
ああ、そして誰かが再分析したい場合に備えて、OPは何らかの方法で画像を修正するに、必ず画像のバックアップを保存する必要があります。インペインティングは、うまくできていても、常に損失の多い操作であり、バイアスを導入する可能性があります(基本的に、破損したピクセルを置き換えるために偽のデータを作成することになるため)。中央値フィルタリングや周波数除去など、この種の損傷を隠す可能性のあるものについても同様です。
Ilmari Karonen 2017年

@IlmariKaronen先端をありがとう。間違いなくこれらの画像をもっと注意してみます。
スティーブンE

回答:


16

標準の修復アルゴリズムを使用できます。これらのアルゴリズムは、画像内のマークされたピクセルを、これらのマークされたピクセルを囲むピクセル値に置き換えます。ここでの課題は、グリッドを検出することです(私のテストでは、完全に通常のグリッドではないようです)。だから、私はこの解決策を思いつきました:

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)

プログラムの出力は次のとおりです。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

グリッドを検出するために、私は迅速かつ汚いソリューションを行いました。かなり改善できますが、それは最初のアイデアを示しています。一般的なフローは次のとおりです。

  1. グリッドを検出する
  2. グリッドによって破損しているピクセルを説明するマスクを作成する
  3. 破損したピクセルを修復します。

インペイントには、OpenCV インペイント操作を使用しました。グリッドを検出するために、ソーベルフィルターを使用してXおよびY方向のエッジ検出を実行しました。次に、X方向とY方向のすべてのエッジ値を追加して、グリッド線があるピークを見つけます。次に、グリッド線が推定される座標として、最も高いピークを選択します。これは完全に機能しているわけではありません(たとえば、画像の強いエッジがグリッドラインとして誤って検出されるなど)が、それはアイデアを示しています。たとえば、ラインを見つけるためのハフ変換、非常に強いエッジの蹴り出しなどによって改善できます。

または、グリッドがすべての画像で本当に同じである場合、すべての画像でグリッド検出を同時に実行できます。これにより、はるかに優れた精度が得られます(上記の手法を実行するだけですが、ピークを選択する前に、からの結果を合計します。すべての写真)。より詳細には、すべての画像のeXを計算し、これらすべてのeXを1つのベクトルに追加します。このベクトルは、より明確なピーク構造を持ち、しきい値処理をより簡単に行うことができます。


ご入力ありがとうございます!ここでの結果は本当に素晴らしいです!これをやってみます。免責事項:私は画像処理の初心者なので、自分で作業するのには時間がかかりますが、あなたの側でうまく機能するので、解決済みとマークします。このアルゴリズムを実行している環境は何ですか?画像の大部分はそれらのいずれも含まず、単なるタンドラまたは水、あるいはその両方であるため、画像内の計装およびインフラストラクチャでの望ましくないエッジ検出はそれほど問題にはならないと思います。すべての写真のピークを合計するにはどうすればよいですか?
スティーブンE

ありがとう!環境はPythonであり、すべての画像のピークを合計することの意味についてのメモを追加しました。
MaximilianMatthé2017年

3

その画像の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ビンを直接ゼロにする(実際には絶対に行わないでください)代わりに注意深くノッチフィルターを設計し、ノイズが存在する画像の領域にのみフィルターを適用する(つまり、空をフィルターしない)ことで、より良い結果が得られます。

ここに画像の説明を入力してください


最後の行では、赤のチャネルを2回フィルターするだけだと思います(最後のインデックスは0ではなくiにする必要があります)
MaximilianMatthéJan

@MaximilianMatthéグッドキャッチ!(幸いにも、実行した実際のコードは問題ありませんでした:P)
Atul Ingle

フーリエ変換法に関して:これが確実に機能するのは、グリッドが本当に規則的である(つまり、すべての線の間の距離が同じ)場合のみです。壊れた線の上に通常のグリッドを描画できるようなパラメーターを(少なくともすぐに)見つけることができませんでした。次に、フーリエ法は、この正確ではない周期的なノイズを除去することもできません。
MaximilianMatthé2017年

@MaximilianMatthé正解-ノイズは完全に周期的なパターンではないため、FFT法はトリッキーです。しかし、注意深いノッチフィルター設計で動作する可能性があります。多分。
Atul Ingle

ご入力ありがとうございます!(主に)私は、画像の細部の減少好きではなかった(彼らは、Webマッピングアプリケーションにポップアップで表示する必要がある私は、MATLABで3×3のメディアンフィルタを試してみました、それがグリッド化を削除しなかったが。
スティーブンE
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.