一、图像形态学
图像形态学是图像处理学科的一个单独分支学科
主要针对的是灰度图和二值图像
是由数学的集合论以及数学中的拓扑几何原理发展而来
二、膨胀操作(dilate)
3×3的卷积核
以3×3为卷积核从左往右(从上往下)开始运行,若这卷积核内存在1,则用1替代中心元素。
最大值取代中心像素
白变多,黑变少
膨胀的作用:
对象大小增加一个像素(3×3)
平滑对象边缘
减少或者填充对象之间的距离
二值图
import cv2 as cv
import numpy as npdef dilate(image):print(image.shape)gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)cv.imshow("binary", binary)kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))dst = cv.dilate(binary, kernel)cv.imshow("dilate", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\number.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
dilate(src)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
·彩色图·
import cv2 as cv
import numpy as npsrc = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\l.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
dst = cv.dilate(src, kernel)
cv.imshow("result", dst)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
三、腐蚀操作(erode)
3×3的卷积核
以3×3为卷积核从左往右(从上往下)开始运行,若这卷积核内存在0,则用0替代中心元素。
最小值取代中心像素
黑变多,白变少
二值图
import cv2 as cv
import numpy as npdef erode(image):print(image.shape)gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#图像二值化cv.imshow("binary", binary)kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 15))dst = cv.erode(binary, kernel)cv.imshow("erode", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\number.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
erode_demo(src)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
彩色图
import cv2 as cv
import numpy as npsrc = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\l.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))
dst = cv.erode(src, kernel)
cv.imshow("erode", dst)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
腐蚀和膨胀针对彩色图像和二值图像
总结:膨胀---白变多黑变少、腐蚀---黑变多白变少
四、开操作(open)
开操作=腐蚀+膨胀
可以消除图像中小的干扰区域
cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
,若出现反转可以将参数设置为cv.THRESH_BINARY_INV
import cv2 as cv
import numpy as npdef open(image):print(image.shape)gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)cv.imshow("binary", binary)kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (5, 5))binary = cv.morphologyEx(binary, cv.MORPH_OPEN, kernel)cv.imshow("open-result", binary)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\test.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
open(src)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
五、闭操作(close)
闭操作=膨胀+腐蚀
填充小的封闭区域
import cv2 as cv
import numpy as npdef close(image):print(image.shape)gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)cv.imshow("binary", binary)kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))binary = cv.morphologyEx(binary, cv.MORPH_CLOSE, kernel)cv.imshow("close_demo", binary)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\test1.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
close(src)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
开闭操作只针对二值图像
总结:开操作消除白点,闭操作消除黑点
六、顶帽(tophat)
原图像与开操作的差值图像
彩色图像
import cv2 as cv
import numpy as npdef tophat(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 15))dst = cv.morphologyEx(gray, cv.MORPH_TOPHAT, kernel)"""若图片不够亮可以对图像进行整体增加亮度cimage = np.array(gray.shape, np.uint8)cimage = 120;dst = cv.add(dst, cimage)"""cv.imshow("tophat", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\l.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
tophat(src)
cv.waitKey(0)cv.destroyAllWindows()
效果图如下:
二值图像
import cv2 as cv
import numpy as npdef tophat_binary(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))dst = cv.morphologyEx(binary, cv.MORPH_TOPHAT, kernel)cv.imshow("tophat_binary", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\test.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
tophat_binary(src)
cv.waitKey(0)cv.destroyAllWindows()
效果图如下:
七、黑帽(blackhat)
闭操作与原图像的差值图像
彩色图像
import cv2 as cv
import numpy as npdef blackhat(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)kernel = cv.getStructuringElement(cv.MORPH_RECT, (15, 15))dst = cv.morphologyEx(gray, cv.MORPH_BLACKHAT, kernel)"""若图片不够亮可以对图像进行整体增加亮度cimage = np.array(gray.shape, np.uint8)cimage = 120;dst = cv.add(dst, cimage)"""cv.imshow("blackhat", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\l.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
blackhat(src)
cv.waitKey(0)cv.destroyAllWindows()
效果图如下:
二值图像
import cv2 as cv
import numpy as npdef blackhat_binary(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5))dst = cv.morphologyEx(binary, cv.MORPH_BLACKHAT, kernel)cv.imshow("blackhat_binary", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\test.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
blackhat_binary(src)
cv.waitKey(0)cv.destroyAllWindows()
效果图如下:
八、形态学梯度(Gradient)
基本梯度:膨胀后的图像减去腐蚀后的图像得到的差值图像
内部梯度:原图像减去腐蚀之后的图像得到的差值图像
外部梯度:图像膨胀之后减去原来的图像得到的差值图像
基本梯度
import cv2 as cv
import numpy as npdef base_gradient(image):gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))dst = cv.morphologyEx(binary, cv.MORPH_GRADIENT, kernel)cv.imshow("base_gradient", dst)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\test.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
base_gradient(src)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下:
内梯度和外梯度
import cv2 as cv
import numpy as npdef ex_in_gradient(image):kernel = cv.getStructuringElement(cv.MORPH_RECT, (3, 3))dm = cv.dilate(image, kernel)em = cv.erode(image, kernel)dst1 = cv.subtract(image, em) # internal gradientdst2 = cv.subtract(dm, image) # external gradientcv.imshow("internal", dst1)cv.imshow("external", dst2)src = cv2.imread(r"G:\Juptyer_workspace\study\opencv\opencv3\test.jpg")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
ex_in_gradient(src)cv.waitKey(0)
cv.destroyAllWindows()
效果图如下: