前提・実現したいこと
現在、Python3で画像処理の鮮鋭化を勉強しております。
その中で、鮮鋭化フィルタをかけた際に0~255の値から外れた値が出てきました。
色々なサイトをみて回ったものの0~255以外をカットする方法しか見当たらなく、強制的に丸める方法で実装していましたが、鮮鋭化フィルタにかける定数倍の値を大きくするとかなり汚くなりました。
そこで、全体を同比補正するために画素の配列をフィルタ適用後、全体に最小値の分だけ足して全体に、255/abs(max-min)をかけて0~255に収まるよう補正しましたがこちらも定数倍の値を大きくする度に、鮮鋭化は強くなってる気はするのですがそれ以上に画像が潰れて汚くなってしまいました。
なので、自力で実装したいのでOpenCVやPILのImageFilterなどの画像処理ライブラリは使わない方法で、他に良い方法があれば教えて頂きたいです。
発生している問題・エラーメッセージ
実行結果
k=4, 最小値:-270.1111111111111, 最大値:636.9999999999999 k=9, 最小値:-648.0, 最大値:1142.0 k=18, 最小値:-1344.0, 最大値:2051.0
該当のソースコード
Python3
1import numpy as np # 行列の計算用 2from PIL import Image # 画像の読み込み用 3 4# 元画像を読み込む 5image = Image.open('gray02.jpg') 6# 元の画像 7image.convert("L").show() 8 9############################################### 10# 鮮鋭化を行う関数 11# 12# @param int size 鮮鋭化フィルタのサイズ 13# @param int k 入力画素-平滑化画素にかける定数倍の値 14############################################### 15def sharpening_filter(size=3, k=4): 16 17 image_array = np.array(image.convert("L")) # 元画像 18 sharp_image_array = np.array(image.convert("L"), dtype='float64') # 元画像 19 20 ######################### 21 # 鮮鋭化を行う 22 ######################### 23 # 色々と使うので先にずらす値を変数として作っておく 24 slide = int(size/2) 25 # 平均化フィルタ 26 avg_filter = np.full((size, size), 1/size**2) 27 # 入力画素だけ出力するフィルタ 28 input_filter = np.zeros((size, size)) 29 input_filter[slide][slide] = 1 30 # 鮮鋭化フィルタ 31 sharp_filter = input_filter + (k * ( input_filter - avg_filter )) 32 33 min = 0 # 最小値 34 max = 0 # 最大値 35 36 # 鮮鋭化の処理を行う 37 # 縦にかけるループ 38 for row_index in range(slide, len(image_array)-slide): 39 # 横にかけるループ 40 for column_index in range(slide, len(image_array[row_index])-slide): 41 # 注目画素を新しいくするために、一旦0クリアする 42 new_pixel_value = 0 43 # 注目画素と周囲の画素にフィルタをかけて積和の値で画素を更新する 44 # 行列を横1列に変換する 45 input_temp = image_array[row_index-slide:row_index+slide+1, column_index-slide:column_index+slide+1].ravel() 46 sharp_temp = sharp_filter.ravel() 47 # 変換した行列の積和をとる 48 new_pixel_value = np.sum( np.multiply(input_temp, sharp_temp) ) 49 # 最小値・最大値の比較を行う 50 min = min if min < new_pixel_value else new_pixel_value 51 max = max if max > new_pixel_value else new_pixel_value 52 # 適用後の値で更新する 53 sharp_image_array[row_index][column_index] = new_pixel_value 54 55 # 最小値と最大値を表示する 56 print("k={0}, 最小値:{1}, 最大値:{2}".format(k, min, max)) 57 58 delta = abs(max - min) # 最大値と最小値の幅 59 mag = 255 / delta # 補正するための倍率 60 61 # 縦にかけるループ 62 for row_index in range(slide, len(image_array)-slide): 63 # 横にかけるループ 64 for column_index in range(slide, len(image_array[row_index])-slide): 65 # minの値分だけずらして最小値を0にする 66 temp = sharp_image_array[row_index][column_index] + abs(min) 67 # 0~255に収まるようにする 68 temp *= mag 69 # 値を更新 70 sharp_image_array[row_index][column_index] = temp 71 72 # フィルタリングした画像にする 73 sharp_image = Image.fromarray(np.uint8( sharp_image_array ) ) 74 # フィルタリングした変換結果を表示する 75 sharp_image.show() 76 77# 鮮鋭化を行う 78sharpening_filter(3, 4) # k = 4 79sharpening_filter(3, 9) # k = 9 80sharpening_filter(3, 18) # k = 18
補足情報(FW/ツールのバージョンなど)
Python 3.8.0
Numpy 1.17.4
PIL 6.2.1
追記
ソースコードを見るとわかると思いますが、フィルタのかけられない画像の端の方などはそのまま出力するようにしております。
回答1件
あなたの回答
tips
プレビュー