import traceback import numpy as np import cv2 as cv from matplotlib import pyplot as plt def get_binary_img_(img): gray_img = img if len(img.shape) > 2: gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY) binary_img = cv.Canny(gray_img, 80, 150) return binary_img def get_morp_dilate_(binary_img): kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3)) # morp_dilate = cv.morphologyEx(binaryImg, cv.MORPH_DILATE, kernel=(1, 3), iterations=3) # morp_dilate = cv.morphologyEx(morp_dilate, cv.MORPH_DILATE, kernel=(3, 1), iterations=3) # morp_dilate = cv.morphologyEx(binaryImg, cv.MORPH_DILATE, kernel=(11, 11), iterations=3) morp_dilate = cv.morphologyEx(binary_img, cv.MORPH_DILATE, kernel=kernel, iterations=3) return morp_dilate def get_water_img_(img, morp_dilate): # 寻找图像轮廓 返回修改后的 图像的轮廓 以及它们的层次 # contours, hierarchy = cv.findContours(gray_img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_NONE) # contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) contours, hierarchy = cv.findContours(morp_dilate, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) # 32位有符号整数类型, marks = np.zeros(morp_dilate.shape[:2], np.int32) # 绘制每一个轮廓 for index in range(len(contours)): # 对marks进行标记,对不同区域的轮廓使用不同的亮度绘制,相当于设置注水点,有多少个轮廓,就有多少个轮廓 # 图像上不同线条的灰度值是不同的,底部略暗,越往上灰度越高 marks = cv.drawContours(marks, contours, index, (index, index, index), 1, 8, hierarchy) # 使用分水岭算法 # 经过watershed函数的处理,不同区域间的值被置为-1(边界)没有标记清楚的区域被置为0,其他每个区域的值保持不变:1,2,...,contours.size() marks_water = cv.watershed(img, marks) return marks_water def get_mask_img_(morp_dilate, file_dir): contours, hierarchy = cv.findContours(morp_dilate, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) # 32位有符号整数类型, marks = np.zeros(morp_dilate.shape[:2], np.int32) for index in range(len(contours)): dist = cv.pointPolygonTest(contours[index], (marks.shape[0] // 2, marks.shape[1] // 2), True) if dist >= 0: marks = cv.drawContours(marks, contours, contourIdx=index, color=1, thickness=1, lineType=8, hierarchy=hierarchy) edges = np.zeros((marks.shape[0] + 2, marks.shape[1] + 2), np.uint8) # 掩码,长短需要加2个像素 try: cv.floodFill(marks, edges, (marks.shape[0] // 2, marks.shape[1] // 2), 1, cv.FLOODFILL_MASK_ONLY) # 漫水填充 except Exception as e: if file_dir: print(file_dir) print(e) print("=================") print(traceback.format_exc()) # raise e marks = np.ones(morp_dilate.shape[:2], np.int32) return marks def get_binary_img(binary_img, mask): masked_binary_img = cv.bitwise_and(binary_img, binary_img, mask=mask.astype('uint8')) return masked_binary_img def get_water_img(img, morp_dilate, mask): water_img = get_water_img_(img, morp_dilate) masked_water = cv.bitwise_and(water_img, water_img, mask=mask.astype('uint8')) return masked_water def get_more_dim(img, file_dir, source_img=None): if source_img is None: source_img = img # img: ndarray: 852, 847, 3 binary_img = get_binary_img_(img) morp_dilate = get_morp_dilate_(binary_img) mask = get_mask_img_(morp_dilate, file_dir) masked_binary_img = get_binary_img(binary_img, mask) masked_water = get_water_img(source_img, morp_dilate, mask) # print(f"masked_binary_img shape:{masked_binary_img.shape} masked_water shape:{masked_water.shape}") # print(f"type(masked_binary_img):{type(masked_binary_img)} type(masked_water):{type(masked_water)}") # return np.stack((masked_binary_img, mask), axis=0) return masked_binary_img, masked_water