如何通过图像处理分割木质瓷砖区域?已尝试多算法未果求建议
木质瓷砖区域分割可行方案
针对白色/灰色木质瓷砖与纸板的分割需求,结合你尝试过的方法未达预期的情况,以下是几种针对性的解决方案:
一、基于颜色空间的精准分割
瓷砖与纸板的颜色差异在HSV空间中更易区分,可针对不同色调瓷砖调整范围:
白色瓷砖分割
import cv2 import numpy as np # 读取图像并转HSV空间 img = cv2.imread("white_tiles.jpg") hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义白色HSV范围(可根据实际图像微调) lower_white = np.array([0, 0, 200]) upper_white = np.array([180, 30, 255]) # 生成掩码并优化 mask = cv2.inRange(hsv_img, lower_white, upper_white) kernel = np.ones((5,5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 填充内部孔洞 mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) # 去除噪声点 # 提取瓷砖区域 result = cv2.bitwise_and(img, img, mask=mask)
灰色瓷砖分割
img = cv2.imread("grey_tiles.jpg") hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 定义灰色HSV范围 lower_grey = np.array([0, 0, 80]) upper_grey = np.array([180, 30, 200]) mask = cv2.inRange(hsv_img, lower_grey, upper_grey) # 同白色瓷砖的形态学优化步骤 kernel = np.ones((5,5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) result = cv2.bitwise_and(img, img, mask=mask)
二、基于纹理特征的分割
瓷砖与纸板的纹理差异明显,可通过LBP(局部二值模式)提取纹理特征后分割:
def compute_lbp(img): gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) lbp = np.zeros_like(gray) # 遍历像素计算LBP值 for i in range(1, gray.shape[0]-1): for j in range(1, gray.shape[1]-1): center = gray[i,j] code = 0 code |= (gray[i-1,j-1] > center) << 7 code |= (gray[i-1,j] > center) << 6 code |= (gray[i-1,j+1] > center) << 5 code |= (gray[i,j+1] > center) << 4 code |= (gray[i+1,j+1] > center) << 3 code |= (gray[i+1,j] > center) << 2 code |= (gray[i+1,j-1] > center) << 1 code |= (gray[i,j-1] > center) << 0 lbp[i,j] = code return lbp img = cv2.imread("tiles.jpg") lbp_map = compute_lbp(img) # 直方图均衡化增强纹理差异 lbp_eq = cv2.equalizeHist(lbp_map) # Otsu阈值二值化 _, mask = cv2.threshold(lbp_eq, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 形态学优化 mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, np.ones((3,3), np.uint8)) result = cv2.bitwise_and(img, img, mask=mask)
三、改进的分水岭算法
之前的分水岭效果差大概率是预处理不到位,正确流程如下:
img = cv2.imread("tiles.jpg") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 1. 边缘检测+膨胀确定背景区域 edges = cv2.Canny(gray, 50, 150) dilated_bg = cv2.dilate(edges, np.ones((3,3), np.uint8), iterations=2) # 2. 距离变换提取前景种子 dist_transform = cv2.distanceTransform(dilated_bg, cv2.DIST_L2, 5) _, foreground = cv2.threshold(dist_transform, 0.3*dist_transform.max(), 255, 0) foreground = np.uint8(foreground) # 3. 标记未知区域 unknown = cv2.subtract(dilated_bg, foreground) # 4. 连通区域标记+分水岭分割 _, markers = cv2.connectedComponents(foreground) markers += 1 # 背景标记为1,前景从2开始 markers[unknown == 255] = 0 # 未知区域标记为0 markers = cv2.watershed(img, markers) # 生成瓷砖掩码 mask = np.zeros_like(gray) mask[markers > 1] = 255 result = cv2.bitwise_and(img, img, mask=mask)
四、机器学习辅助分割(复杂场景适用)
如果上述方法仍不理想,可采用SVM像素级分类:
- 手动标注少量瓷砖和纸板的样本区域,提取每个像素的HSV值、LBP特征作为特征向量;
- 用标注数据训练SVM分类器;
- 遍历图像每个像素,用分类器预测类别,生成分割掩码。
内容的提问来源于stack exchange,提问作者Gintare
相关产品推荐
相关产品推荐

