Diff of /hsv_remove.py [000000] .. [76022b]

Switch to side-by-side view

--- 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