图像开、闭、膨胀、腐蚀形态学变换-《医学图像处理》小作业七-Python代码/Matlab代码

天津中医药大学-20级医学信息工程   教师:王翌   学生:邓集亲

声明:本文章中所涉及的代码并非我个人独立完成的成果。

        在撰写的过程中,我广泛地吸取了前一辈人,尤其是学长学姐们的宝贵学习经验。通过深入研究他们的学习轨迹,以及查阅和分析了众多相关的理论文献与资料,并在王老师的悉心指导下,经过反复的实验、调试与优化,最终得以总结完成本文所展现的代码。

        建议各位学弟学妹们,先根据王老师的授课内容,独立思考一下应该如何完成。如果实在是有理解上的困难,不知道从何下手,再来学习和参考本文。

        学长我是用Python写的,如果你使用MATLAB,同样可以参考此代码进行翻译。我在代码中加入了许多注释和测试环节,以便于理解。由于学长能力有限,代码中或许存在一些疏漏或错误,请批判性地参考。

实验七:形态学变换

作业要求:

  1. 参考“形态学图像处理”课的内容,对输入图像进行开、闭、腐蚀、膨胀这四种形态学变换,并显示每种变换后的结果图像。

实验图片:

word_bw.bmp,再自选其它至少20张图片(包括灰度图片和彩色图片)。

  图像开、闭、膨胀、腐蚀是形态学图像处理中常用的操作,它们可以用于改变图像的形状、去除噪声、分离物体等。

  图像开操作是指先进行腐蚀操作,再进行膨胀操作。其原理是先对图像进行腐蚀,去除掉小区域的噪声或毛刺,然后再进行膨胀,使得物体边缘更加清晰和平滑。这样可以使得物体轮廓更加鲜明,并且去除了不必要的细节信息。

  相反,图像闭操作则是指先进行膨胀操作,再进行腐蚀操作。其原理是先对图像进行膨胀,填充物体内部的孔洞和空隙,然后再进行腐蚀,使得物体边缘更加平滑和连续。这样可以使得物体轮廓更加鲜明,并且填补了不必要的空隙。

  图像膨胀操作是指将结构元素在二值化图像上向外扩张一定距离。其原理是将结构元素与待处理图像进行卷积,如果结构元素中心与待处理图像的某个像素点重合,则将结构元素中的所有像素点都赋值给该像素点。这样可以使得物体变大,边缘更加平滑和连续。

  图像腐蚀操作则是指将结构元素在二值化图像上向内收缩一定距离。其原理是将结构元素与待处理图像进行卷积,如果结构元素中心与待处理图像的某个像素点重合,则判断该像素点周围是否都为白色(或黑色),如果不是,则将该像素点置为黑色(或白色)。这样可以使得物体变小,去除掉小区域的噪声或毛刺。

Windows图片文件目录:

ImageSet文件目录下储存其他待处理图片

Python代码:

#导入库
import cv2 as cv
import numpy as np
from matplotlib import pyplot


#开
def open_operation(image, kernel):

    erosion_img = img_erode(image, kernel)
    dilation_img = img_dilate(erosion_img, kernel)

    return dilation_img

#闭
def close_operation(image, kernel):

    dilation_img = img_dilate(image, kernel)
    erosion_img = img_erode(dilation_img, kernel)

    return erosion_img

#腐蚀
def img_erode(src, kernel, borderType=cv.BORDER_CONSTANT):
    dst = np.zeros_like(src)  #创建并初始化数组
    kernel_h, kernel_w = kernel.shape[:2]
    kernel_half_h, kernel_half_w = kernel_h // 2, kernel_w // 2
    padded_src = cv.copyMakeBorder(src, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    
    for i in range(kernel_half_h, padded_src.shape[0] - kernel_half_h):
        for j in range(kernel_half_w, padded_src.shape[1] - kernel_half_w):
            roi = padded_src[i-kernel_half_h:i+kernel_half_h+1, j-kernel_half_w:j+kernel_half_w+1]
            dst[i-kernel_half_h, j-kernel_half_w] = cv.minMaxLoc(roi, mask=kernel)[0]         #寻找最小值

    padded_src = cv.copyMakeBorder(dst, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    return dst


#膨胀
def img_dilate(src, kernel, borderType=cv.BORDER_CONSTANT):
    dst = np.zeros_like(src)  #创建并初始化数组
    kernel_h, kernel_w = kernel.shape[:2]
    kernel_half_h, kernel_half_w = kernel_h // 2, kernel_w // 2
    padded_src = cv.copyMakeBorder(src, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    
    for i in range(kernel_half_h, padded_src.shape[0] - kernel_half_h):
        for j in range(kernel_half_w, padded_src.shape[1] - kernel_half_w):
            roi = padded_src[i-kernel_half_h:i+kernel_half_h+1, j-kernel_half_w:j+kernel_half_w+1]
            dst[i-kernel_half_h, j-kernel_half_w] = cv.minMaxLoc(roi, mask=kernel)[1]         #寻找最大值

    padded_src = cv.copyMakeBorder(dst, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    return dst

#读取图像

original = cv.imread(r'D:\deng\smalljob\ImageSet\word_bw.bmp')
original_gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)   #将图像从RGB颜色空间转换到灰度颜色空间

kernel=np.ones((3,3),np.uint8)          #卷积核

img_1=img_erode(original_gray,kernel)
img_2=img_dilate(original_gray,kernel)
img_3=open_operation(original_gray,kernel)
img_4=close_operation(original_gray,kernel)

#展示结果

pyplot.subplot(231),pyplot.imshow(original_gray,cmap='gray')
pyplot.title('original')
pyplot.axis('off')

pyplot.subplot(232),pyplot.imshow(img_1,cmap='gray')
pyplot.title('erode')
pyplot.axis('off')

pyplot.subplot(233),pyplot.imshow(img_2,cmap='gray')
pyplot.title('dilate')
pyplot.axis('off')

pyplot.subplot(234),pyplot.imshow(img_3,cmap='gray')
pyplot.title('open')
pyplot.axis('off')

pyplot.subplot(235),pyplot.imshow(img_4,cmap='gray')
pyplot.title('close')
pyplot.axis('off')
pyplot.show()

运行结果:(处理白色部分,通过更改img_erode和img_dilate中寻找最大和最小值的cv.minMaxLoc函数实现,cv.minMaxLoc函数用法在此不做详细解释。膨胀操作在cv.minMaxLoc函数中我们处理的是最大值,0~255,即对应“白色”部分)

处理黑色部分

以上是处理灰度图,以下是处理彩色图像 

import cv2 as cv
import numpy as np
from matplotlib import pyplot


#开
def open_operation(image, kernel):

    erosion_img = img_erode(image, kernel)
    dilation_img = img_dilate(erosion_img, kernel)

    return dilation_img

#闭
def close_operation(image, kernel):

    dilation_img = img_dilate(image, kernel)
    erosion_img = img_erode(dilation_img, kernel)

    return erosion_img


#腐蚀
def img_erode(src, kernel, borderType=cv.BORDER_CONSTANT):
    dst = np.zeros_like(src)  #创建并初始化数组
    kernel_h, kernel_w = kernel.shape[:2]
    kernel_half_h, kernel_half_w = kernel_h // 2, kernel_w // 2
    padded_src = cv.copyMakeBorder(src, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    
    for i in range(kernel_half_h, padded_src.shape[0] - kernel_half_h):
        for j in range(kernel_half_w, padded_src.shape[1] - kernel_half_w):
            roi = padded_src[i-kernel_half_h:i+kernel_half_h+1, j-kernel_half_w:j+kernel_half_w+1]
            dst[i-kernel_half_h, j-kernel_half_w] = cv.minMaxLoc(roi, mask=kernel)[0]         #寻找最小值

    padded_src = cv.copyMakeBorder(dst, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    return dst

#膨胀
def img_dilate(src, kernel, borderType=cv.BORDER_CONSTANT):
    dst = np.zeros_like(src)  #创建并初始化数组
    kernel_h, kernel_w = kernel.shape[:2]
    kernel_half_h, kernel_half_w = kernel_h // 2, kernel_w // 2
    padded_src = cv.copyMakeBorder(src, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    
    for i in range(kernel_half_h, padded_src.shape[0] - kernel_half_h):
        for j in range(kernel_half_w, padded_src.shape[1] - kernel_half_w):
            roi = padded_src[i-kernel_half_h:i+kernel_half_h+1, j-kernel_half_w:j+kernel_half_w+1]
            dst[i-kernel_half_h, j-kernel_half_w] = cv.minMaxLoc(roi, mask=kernel)[1]         #寻找最大值

    padded_src = cv.copyMakeBorder(dst, kernel_half_h, kernel_half_h, kernel_half_w, kernel_half_w, borderType)

    return dst


#读取图像

original = cv.imread(r'D:\deng\smalljob\ImageSet\dio.jpg')
original_gray = cv.cvtColor(original, cv.COLOR_BGR2GRAY)   #将图像从RGB颜色空间转换到灰度颜色空间

origin = cv.cvtColor(original, cv.COLOR_BGR2RGB) 
b,g,r=cv.split(origin)#分离颜色通道

kernel=np.ones((3,3),np.uint8)          #卷积核

erode_b=img_erode(b,kernel)#腐蚀通道
erode_g=img_erode(g,kernel)
erode_r=img_erode(r,kernel)

result_erode=np.dstack((erode_b,erode_g,erode_r))
result_erode=np.abs(result_erode).astype(np.float32)/255.0

dilate_b=img_dilate(b,kernel)#膨胀通道
dilate_g=img_dilate(g,kernel)
dilate_r=img_dilate(r,kernel)

result_dilate=np.dstack((dilate_b,dilate_g,dilate_r))
result_dilate=np.abs(result_dilate).astype(np.float32)/255.0

open_b=open_operation(b,kernel)#开通道
open_g=open_operation(g,kernel)
open_r=open_operation(r,kernel)

result_open=np.dstack((open_b,open_g,open_r))
result_open=np.abs(result_open).astype(np.float32)/255.0

close_b=close_operation(b,kernel)#闭通道
close_g=close_operation(g,kernel)
close_r=close_operation(r,kernel)

result_close=np.dstack((close_b,close_g,close_r))
result_close=np.abs(result_close).astype(np.float32)/255.0


#展示结果

pyplot.subplot(231),pyplot.imshow(origin)
pyplot.title('original')
pyplot.axis('off')

pyplot.subplot(232),pyplot.imshow(result_erode)
pyplot.title('erode')
pyplot.axis('off')

pyplot.subplot(233),pyplot.imshow(result_dilate)
pyplot.title('dilate')
pyplot.axis('off')

pyplot.subplot(234),pyplot.imshow(result_open)
pyplot.title('open')
pyplot.axis('off')

pyplot.subplot(235),pyplot.imshow(result_close)
pyplot.title('close')
pyplot.axis('off')
pyplot.show()

运行结果:(仔细看会发现,腐蚀操作和闭操作最后得到的图片最外边缘有道黑框,其实这个跟你处理的图像像素值有关,腐蚀操作在cv.minMaxLoc函数中我们处理的是最小值,对应黑色部分,但由于图像外框边缘每个像素点的周围8个像素点会丢失部分信息,例如最左上角第一个像素点,只有[1][1]、[1][2]、[2][1]、[2][2]有信息,缺失的部分做零处理,于是就出现了黑框)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值