题目要求
![image-20230410192801138](http://hhq-notion.oss-cn-hangzhou.aliyuncs.com/img/image-20230410192801138.png)
提供了上图所示胸部CT图像,实现:提取两个肺部区域,如由下图所示。
![image-20230410192825834](http://hhq-notion.oss-cn-hangzhou.aliyuncs.com/img/image-20230410192825834.png)
说明:不能使用区域增长算法!
环境
- python 3.8
- openCV 4.2.0
实验步骤
-
读取图片
-
二值化
测试了 lab04的四个分割方法,选取 yen分割,yen的代码也是lab04中实现的
-
图像反转
-
获取联通分量的信息
我们想要保留的肺部区域为 label 97和130 -
保留目标区域的联通分量
-
形态学处理去除孔洞
源代码
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
from skimage import measure
# 测试了 lab04的四个分割方法,选取 yen分割
def yen(src):
H, W = src.shape
hist, bins = np.histogram(src.ravel(), 256, [0, 256])
total_pixels = H*W
p = hist / total_pixels
w = np.cumsum(p)
mu = np.cumsum(p * np.arange(0, 256))
mu_t = mu[-1]
sigma_b_squared = (mu_t * w - mu) ** 2 / (w * (1 - w))
sigma_b_squared[~np.isfinite(sigma_b_squared)] = 0
sigma_b_squared_max = sigma_b_squared.max()
T = np.where(sigma_b_squared == sigma_b_squared_max)[0][0]
dst = src.copy()
for i in range(H):
for j in range(W):
if src[i, j] < T:
dst[i, j] = 0
else:
dst[i, j] = 1
return dst
# 读取图片
org_img = cv.imread('chest.PNG', cv.IMREAD_GRAYSCALE)
# 二值化
yen_img = yen(org_img)
# 图像反转
gr_img = np.array(255-yen_img)
# 连通分量标记
rst_labels, num_labels = measure.label(gr_img, connectivity=2, return_num=True)
# 连通分量属性提取
props = measure.regionprops(rst_labels)
# 对连通分量按面积大小进行排序
props_sorted = sorted(props, key=lambda x: x.area, reverse=True)
# 构建全黑图像
mask = np.zeros_like(gr_img)
# 保留面积第3、4的连通分量
for prop in props_sorted[2:4]:
# 将该连通分量在遮罩上标出
mask[rst_labels == prop.label] = 255
# 形态学处理去除孔洞
# 定义结构元素,十字形
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (30, 30))
# 进行闭操作
closed_img = cv.morphologyEx(mask, cv.MORPH_CLOSE, kernel)
plt.imshow(closed_img, cmap='gray'), plt.axis('off')
plt.show()