机器学习基础篇(5)之形态学

1.形态学概述

什么是形态学 ?

  • 指一系列处理图像形状特征的图像处理技术

  • 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。

  • 这些处理方法基本是对二进制图像进行处理, 即黑白图像

  • 卷积核决定着图像处理后的效果

  • 形态学常用基本操作有:

    • 膨胀和腐蚀

    • 开运算

    • 闭运算

    • 顶帽

    • 黑帽

形态学,本质上就是对二进制图像进行图像处理,采用卷积的方式。 

2.图像二值化 

二值化: 将图像的每个像素变成两种值, 比如0, 255.

2.1.自定义阈值

threshold(src, thresh, maxval, type[, dst])

  • src 最好是灰度图

  • thresh: 阈值

  • maxval: 最大值, 最大值不一定是255 建议是255比较好

  • type: 操作类型. 常见操作类型如下:

 代码案例:

import cv2
import numpy as np

img = cv2.imread('123.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 返回两个结果, 一个是阈值, 另一个是处理后的图片
ret, dst = cv2.threshold(gray, 80, 255, cv2.THRESH_BINARY)
print("ret",ret)#80.0
cv2.imshow('dog', np.hstack((gray, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

2.2.自适应阈值二值化

 在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。

adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, [dst=None)   这种方法需要我们指定六个参数,返回值只有一个。

src:建议最好灰度图

maxValue:最大值, 最大值不一定是255 建议是255比较好

Adaptive Method- 指定计算阈值的方法。                               cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值         cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口。     

Block Size - 邻域大小(用来计算阈值的区域大小)。     

C - 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。

 案例代码:

# 因为光线问题, 全局二值化导致有部分地方看不见了.这时就需要自适应阈值二值化了.
import cv2
import numpy as np

img = cv2.imread('./math.png')

cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 1920, 1080)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 自适应阈值二值化只返回一个值, 即二值化后的结果
dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 3, 0)

cv2.imshow('img', np.hstack((gray, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

3.腐蚀 & 膨胀

我们一般让物体是白色,背景是黑色的,

腐蚀:就是让物体变“苗条了”

膨胀:就是让物体变“胖胖的”

3.1 腐蚀操作

腐蚀操作也是用卷积核扫描图像, 只不过腐蚀操作的卷积和一般都是1, 如果卷积核内所有像素点都是白色, 那么锚点即为白色.

erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

  • iterations是腐蚀操作的迭代次数, 次数越多, 腐蚀操作执行的次数越多, 腐蚀效果越明显

  • kernel越大,腐蚀效果越明显

示例代码:

import cv2
import numpy as np

img = cv2.imread('./123.png')

kernel = np.ones((3, 3), np.uint8)

dst = cv2.erode(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 3.2获取形态学卷积核

在腐蚀操作里面,我们的卷积核是自己创建的,opencv也给我提供了获取卷积核的api.不需要我们手工创建卷积核.

getStructuringElement(shape, ksize[, anchor])

  • shape是指卷积核的形状, 注意不是指长宽, 是指卷积核中1形成的形状.

    • MORPH_RECT 卷积核中的1是矩形, 常用.

    • MORPH_ELLIPSE 椭圆

    • MORPH_CROSS 十字

shape可以确定矩阵里面1组合而成的形状, 

示例代码:

import cv2
import numpy as np

img = cv2.imread('./j.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.erode(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 3.3膨胀操作

膨胀是腐蚀的相反操作,就是将物体变肥了, 基本原理是只要保证卷积核的锚点是非0值, 周边无论是0还是非0值, 都变成非0值.

dst=dilate(img, kernel, iterations=1)

示例代码:

import cv2
import numpy as np

img = cv2.imread('./j.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.dilate(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

3.4腐蚀和膨胀的联合使用

先腐蚀,将一些小的点进行去除,然后再膨胀回来恢复原样,达到去除小的点的效果。

4.开运算 & 闭运算

开运算和闭运算都是腐蚀和膨胀的基本应用.

4.1.开运算

可以去除噪声

  • 开运算 = 腐蚀 + 膨胀

  • dst = cv2.morphologyEx(src,cv2.MORPH_OPEN,kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])

    • MORPH_OPEN 表示形态学的开运算

    • kernel 如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel

    • iterations 操作数,操作数越大,效果越好

 示例代码:

import cv2
import numpy as np

img = cv2.imread('./dotj.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 腐蚀
# dst = cv2.erode(img, kernel, iterations=2)

# # 膨胀
# dst = cv2.dilate(dst, kernel, iterations=2)

# 直接调用opencv提供的开运算api
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

效果:

 

 

4.2.闭运算

闭运算 = 膨胀 + 腐蚀  也可以去除噪声点。

示例代码:

import cv2
import numpy as np

img = cv2.imread('./dotinj.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

效果:

 

 5.运用

5.1形态学梯度---边缘提取

  • 梯度 = 原图 - 腐蚀

  • 腐蚀之后原图边缘变小了, 原图 - 腐蚀 就可以得到腐蚀掉的部分, 即边缘.

 使用的api和开闭运算是一样都。

import cv2
import numpy as np

img = cv2.imread('./j.png')

# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

5.2.顶帽运算---获取图像外的噪声点

  • 顶帽 = 原图 - 开运算

  • 开运算的效果是去除图像外的噪点, 原图 - 开运算就得到了去掉的噪点.

 代码案例:

import cv2
import numpy as np

img = cv2.imread('./tophat.png')

# 注意调整kernel以保留小图形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (19, 19))

dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 5.3.黑帽操作--获取图像内的噪声点

  • 黑帽 = 原图 - 闭运算

  • 闭运算可以将图形内部的噪点去掉, 那么原图 - 闭运算的结果就是图形内部的噪点.

示例代码:

import cv2
import numpy as np

img = cv2.imread('./dotinj.png')

# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))

dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值