再帰関数プログラムでオーバーフローが発生する
Pythonでカラー画像を類似色を同一領域としてラベリング(1つの領域ごとに番号を付ける)処理を行うプログラムを書いています
例えば、以下のような画像を同じような色の領域ごとに分割します(出力画像は領域の境界が分かるように疑似カラーを付けてあります)
大きなサイズの画像ではオーバーフローが起きてしまうため画像を9ブロック程に分割して1ブロックずつ処理を行いました
しかし、ブロック分割を行って処理を行ってもオーバーフローが発生してしまいます
オーバーフローを回避する方法等教えていただけたら幸いです
エラーメッセージは以下のようになっています
発生している問題・エラーメッセージ
PS C:\Users\cs17090\Saji-Lab\researchSaji\programs> py .\analyze.py label number : 53 label number : 36 label number : 26 Traceback (most recent call last): File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) [Previous line repeated 19 more times] (中略) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 141, in relabeling relabeling(j-1,i+1,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) [Previous line repeated 4 more times] File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 133, in relabeling relabeling(j+1,i-1,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 138, in relabeling relabeling(j+1,i,pix) [Previous line repeated 32 more times] File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 130, in relabeling if (approximation(pix,_la[j,i-1])&(_dm[j,i-1]==0)): File "C:\Users\cs17090\Saji-Lab\researchSaji\programs\methods.py", line 84, in approximation if ((d1<dv)&(d2<dv)&(d3<dv)): MemoryError: Stack overflow
該当のソースコード
analyze.py
1import cv2 2import numpy as np 3import matplotlib.pyplot as plt 4import methods 5 6 7# 入力画像読込 8# 画像サイズ(500(width) x 218(height) pix) 9img = cv2.imread('images/madslide12.jpg', cv2.IMREAD_COLOR) 10 11# オリジナル画像保存 12# import pdb; pdb.set_trace() 13org = img.copy() 14cv2.imwrite('results/original.png', org) 15 16# 画像ファイル 17# - 画像データを処理プログラムに送る 18methods.image(org,img) 19 20# PyMeanShift 21# - 第1引数:探索範囲、第2引数:探索色相、第3引数:粗さ 22methods.meanshift(12,3,200) 23 24# ヒストグラム均一化 25methods.contrast() 26 27# 類似色統合 28methods.clustering() 29 30# ブロック分割 31methods.division() 32 33# カラーラベリング 34methods.labeling()
methods.py
1import cv2 2import matplotlib.pyplot as plt 3import matplotlib as mpl 4import numpy as np 5import pymeanshift as pms 6import os 7import sys 8from PIL import Image 9# sys.setrecursionlimit(8000) # 200 x 113 pix 10sys.setrecursionlimit(30000) # 500 x 281 pix 11plt.gray() 12 13 14def image(_org,_img): 15 global org,img,h,w,c 16 global bo,go,ro,al 17 18 org,img = _org,_img 19 h,w,c = img.shape 20 bo,go,ro = cv2.split(org) 21 al = 0.55 22 23def meanshift(spatial_radius,range_radius,min_density): 24 global img 25 (img,labels,num) = pms.segment(cv2.cvtColor(img,cv2.COLOR_BGR2Lab),spatial_radius,range_radius,min_density) 26 img = cv2.cvtColor(img, cv2.COLOR_Lab2BGR) 27 cv2.imwrite('results/meanshift.png',img) 28 29def contrast(): 30 global img 31 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) 32 h,s,v = cv2.split(hsv) 33 34 clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(3, 3)) 35 result = clahe.apply(v) 36 37 hsv = cv2.merge((h,s,result)) 38 img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) 39 cv2.imwrite("results/contrast.png", img) 40 41def division(): 42 global block 43 hs,ws,cnt = 113,200,1 44 45 if ((h>hs)&(w>ws)): 46 for j in range(0,h,hs): 47 for i in range(0,w,ws): 48 if (((j+hs)<h)&((i+ws)<w)): 49 div = np.zeros((hs,ws,c),dtype=int) 50 div[0:hs,0:ws] = img[j:j+hs,i:i+ws] 51 else: 52 if (((i+ws)>w)&((j+hs)>h)): 53 div = np.zeros((h-j,w-i,c),dtype=int) 54 div[0:h-j,0:w-i] = img[j:h,i:w] 55 elif ((j+hs)>h): 56 div = np.zeros((h-j,ws,c),dtype=int) 57 div[0:h-j,0:ws] = img[j:h,i:i+ws] 58 else: 59 div = np.zeros((hs,w-i,c),dtype=int) 60 div[0:hs,0:w-i] = img[j:j+hs,i:w] 61 cv2.imwrite('results/division/division{}.png'.format(cnt),div) 62 cnt += 1 63 block = cnt 64 print('block number :',block) 65 66def clustering(): 67 global img 68 im = Image.open('results/contrast.png') 69 im_q = im.quantize(colors=128, method=0, dither=1) 70 im_q.save('results/clustering.png') 71 img = cv2.imread('results/clustering.png', cv2.IMREAD_COLOR) 72 73def approximation(pix1,pix2): 74 dif = abs(pix1.astype(np.int8)-pix2.astype(np.int8)) 75 d1,d2,d3 = dif[0],dif[1],dif[2] 76 dv = 10 77 if ((d1<dv)&(d2<dv)&(d3<dv)): 78 return True 79 else: 80 return False 81 82def relabeling(j,i,pix): 83 # 同色領域にラベル付与 84 if ((j>=1)&(i>=1)&(j<_la.shape[0]-1)&(i<_la.shape[1]-1)): 85 _dm[j,i] = label 86 la[j-1,i-1] = label*5,label*10,label*30 87 88 # 8近傍 89 if (approximation(pix,_la[j-1,i-1])&(_dm[j-1,i-1]==0)): 90 relabeling(j-1,i-1,pix) 91 if (approximation(pix,_la[j,i-1])&(_dm[j,i-1]==0)): 92 relabeling(j,i-1,pix) 93 if (approximation(pix,_la[j+1,i-1])&(_dm[j+1,i-1]==0)): 94 relabeling(j+1,i-1,pix) 95 96 if (approximation(pix,_la[j-1,i])&(_dm[j-1,i]==0)): 97 relabeling(j-1,i,pix) 98 if (approximation(pix,_la[j+1,i])&(_dm[j+1,i]==0)): 99 relabeling(j+1,i,pix) 100 101 if (approximation(pix,_la[j-1,i+1])&(_dm[j-1,i+1]==0)): 102 relabeling(j-1,i+1,pix) 103 if (approximation(pix,_la[j,i+1])&(_dm[j,i+1]==0)): 104 relabeling(j,i+1,pix) 105 if (approximation(pix,_la[j+1,i+1])&(_dm[j+1,i+1]==0)): 106 relabeling(j+1,i+1,pix) 107 108def _labeling(div): 109 global _dm,dm,_la,la,label 110 dh,dw = div.shape[0],div.shape[1] 111 _dm,_la,la = np.zeros((dh+2,dw+2),dtype=int),np.zeros((dh+2,dw+2,c),dtype=int),np.zeros((dh,dw,c),dtype=int) 112 113 _la[1:dh+1,1:dw+1] = div 114 label = 1 115 116 for j in range(1,dh+1): 117 for i in range(1,dw+1): 118 # ダミー配列にラベル付けされている画素ならば処理を行わない 119 if (_dm[j,i]==0): 120 # 注目画素値取得 121 pix = div[j-1,i-1] 122 # ラベリング 123 relabeling(j,i,pix) 124 # ラベル更新 125 label += 1 126 127 print('label number :',label) 128 129 dm = np.zeros((dh,dw,c),dtype=int) 130 dm = _dm[1:dh+1,1:dw+1] 131 132 la = la.astype(np.uint8) 133 134 return dm,la 135 136def labeling(): 137 global label 138 label = 1 139 dir = 'results/division' 140 n = (sum(os.path.isfile(os.path.join(dir,name)) for name in os.listdir(dir))) 141 142 for i in range(4,n+1): 143 div = cv2.imread('results/division/division{}.png'.format(i),cv2.IMREAD_COLOR) 144 # dh,dw = div.shape[0],div.shape[1] 145 # d,l = np.zeros((dh,dw),dtype=int),np.zeros((dh,dw,c),dtype=int) 146 d,l = _labeling(div) 147 np.savetxt('results/dummy/dummy{}.txt'.format(i),d,fmt='%d') 148 cv2.imwrite('results/dummy/dummy{}.png'.format(i),d) 149 cv2.imwrite('results/labeling/labeling{}.png'.format(i),l)
試したこと
再帰処理を減らす、関数の引数を減らす、無駄な処理を減らす等負荷が軽くなるようなことを中心に行いましたが、途中でオーバーフローしてしまいました
回答1件
あなたの回答
tips
プレビュー