OpenCV图像处理
1. 图像阈值
ret, dst = cv2.threshold(src, thresh, maxval, type)
src
: 输入图,只能输入单通道图像,通常来说为灰度图dst
: 输出图thresh
: 阈值maxval
: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值type
:二值化操作的类型,包含以下5种类型:- cv2.THRESH_BINARY : 超过阈值部分取maxval(最大值),否则取0
- cv2.THRESH_BINARY_INV : THRESH_BINARY的反转
- cv2.THRESH_TRUNC :大于阈值部分设为阈值,否则不变
- cv2.THRESH_TOZERO :大于阈值部分不改变,否则设为0
- cv2.THRESH_TOZERO_INV :THRESH_TOZERO的反转
import cv2
import matplotlib.pyplot as plt
img=cv2.imread('../image/cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) # 超过阈值部分取maxval(最大值),否则取0
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV) # THRESH_BINARY的反转
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC) # 大于阈值部分设为阈值,否则不变
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO) # 大于阈值部分不改变,否则设为0
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV) # THRESH_TOZERO的反转
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
2. 图像平滑
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread('../image/lenaNoise.png')[:,:,::-1] #cv2显示图像为bgr,plt显示图像为rgb
# 均值滤波
# 简单的平均卷积操作
blur = cv2.blur(img, (3, 3))
# 方框滤波
# 基本和均值一样,可以选择归一化
box1 = cv2.boxFilter(img,-1,(3,3), normalize=True)
# 方框滤波
# 基本和均值一样,可以选择归一化,容易越界
box2 = cv2.boxFilter(img,-1,(3,3), normalize=False)
# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)
# 中值滤波
# 相当于用中值代替
median = cv2.medianBlur(img, 5) # 中值滤波
# 展示所有的
plt.subplot(231),plt.imshow(img,"gray"),plt.title("img")
plt.subplot(232),plt.imshow(box1),plt.title("box1")
plt.subplot(233),plt.imshow(box2),plt.title("box2")
plt.subplot(234),plt.imshow(blur),plt.title("blur")
plt.subplot(235),plt.imshow(aussian),plt.title("aussian")
plt.subplot(236),plt.imshow(median),plt.title("median")
plt.show()
3. 形态学操作
3.1 腐蚀
腐蚀与膨胀十分相似,同样也是将原图以及任意形状的内核进行卷积。不同的是进行膨胀操作时,将内核划过图像,提取内核覆盖的最小像素值,代替锚点位置的像素。这个操作会使图像中的“暗区”扩展。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../image/wz.png')
kernel = np.ones((3,3),np.uint8)
img_erode = cv2.erode(img,kernel,iterations = 2) #腐蚀
plt.subplot(121),plt.imshow(img,"gray"),plt.title("img")
plt.subplot(122),plt.imshow(img_erode,"gray"),plt.title("img_erode")
plt.show()
3.2 膨胀
膨胀操作是将原图以及任意形状的内核进行卷积,内核中有一个可定义的锚点,称为内核中心点。进行膨胀操作时,将内核划过图像,提取内核覆盖的最大像素值,代替锚点位置的像素。这个操作会使图像中的“亮区”扩展。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../image/wz.png')
kernel = np.ones((3,3),np.uint8)
img_dilate = cv2.dilate(img,kernel,iterations = 2) #膨胀
plt.subplot(121),plt.imshow(img,"gray"),plt.title("img")
plt.subplot(122),plt.imshow(img_dilate,"gray"),plt.title("img_dilate")
plt.show()
3.3 开运算与闭运算
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../image/wz.png')
kernel = np.ones((5,5),np.uint8)
# 开:先腐蚀,再膨胀
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 闭:先膨胀,再腐蚀
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
plt.subplot(131),plt.imshow(img,"gray"),plt.title("img")
plt.subplot(132),plt.imshow(opening,"gray"),plt.title("opening")
plt.subplot(133),plt.imshow(closing,"gray"),plt.title("closing")
plt.show()
3.4 梯度运算
梯度=膨胀-腐蚀
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../image/wz.png')
kernel = np.ones((5,5),np.uint8)
dilate = cv2.dilate(img,kernel,iterations = 2)
erosion = cv2.erode(img,kernel,iterations = 2)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
plt.subplot(221),plt.imshow(img,"gray"),plt.title("img")
plt.subplot(222),plt.imshow(dilate,"gray"),plt.title("dilate")
plt.subplot(223),plt.imshow(erosion,"gray"),plt.title("erosion")
plt.subplot(224),plt.imshow(gradient,"gray"),plt.title("gradient")
plt.show()
3.5 礼帽与黑帽
-
礼帽 = 原始输入-开运算结果
-
黑帽 = 闭运算-原始输入
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../image/wz.png')
kernel = np.ones((5,5),np.uint8)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) #礼帽
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) #黑帽
plt.subplot(131),plt.imshow(img,"gray"),plt.title("img")
plt.subplot(132),plt.imshow(tophat,"gray"),plt.title("tophat")
plt.subplot(133),plt.imshow(gradient,"gray"),plt.title("gradient")
3.6 getStructuringElement()
图像处理经常要用到形态学操作,其中首先要获取结构元素。包括结构元素的大小及形状。cv2.getStructuringElement()返回一个特定大小与形状的结构元素用于形态学操作。
使用 Numpy 构建结构化元素是正方形的。但有时我们需要构建一个椭圆形/圆形的核。为了实现这种要求,提供了 OpenCV函数 cv2.getStructuringElement()。你只需要告诉他你需要的核的形状和大小。
cv.getStructuringElement( shape, ksize[, anchor] )
参数:
shape
: 元素形状,OpenCV 中提供了三种,MORPH_RECT(矩阵)
,MORPH_CORSS(交叉形状)
,MORPH_ELLIPSE(椭圆)
;ksize
,结构元素的大小;anchor
,元素内的描点位置,默认为(-1,-1)
表示形状中心;值得注意的时,只有MORPH-CROSS
形状依赖 描点位置,其它情况 描点仅调节其他形态运算结果偏移了多少
import cv2
import numpy as np
# 矩形
kernel = np.ones((5,5),np.uint8)
kernel_1 = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
print("矩形:\n%s" %kernel)
#print("矩形1:\n%s" %kernel_1)
# 椭圆
kernel_2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
print("椭圆:\n%s" %kernel_2)
# 十字形
kernel_3 = cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
print("十字:\n%s" %kernel_3)
矩形:
[[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]]
椭圆:
[[0 0 1 0 0]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[0 0 1 0 0]]
十字:
[[0 0 1 0 0]
[0 0 1 0 0]
[1 1 1 1 1]
[0 0 1 0 0]
[0 0 1 0 0]]
参考链接:https://www.cnblogs.com/zeroing0/p/14127411.html
3.7 morphologyEx()
cv.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]]
参数:
src
,预处理的图像;op
,形态操作的类型,可选择一种类型- 开运算 : cv2.MORPH_OPEN : 2
- 闭运算 : cv2.MORPH_CLOSE: 3
- 梯度运算 : cv2.MORPH_GRADIENT: 4
- 礼帽 : cv2.MORPH_TOPHAT: 5
- 黑帽 : cv2.MORPH_BLACKHAT: 6
kernel
: 结构元素,来自于getStructuringElement
方法
参考链接:
https://www.cnblogs.com/zeroing0/p/14127411.html
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/opening_closing_hats/opening_closing_hats.html