Python | 您所在的位置:网站首页 › python中递归算法 › Python |
Python——基于局部自适应二值化(递归法)的裂缝图像分割
Python------基于局部自适应二值化(递归法)的裂缝图像分割一、局部自适应二值化二、递归法局部自适应二值化介绍三、Python实现1、将图像划分为若干个窗口2、预先确定阈值T3、确定各个窗口的最佳阈值4、利用OpenCV中的threshold函数实现二值化5、图像重构输出
四、测试五、完整代码六、不足
Python------基于局部自适应二值化(递归法)的裂缝图像分割
一、局部自适应二值化
可以参考这几篇文章: 图像的自适应二值化OpenCV全局/局部阀值二值化OpenCV_基于局部自适应阈值的图像二值化 二、递归法局部自适应二值化介绍
Step 1:确定窗口大小
Step 2:将图像中每个窗口的值单独取出,放入windows二维矩阵 注:此是输入的图像的灰度图像,每一幅图像都是由不同的灰度值像素点构成,划分窗口是概念上的理解,真正计算的还是数值。 示例图片:(宿舍采的裂缝) 在做数值处理的时候,划分窗口就好比怎么把两个相同面积但长宽不同的长方体相互转换。好比: 到此,递归法局部自适应二值化就完成啦!看一下效果。 四、测试我们用上述裂缝图像,先用OpenCV自带的函数看一下效果。 代码: #coding = utf-8 import cv2 as cv import numpy as np import math from skimage import morphology from skimage import img_as_float from skimage import img_as_ubyte import matplotlib.pyplot as plt image = cv.imread("C:\\Users\\LENOVO\\Desktop\\004.png") #你的图片路径 # 图像灰度化 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) #加权平均法 Gray(i,j) = 0.299R(i,j) + 0.578G(i,j) + 0.114B(i,j) 可尝试其他方法,但目前此方法最优 cv.imshow('show', gray) ret,th1 = cv.threshold(gray,70,255,cv.THRESH_BINARY) #全局二值化 # 3为Block size, 5为param1值 th2 = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,5) #adaptive_thresh_mean局部二值化 th3 = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,5) #adaptive_thresh_gaussian局部二值化 titles = ['Gray Image', 'Global Thresholding (v = 70)', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] images = [gray, th1, th2, th3] print(ret) for i in range(4): plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show() while True: key = cv.waitKey(10) if key == 27: cv.destroyAllWindows() #按Esc键退出效果: 看一下本文中的方法的结果: 在阈值那里,把最终得到的最佳阈值都减去5(5应该是经验值),效果8错。 代码的前面部分是图像预处理。 #coding=utf-8 import cv2 as cv import numpy as np import math from skimage import morphology from skimage import img_as_float from skimage import img_as_ubyte import matplotlib.pyplot as plt #1、加载图片 image = cv.imread("C:\\Users\\LENOVO\\Desktop\\004.png") #你的图片路径 (h, w, d) = image.shape print("width={}, height={}, depth={}".format(w, h, d)) # 2、图像灰度化 gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY) #加权平均法 Gray(i,j) = 0.299R(i,j) + 0.578G(i,j) + 0.114B(i,j) 可尝试其他方法,但目前此方法最优 cv.imshow('show', gray) #3、中值滤波 (论文中用的是中值滤波,但我采的图片没有很多椒盐噪声,所以换为高斯滤波器,名字懒得改了-v-) median = cv.GaussianBlur(gray, (3, 3), 0) #sigmaX = 0时,标准差大小由高斯核大小自动确定 cv.imshow('Gaus', median) (mh, mw) = median.shape # median = cv.medianBlur(gray,5) #sigmaX = 0时,标准差大小由高斯核大小自动确定 # cv.imshow('Median', median) # (mh, mw) = median.shape print("medianwidth={}, medianheight={}".format(mw, mh)) #4、局部自适应二值化(递归法) (gh, gw) = gray.shape print("graywidth={}, grayheight={}".format(gw, gh)) # for i in range(gh): # for j in range(gw): # print(gray[i][j]) #--------划分窗口--------- #窗口大小 window_w = 11 window_h = 11 window_size = window_w * window_h window_w_num = math.floor(mw/window_w) window_h_num = math.floor(mh/window_h) print(window_w_num,window_h_num) #窗口总数 window_num = window_w_num * window_h_num print(window_num) windows = [] #print(windows,windows.shape) for m in range(window_h_num): for k in range(window_w_num): for i in range(window_h): for j in range(window_w): windows.append(median[i+window_h*m][j+window_w*k]) arr_windows = np.array(windows) print(arr_windows.shape) reshape_arr = arr_windows.reshape(window_num,window_size) print(reshape_arr.shape) F_max = np.amax(reshape_arr, axis=1) print(reshape_arr[0,:]) #print(F_max[0],F_max.shape) #713 F_min = np.min(reshape_arr, axis=1) print(F_min[0]) #-----------确定各个窗口的最佳阈值----------- Ts = np.zeros(window_num) for i in range(window_num): Ts[i] = round((int(F_max[i]) + int(F_min[i])) / 2) T_uint = np.array(Ts,dtype='uint8') print(T_uint.shape,T_uint.dtype,F_max.dtype) # temp = np.zeros(window_size,dtype='uint8') #print(reshape_arr.shape,temp.shape) # ground = np.empty(window_size,dtype='uint8') # crack = np.empty(window_size,dtype='uint8') ground = [] crack = [] for i in range(window_num): T = 0 temp = reshape_arr[i,:] temp = np.array(temp,dtype='uint8') T1 = T_uint[i] #一般T都不会是零 #print(T1) while T1 != T : T = T1 for j in range(window_size): if temp[j]>= T1: ground.append(temp[j]) else: crack.append(temp[j]) R1 = int(np.mean(crack)) R2 = int(np.mean(ground)) T1 = int((R1 + R2) / 2) #print(T,T1) T_uint[i] = T1 - 5 print(T_uint.shape,T_uint.dtype) #713个窗口 #---------局部自适应二值化----------- binary_gray = np.zeros((window_num,window_size),dtype='uint8') for i in range(window_num): temp = reshape_arr[i, :] temp = np.array(temp, dtype='uint8') #temp_reshape = np.reshape(temp,(window_h,window_w)) ret, th = cv.threshold(temp, T_uint[i], 255, cv.THRESH_BINARY) thresh = np.array(th, dtype='uint8') thresh = np.squeeze(thresh) binary_gray[i, :] = thresh print(binary_gray.shape,thresh.shape) #---------图像重构输出显示------------- binary_gray = np.reshape(binary_gray,window_num*window_size) print(binary_gray.shape) c = 0 gray_binary = np.zeros((window_h_num*window_h,window_w_num*window_w),dtype='uint8') for m in range(window_h_num): for k in range(window_w_num): for i in range(window_h): for j in range(window_w): gray_binary[i+window_h*m][j+window_w*k] = binary_gray[c] c = c + 1 print(c) cv.imshow('binary_gray',gray_binary) plt.imsave('C:\\Users\\LENOVO\\Desktop\\binary_gray.png',gray_binary) while True: key = cv.waitKey(10) if key == 27: cv.destroyAllWindows() #按Esc键退出 六、不足1、算法时间较长,比如上面那张图987x742,需要跑大概十几分钟,OpenCV自带的函数就几秒钟 2、特定场景表现得较好,有些场景表现不好 例如下面这张图: *** 第一次写博客,记录更容易成长。知道自己很菜,但慢慢来。若有错误之处,欢迎指正交流。*** |
CopyRight 2018-2019 实验室设备网 版权所有 |