first commit

This commit is contained in:
admin
2026-05-20 15:05:35 +08:00
commit ac09b26253
2048 changed files with 189478 additions and 0 deletions

View File

@@ -0,0 +1,185 @@
import cv2
import random
import numpy as np
from scipy.ndimage import label, distance_transform_edt
########################### 1. 超参数 ###########################
Annotate_CLASSES = ('背景','术中超声','吻合器','乳胶管','推结器','肝带','钳夹','超声刀','脂肪','双极电凝','棉球','血管阻断夹','肿瘤','','线','韧带','胆囊静脉','肝脏','胆囊','分离钳','止血海绵','肝总管','胆总管','吸引器','剪刀','止血纱布','生物夹','无损伤钳','喷洒','胆囊管','胆囊动脉','电凝','标本袋','引流管','纱布','金属钛夹') # 待分类的类
Annotate_PALETTE = [[0,0,0],[138,251,213],[136,162,196],[197,83,181],[202,202,200],[113,102,140],[66,115,82],[240,16,116],[155,132,0],[155,62,0],[146,175,236],[255,172,159],[245,161,0],[134,124,118], [0,157,142], [181,85,105], [42,8,66], [255,91,0],[255,234,0],[85, 107, 179],[181, 227, 14],[72, 0, 255],[0, 155, 33],[255,0,255],[29, 32, 136],[160, 15, 95],[0,160,233],[52,184,178],[90,120,41],[255,0,0],[177,0,0],[167,24,233],[112,113,150],[0,255,0],[255,255,255],[0,255,255]]
def skeletonize(image):
"""骨架化函数确保线条连通性并缩减为1像素宽"""
skeleton = np.zeros_like(image)
temp_image = np.copy(image)
while True:
eroded = cv2.erode(temp_image, None) # 腐蚀操作
temp_dilate = cv2.dilate(eroded, None) # 膨胀操作
temp = cv2.subtract(temp_image, temp_dilate) # 提取边缘
skeleton = cv2.bitwise_or(skeleton, temp) # 将边缘加入骨架
temp_image = np.copy(eroded)
if cv2.countNonZero(temp_image) == 0:
break
return skeleton
# 1. *** 边缘检测并膨胀 ***
def edge_detection(image):
"""对图像的各个通道进行边缘检测并进行膨胀处理"""
b_channel, g_channel, r_channel = cv2.split(image)
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
edges_b = cv2.Canny(b_channel, 100, 200)
edges_g = cv2.Canny(g_channel, 100, 200)
edges_r = cv2.Canny(r_channel, 100, 200)
edges_gray = cv2.Canny(gray_image, 100, 200)
# 合并所有边缘检测结果
edges = cv2.bitwise_or(edges_b, edges_g)
edges = cv2.bitwise_or(edges, edges_r)
edges = cv2.bitwise_or(edges, edges_gray)
# 创建膨胀核并进行膨胀操作
kernel = np.ones((3, 3), np.uint8)
dilated_image = cv2.dilate(edges, kernel, iterations=1)
return dilated_image
# 2. ** 检测连通区域 ***
def detect_connected_regions(dilated_image):
"""检测图像中的连通区域并过滤掉小区域"""
_, binary = cv2.threshold(dilated_image, 1, 255, cv2.THRESH_BINARY_INV)
binary[binary > 0] = 1 # 转换为二值图像
# 标记连通区域
structure = np.ones((3, 3), dtype=int)
labeled_array, num_features = label(binary, structure=structure)
# 清除掉小于100像素的区域
filtered_labeled_array = np.copy(labeled_array)
for label_num in range(1, num_features + 1):
area = np.sum(labeled_array == label_num)
if area < 100:
filtered_labeled_array[filtered_labeled_array == label_num] = 0
# 重新标记过滤后的连通区域
filtered_labeled_array, num_features = label(filtered_labeled_array, structure=structure)
return filtered_labeled_array, num_features # 返回过滤后的labeled_array和未过滤的labeled_array用于寻找颜色
# 3. *** 分水岭填充白色区域 ***
def fill_white_regions(filtered_labeled_array):
"""使用分水岭算法填充白色区域"""
# 准备三通道图像作为分水岭算法的输入
color_image = np.zeros((filtered_labeled_array.shape[0], filtered_labeled_array.shape[1], 3), dtype=np.uint8)
# 将过滤后的 labeled_array 转化为 32 位整型,作为分水岭的 markers
markers = np.copy(filtered_labeled_array).astype(np.int32)
markers[markers == 0] = -1 # 背景标记为 -1
# 执行分水岭算法
cv2.watershed(color_image, markers)
# 更新分水岭结果
filled_labeled_array = markers.astype(int)
filled_labeled_array[filled_labeled_array == -1] = 0
# 使用距离变换计算边缘像素0最近的非零值
non_zero_mask = filled_labeled_array != 0
distance, nearest_indices = distance_transform_edt(non_zero_mask == 0, return_indices=True)
nearest_values = filled_labeled_array[tuple(nearest_indices)]
filled_labeled_array[filled_labeled_array == 0] = nearest_values[filled_labeled_array == 0]
return filled_labeled_array
# 4. *** 对连通区域上色(使用“filtered_labeled_array”作为颜色判断给“filled_labeled_array”上色) ***
def color_connected_regions(filled_labeled_array, filtered_labeled_array, ori_labeled_image, Annotate_PALETTE):
"""根据原始图像的颜色和注解调色板给连通区域上色"""
# 初始化一个三通道的彩色图像
colored_image = np.zeros((*filled_labeled_array.shape, 3), dtype=np.uint8)
# 遍历filtered_labeled_array中的每个标签
unique_labels = np.unique(filtered_labeled_array)
for label_num in unique_labels:
if label_num == 0:
continue # 跳过背景标签
# 找到filtered_labeled_array中等于当前标签的区域
mask_filtered = (filtered_labeled_array == label_num)
# 获取ori_labeled_image中对应区域的RGB值
region_rgb_values = ori_labeled_image[mask_filtered]
if len(region_rgb_values) == 0:
continue
# 计算区域的RGB平均值
average_rgb = np.mean(region_rgb_values, axis=0)
# 找到Annotate_PALETTE中与average_rgb最接近的颜色
closest_palette_color = find_closest_palette_color(average_rgb, Annotate_PALETTE)
# 将该颜色赋给filled_labeled_array对应区域的元素
mask_filled = (filled_labeled_array == label_num)
colored_image[mask_filled] = closest_palette_color
return colored_image
# 寻找最近邻颜色
def find_closest_palette_color(average_rgb, Annotate_PALETTE):
"""根据平均RGB值找到Annotate_PALETTE中最接近的颜色"""
Annotate_PALETTE = [[color[2], color[1], color[0]] for color in Annotate_PALETTE]
average_rgb = np.array(average_rgb)
min_distance = float('inf')
closest_color = None
# 遍历调色板计算每个颜色与平均RGB的欧几里得距离
for palette_color in Annotate_PALETTE:
palette_color = np.array(palette_color)
distance = np.linalg.norm(average_rgb - palette_color) # 欧几里得距离
if distance < min_distance:
min_distance = distance
closest_color = palette_color
return closest_color
# 5. 对Array区域上色4的简化版
def Tool_color_connected_array(Array):
colored_image = np.zeros((*Array.shape, 3), dtype=np.uint8)
for label_num in range(1, np.max(Array) + 1):
color = [np.random.randint(0, 254) for _ in range(3)]
colored_image[Array == label_num] = color
return colored_image
if __name__ == '__main__':
"""超参数"""
image_path = './2023_02_03_09_13_48.00_08_04_21.Still085.png'
"""主函数,处理图像并保存结果"""
# 读取图像
image = cv2.imread(image_path)
# 1. 边缘检测并膨胀
dilated_image = edge_detection(image)
cv2.imwrite('./1_1_range_image.png', dilated_image)
# 2. 检测连通区域
filtered_labeled_array, _ = detect_connected_regions(dilated_image)
colored_image_filtered = Tool_color_connected_array(filtered_labeled_array)
cv2.imwrite('./2_colored_image_filtered.png', colored_image_filtered)
# 3. 分水岭填充白色区域
filled_labeled_array = fill_white_regions(filtered_labeled_array)
colored_image_filled = Tool_color_connected_array(filled_labeled_array)
cv2.imwrite('./3_colored_image_filled.png', colored_image_filled)
# 4. 对连通区域上色
ori_labeled_image = image
colored_image_final = color_connected_regions(filled_labeled_array, filtered_labeled_array, ori_labeled_image, Annotate_PALETTE)
cv2.imwrite('./4_color_image_Final.png', colored_image_final)
print("处理后的图片已保存。")