--- a +++ b/hsv_remove.py @@ -0,0 +1,119 @@ +import time +import copy +import os +import glob +import numpy as np +import pandas as pd +import cv2 + +#複数の画像にHSV条件による画像の削減を行い削減後の画像を保存 +# ※simplemain()の引数を設定して使用するとできる + +def jugde_bleeding_hsv(img, h_low=20, h_high=200, s_low=120, v_low=5, opening_noise_removing=True, opening_kernel=5, height=512, width=512): + ''' + height×widthのカラー内視鏡画像(numpy.ndarray)一枚に対しHSV条件に当てはまる画素数を返す + 流れ:HSV条件に当てはまる座標の取得⇒(オープニング処理でノイズ除去)⇒条件に当てはまる座標の個数(red_area_px)と条件に当てはまる画素を白にしたサイズがheight×widthの画像(red_area)を返す + ''' + img_hsv = copy.deepcopy(img) + img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV_FULL) + red_area = np.zeros((height, width, 1), dtype=np.uint8) + # 条件に当てはまるとき、red_area(真っ黒な画像)のその領域を255にする + red_area[:,:,0] = np.where((img_hsv[:,:,0]>=h_low) & (img_hsv[:,:,0]<=h_high) & (img_hsv[:,:,1]>=s_low) & (img_hsv[:,:,2]>=v_low), 255, 0) + if opening_noise_removing: + # 出血判定した領域にオープニング処理することで小さい領域を消去 + kernel = np.ones((opening_kernel, opening_kernel),np.uint8) + red_area = cv2.morphologyEx(red_area, cv2.MORPH_OPEN, kernel) + else: + red_area = np.reshape(red_area, (height, width)) + # 全出血領域の画素数の合計 + red_area_px = cv2.countNonZero(red_area)#ほぼ0s + return red_area_px, red_area + +def simplemain(png_path='data_all_red/angio_bleeding', out_path='', h_low=0, h_high=15, s_low=205, v_low=156, range360degree_100percent=True, opening_noise_removing=True, opening_kernel=5, height=512, width=512, stat_area=300, source_save=False, r_display=0, g_display=255, b_display=0): + ''' + height×widthのカラー内視鏡画像に対しHSV条件に当てはまる画像を保存 + (保存先:out_path/png_path/-h-_-s_-v(_360degree100percent_opening_kernel-)/.png) + args + png_path:HSV条件を適用させる画像が入ったフォルダ + out_path:HSV適用後の画像を保存するフォルダ + h_low, h_high: "□<=H<=□" の□の部分の条件 + s_low: "□<=S" の□の部分の条件 + v_low: "□<=V" の□の部分の条件 + range360degree_100percent:True ⇒ h_low, h_high, s_low, v_lowの条件で範囲をhが0-360°,sとvが0-100%とするとき + False ⇒ h_low, h_high, s_low, v_lowの条件で範囲を0-255とするとき(cv2.cvtColorで引数がcv2.COLOR_BGR2HSV_FULL) + opening_noise_removing:True ⇒ HSV条件適用後にオープニング処理によるノイズ除去をする + opening_kernel:opening_noise_removingがTrueのときのみ使用。オープニング処理のカーネルサイズ + height, width:入力画像サイズ + stat_area:これ未満の領域の面積は削除される + source_save:True ⇒ HSV条件に当てはまるときその元画像を保存 + r_display, g_display, b_display:HSV条件に当てはまる部分を何色にするか + ''' + pngpath_name = glob.glob(f'{png_path}/*.png') + pngpath_name_only = [os.path.splitext(os.path.basename(p))[0] for p in pngpath_name] + outpath_only = os.path.splitext(os.path.basename(png_path))[0] + if opening_noise_removing: + if range360degree_100percent: + outpath_save = os.path.join(out_path, png_path, f'{h_low}h{h_high}_{s_low}s_{v_low}v_360degree100percent_opening_kernel{opening_kernel}') + else: + outpath_save = os.path.join(out_path, png_path, f'{h_low}h{h_high}_{s_low}s_{v_low}v_opening_kernel{opening_kernel}') + else: + if range360degree_100percent: + outpath_save = os.path.join(out_path, png_path, f'{h_low}h{h_high}_{s_low}s_{v_low}v_360degree100percent') + else: + outpath_save = os.path.join(out_path, png_path, f'{h_low}h{h_high}_{s_low}s_{v_low}v') + os.makedirs(outpath_save, exist_ok=True) + if source_save: + os.makedirs(os.path.join(outpath_save, f'source'), exist_ok=True) + if range360degree_100percent:#Hが0-360°でSとVが0-100%の範囲を0-255にする + print(f'({h_low}≦H≦{h_high}[°], {s_low}≦S[%], {v_low}≦V[%])pixels, each areas<{stat_area}') + h_low = 255*h_low/360 + h_high = 255*h_high/360 + s_low = 255*s_low/100 + v_low = 255*v_low/100 + else: + print(f'({360*h_low/255}≦H≦{360*h_high/255}[°], {100*s_low/255}≦S[%], {100*v_low/255}≦V[%])pixels, each areas<{stat_area}') + start_ = time.time() + for i in range(0,len(pngpath_name)): + # 出血判定したい画像の読み込み + img = cv2.imread(pngpath_name[i]) + for_red_area = copy.deepcopy(img) + red_area_px, red_area = jugde_bleeding_hsv(for_red_area, h_low=h_low, h_high=h_high, s_low=s_low, v_low=v_low, opening_noise_removing=opening_noise_removing, opening_kernel=opening_kernel, height=height, width=width) + retval, labels, stats, _ = cv2.connectedComponentsWithStats(red_area)#ラベル数、ラベリング結果、各ラベルの構造情報(左上の x 座標, 左上の y 座標, 幅, 高さ, 面積)、重心 + + if red_area_px>=stat_area:#なくてもいいが処理の回数を減らし実行時間が少し早くなる(特にopeningなしだと) + count_small_area_num = 0 #閾値未満の領域の個数 + for k, row in enumerate(stats): + ##一画像内の領域の個数とその情報 + #print(f"label {i}")#i番目の領域(0番目は画像全体) + #print(f"* topleft: ({row[cv2.CC_STAT_LEFT]}, {row[cv2.CC_STAT_TOP]})")#i番目の領域の座標 + #print(f"* size: ({row[cv2.CC_STAT_WIDTH]}, {row[cv2.CC_STAT_HEIGHT]})")#i番目の領域の幅と高さ + #print(f"* area: {row[cv2.CC_STAT_AREA]}")#i番目の領域の面積 + if (row[cv2.CC_STAT_AREA]<stat_area) & (k!=0):#領域ごと閾値未満で黒塗 + count_small_area_num += 1 + red_area = np.where(labels[:] == k, 0, red_area) + count_area_num = (retval - 1) - count_small_area_num #領域数/1枚 + if count_area_num>0:#領域の個数が1個以上の場合に画像を保存 + img_res = copy.deepcopy(img) + img_res[:,:,1] = np.where(red_area!=0, g_display, img_res[:,:,1]) + img_res[:,:,0] = np.where(red_area!=0, b_display, img_res[:,:,0]) + img_res[:,:,2] = np.where(red_area!=0, r_display, img_res[:,:,2]) + if source_save: + cv2.imwrite(f'{outpath_save}/source/{pngpath_name_only[i]}.png', img)#元画像 + cv2.imwrite(f'{outpath_save}/{pngpath_name_only[i]}.png', img_res)##色条件⇒(オープニング)⇒領域ごとに閾値未満を消した画像 + print(f'実行終了、色の条件による削減画像保存先:{outpath_save}\n\n所要時間:\n{time.time() - start_}s') +if __name__ == '__main__': + simplemain(png_path='data_all_red/angio_bleeding', out_path='', h_low=0, h_high=21, s_low=80, v_low=22, range360degree_100percent=True, opening_noise_removing=True, opening_kernel=5, height=512, width=512, stat_area=200, source_save=True, r_display=0, g_display=255, b_display=255) + #引数 + #png_path:HSV条件を適用させる画像が入ったフォルダ + #out_path:HSV適用後の画像を保存するフォルダ + #h_low, h_high: "□<=H<=□" の□の部分の条件 + #s_low: "□<=S" の□の部分の条件 + #v_low: "□<=V" の□の部分の条件 + #range360degree_100percent:True ⇒ h_low, h_high, s_low, v_lowの条件で範囲をhが0-360°,sとvが0-100%とするとき + # False ⇒ h_low, h_high, s_low, v_lowの条件で範囲を0-255とするとき(cv2.cvtColorで引数がcv2.COLOR_BGR2HSV_FULL) + #opening_noise_removing:True ⇒ HSV条件適用後にオープニング処理によるノイズ除去をする + #opening_kernel:opening_noise_removingがTrueのときのみ使用。オープニング処理のカーネルサイズ + #height, width:入力画像サイズ + #stat_area:これ未満の領域の面積は削除される + #source_save:True ⇒ HSV条件に当てはまるときその元画像を保存 + #r_display, g_display, b_display:HSV条件に当てはまる部分を何色にするか \ No newline at end of file