二值化: 图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮廓。要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像。
将图像的每个像素变成两种值, 比如0, 255.
cv2.threshold(src, thresh, maxval, type[, dst])
src: 最好是灰度图
thresh: 阈值
maxval: 最大值, 最大值不一定是255(用的最多的还是255)
type: 操作类型. 常见操作类型如下(常用的是1、4):
通常情况下,我们一般不知道设定怎样的阈值thresh才能得到比较好的二值化效果,只能去尝试。但是如果对于一幅双峰图像(可理解成图像直方图中存在两个峰值),我们指定的阈值应尽量在两个峰之间的峰谷。这时,我们就要多传人一个参数cv2. THRESH_OTSU,并且把阈值设为0,算法就会自动找到最优阈值,并返回。
会返回两个结果, 一个是阈值thresh, 另一个是处理后的图片dst
import cv2
import numpy as np
# 导入图片
img = cv2.imread('./dog.jpeg')
# 二值化操作是对灰度图像操作, 把dog变成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 注意, threshold会返回两个值, 一个是阈值, 二值化处理后的图片
thresh, dst = cv2.threshold(gray, 110, 255, cv2.THRESH_BINARY)
print(thresh)
# 展示
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。但是这种方法并不适应于所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果,比全局二值化更加灵活一些。
通常情况下,我们一般不知道设定怎样的阈值thresh才能得到比较好的二值化效果,只能去尝试。但是如果对于一幅双峰图像(可理解成图像直方图中存在两个峰值),我们指定的阈值应尽量在两个峰之间的峰谷。这时,我们就要多传人一个参数cv2. THRESH_OTSU,并且把阈值设为0,算法就会自动找到最优阈值,并返回。
import cv2
import numpy as np
# 导入图片
img = cv2.imread('./dog.jpeg')
# 二值化操作是对灰度图像操作, 把dog变成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应阈值二值化只有一个返回值,
dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 19, 0)
# 展示
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
腐蚀操作也是用卷积核扫描图像, 只不过腐蚀操作的卷积核元素一般都是1, 如果卷积核内所有像素点都是白色, 那么锚点即为白色.
大部分时候腐蚀操作使用的都是全为1的卷积核.
cv2.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
import cv2
import numpy as np
# 导入图片
img = cv2.imread('./j.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()
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()
膨胀是腐蚀的相反操作, 基本原理是只要保证卷积核的锚点是非0值, 周边无论是0还是非0值, 都变成非0值.
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()
膨胀和腐蚀的简单应用:
# 膨胀和腐蚀简单应用
import cv2
import numpy as np
# 导入图片
img = cv2.imread('./msb.png')
# 定义核
kernel = np.ones((5, 5), np.uint8)
# 先腐蚀
dst = cv2.erode(img, kernel, iterations=1)
# 再膨胀
dst = cv2.dilate(dst, kernel, iterations=1)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
# 开运算 = 腐蚀 + 膨胀
# 开运算提供了另一种去除噪声的思路.
img = cv2.imread('./dotj.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 直接调用opencv提供的开运算api
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
# 闭运算= 膨胀 + 腐蚀
# 闭运算可以去除图形内部的噪声
img = cv2.imread('./dotinj.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
# 形态学梯度 = 原图 - 腐蚀
import cv2
import numpy as np
img = cv2.imread('./j.png')
# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
# 顶帽操作 = 原图 - 开运算 得到图形外的噪声
import cv2
import numpy as np
img = cv2.imread('./dotj.png')
# 注意调整kernel以保留小图形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=2)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
# 黑帽操作 = 原图 - 闭运算 得到图形内部的噪声
import cv2
import numpy as np
img = cv2.imread('./dotinj.png')
# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=2)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
附OpenCV目录:OpenCV总目录学习笔记
智科专业小白,写博文不容易,如果喜欢的话可以点个赞哦!