一、圖像形態學
圖像形態學是圖像處理學科的一個單獨分支學科
主要針對的是灰度圖和二值圖像
是由數學的集合論以及數學中的拓撲幾何原理發展而來
二、膨脹操作(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()
效果圖如下: