bonclumsy
@bonclumsy

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

欠点画像の画像処理と指標化について

欠点の指標化

下記の画像で中央やや左側の縦線が欠点なのですが、こちらを抽出して数値化し欠点判定を行いたいです。

全体的に汚れのようなノイズがあるので、これらを消去したい。
縦線の欠点には影響を及ぼさないで、ノイズを消去する一番効果のある方法をご教示いただきたいです。
また全体を通して、お勧めの処理方法をご教示いただきたいです。
1.jpg

発生している問題・エラー

現在はコントラストを単純にグラフ化しておりますが、どう改善したらよいか苦悩しております。

該当するソースコード

from PIL import Image
import matplotlib.pyplot as plt

def calculate_contrast(column_pixels):
    return max(column_pixels) - min(column_pixels)

def plot_contrast_graph(column_contrasts, label):
    plt.plot(column_contrasts, label=label)

def main():
    # 画像の読み込み
    image_path = '1.jpg'   # 画像のパスを指定
    image = Image.open(image_path)

    # 上から10ピクセル目から50ピクセル目までの全幅方向のコントラストを計算
    width, height = image.size
    pixels = list(image.getdata())
    start_indexes = [10 * width, 20 * width, 30 * width, 40 * width, 50 * width]
    end_indexes = [(10 + 1) * width, (20 + 1) * width, (30 + 1) * width, (40 + 1) * width, (50 + 1) * width]

    column_contrasts = [[] for _ in range(len(start_indexes))]

    for i, (start_index, end_index) in enumerate(zip(start_indexes, end_indexes)):
        for j in range(start_index, end_index):
            column_pixels = [pixels[k][0] for k in range(j, len(pixels), width)]
            contrast = calculate_contrast(column_pixels)
            column_contrasts[i].append(contrast)

        label = f'{(i + 1) * 10}th pixel'
        plot_contrast_graph(column_contrasts[i], label=label)

    # グラフを作成して表示
    plt.xlabel('Width')
    plt.ylabel('Contrast')
    plt.title('Contrast across Width')
    plt.legend()
    plt.show()

if __name__ == '__main__':
    main()
0

2Answer

scikit-imageやopencvなどの画像解析moduleを使うと様々なフィルタが用意されています。
縦線ををノイズと認識させないためには縦方向に長いfootprintを使ってフィルタをかけるといいです。
ノイズ消去はSmoothing filterが良いと思いますが、median filter とgaussian filterの例をあげています。ノイズの検知としてgradient とentropyの例をあげています。


#%%
import numpy as np
import matplotlib.pyplot as plt
from skimage import filters, morphology

#%% サンプル画像作成
# sample_img = np.random.standard_normal(size=(100, 100))
sample_img = np.zeros((100, 100))
# add linear bright line 
for i in range(5):
    column_idx = np.floor(np.random.rand() * 100).astype(int)
    sample_img[:, column_idx] += 4

# add noise blob
for i in range(10):
    noise_image = np.zeros((100, 100))
    column_idx = np.floor(np.random.rand() * 100).astype(int)
    row_idx = np.floor(np.random.rand() * 100).astype(int)
    noise_image[row_idx, column_idx] = np.random.rand() * 100
    noise_image = filters.gaussian(noise_image, sigma=1 + np.random.rand() * 3)
    sample_img += noise_image
sample_img= sample_img/np.max(np.abs(sample_img))
plt.imshow(sample_img)

# %%
footprint = morphology.rectangle(30, 1) #ここで縦方向に何ピクセルを使うかを指定

# median filter(中央値に置き換え)
median_img = filters.median(sample_img, footprint=footprint) 
# gaussian filter (ガウシアンフィルタ、sigmaで縦長を指定)
gaussian_img = filters.gaussian(sample_img, sigma=(20,0.1))
# 提示されている方法 (ローカルのmax-min)
min_img = filters.rank.minimum(sample_img, footprint=footprint)
max_img = filters.rank.maximum(sample_img, footprint=footprint)
contrast_img = max_img - min_img
# 同じ方法
gradient_img = filters.rank.gradient(sample_img, footprint=footprint)
# エントロピー
entropy_img = filters.rank.entropy(sample_img, footprint=footprint)

plt.imshow(median_img)
plt.show()
plt.imshow(gaussian_img)
plt.show()
plt.imshow(contrast_img)
plt.show()
plt.imshow(gradient_img)
plt.show()
plt.imshow(entropy_img)
plt.show()

0Like

とりあえずイメージが分かりにくいのでコントラストと明るさをあげましたが
image.png

縦線の欠点には影響を及ぼさないで、

下図のイメージだとしたら、おそらく縦線を検知してそこ以外をフィルタ除外するイメージなので縦線検出が必要かと思われます。
image.png

0Like

Your answer might help someone💌