局部直方图 算法优化
这是我在写数字图像处理第三章中局部直方图优化的一些体会,最大的体会就是优化计算方法可以极大地加快运算速度
1、优化前
源代码
这是根据数字图像处理p75的公式写的
#例3.10 #局部直方图均衡 import cv2 import numpy as np import self_def img = cv2.imread("1.tif",0) #1截取图像,调试时减小计算时间 cut_m,cut_n = 300,300 #截取的行数和列数 img_cut = np.zeros((cut_m,cut_n)) img_cut = img_cut.astype(np.uint8) img_cut = img[0:cut_m,0:cut_n] L = np.max(img_cut)+1 #计算灰度范围 rk = np.arange(L) m,n = np.shape(img_cut) #填充 img_fill = np.zeros((m+2,n+2),dtype=int) img_fill[1:m+1,1:n+1] = img_cut #注意,应该写道m+1 #int_img_fill = img_fill.astype(np.uint8) img_trans = np.zeros((m,n),dtype=int) for i in range(m): for j in range(n): img_temp = np.zeros((3,3),dtype=int) img_temp[:,:] = img_fill[i:i+3,j:j+3] L_max = np.max(img_temp) + 1 # 计算灰度范围 L_min = np.min(img_temp) rk = np.arange(L_max) m_, n_ = np.shape(img_temp) # 统计每个灰度级的个数 nk = np.zeros(L_max) for i_ in range(m_): for j_ in range(n_): nk[img_temp[i_, j_]] += 1 pk = nk / (m_ * n_) # 3.3-7 sk = np.zeros(L_max) # 计算变换后的灰度 for i_ in np.arange(L_min,L_max): # 3.3-8 for j_ in range(i_+1): #注意加一!!!! sk[i_] += (L_max - 1) * pk[j_] img_trans[i,j] = sk[img_cut[i,j]] print("end") #用于调试 cv2.imshow("img",img_cut) cv2.imshow("img_fill",img_trans.astype(np.uint8)) cv2.waitKey(0) cv2.destroyAllWindows()
结果
我为了节省时间,只选取了一部分进行处理,尽管这样,仍然花费了大约五分钟
这么慢令我十分不爽,仔细研究发现,在邻域中只有九个灰度,计算时也只需要计算这九个灰度即可,而在我设计的算法中,把[0,L-1]范围内所有的灰度都计算了,这样就增加了很多的计算量,于是进行优化
2、优化后
源代码
#例3.10 #局部直方图均衡 import cv2 import numpy as np import self_def img = cv2.imread("1.tif",0) m,n = np.shape(img) '''2改进算法后,没必要截取图像 #1截取图像 cut_m,cut_n = 150,150 #截取的行数和列数 img_cut = np.zeros((cut_m,cut_n)) img_cut = img_cut.astype(np.uint8) img_cut = img[0:cut_m,0:cut_n]''' m,n = np.shape(img) #填充 img_fill = np.zeros((m+2,n+2),dtype=int) img_fill[1:m+1,1:n+1] = img #注意,应该写道m+1 #int_img_fill = img_fill.astype(np.uint8) img_trans = np.zeros((m,n),dtype=int) for i in range(m): for j in range(n): temp = np.zeros((3,3),dtype=int) temp[:, :] = img_fill[i:i + 3, j:j + 3] huidu_temp = temp.reshape(1,9) rk = np.sort(huidu_temp) #huidu_temp_number = np.zeros(9,dtype=int) rk_unique = np.unique(rk) nk = [] for i_ in rk_unique: nk.append(np.sum(rk == i_)) #有问题 sk = [] kind_number = np.size(rk_unique) for i_ in range(kind_number): sum_ = 0 for j_ in range(i_+1): #注意这个加一 sum_ += rk_unique[-1]*nk[j_]/9 sk.append(int(sum_)) if rk_unique[i_]==img[i,j]: #顺便也求出邻域中心的灰度的位置 temp = i_ img_trans[i, j] = sk[temp] print("end") #用于调试 cv2.imshow("img",img) cv2.imshow("img_cut",img_trans.astype(np.uint8)) cv2.waitKey(0) cv2.destroyAllWindows()
结果
这次运算只花了约8s的时间,可见优化计算方法的重要性
遗憾的是,我将邻域由3,扩展到5,再扩展到9,都没有实现图3.26的结果