OpenCV 图像处理(学习笔记)
OpenCV 图像处理(学习笔记)
灰度图
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline
img=cv2.imread('cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 查看维度
img_gray.shape
(414, 500)
# 查看灰度图
cv2.imshow("img_gray", img_gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
HSV
H - 色调(主波长)。
S - 饱和度(纯度/颜色的阴影)。
V 值(强度)
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.imshow("hsv", hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像阈值
cv2.threshold
是一个阈值函数处理,如果图像的矩阵大于一定的阈值,应该怎么处理。
ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV
cv2.THRESH_BINARY ? ? ? ? ? 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INV ? ?THRESH_BINARY的反转
cv2.THRESH_TRUNC ? ? ? ? ? ?大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO ? ? ? ? ?大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INV ?THRESH_TOZERO的反转
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)
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()
图像平滑
原图如下:
img = cv2.imread('lenaNoise.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
均值滤波
简单的平均卷积操作.
均值滤波可去掉一些噪声滤波。
首先提供一个全部都是1的卷积核,这里矩阵为3*3
的大小,去与每一个3*3的数相互乘再相加最后再除以它们的数量(这里是9).
blur = cv2.blur(img, (3, 3))
cv2.imshow('blur', blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
方框滤波
基本和均值一样,可以选择归一化。
方框滤波与均值滤波唯一区别在于多了一个normalize
的参数一旦为False,就是不除以9,会导致数值越界。
box = cv2.boxFilter(img,-1,(3,3), normalize=True)
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 基本和均值一样,可以选择归一化,容易越界
box = cv2.boxFilter(img,-1,(3,3), normalize=False)
cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
高斯滤波
高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的。
高斯滤波简单来讲一个中间的5*5
的卷积核中间是1,离得比较近的是0.8,然后远一点的是0.6,依次递减。
aussian = cv2.GaussianBlur(img, (5, 5), 1)
cv2.imshow('aussian', aussian)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波
相当于用中值代替
中值滤波,通过从小到大进行排序然后取出中间的值,然后把中间的结果去进行处理。
median = cv2.medianBlur(img, 5) # 中值滤波
cv2.imshow('median', median)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 展示所有的
res = np.hstack((blur,aussian,median))
#print (res)
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
我这里截图截得不全见谅。
形态学-腐蚀操作
使当前边缘越来越小,通过一定的卷积核在一定范围内抹去不同的一小块。
img = cv2.imread('dige.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 卷积核
kernel = np.ones((3,3),np.uint8)
# cv2.erode腐蚀方法,iterations迭代次数
erosion = cv2.erode(img,kernel,iterations = 1)
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
接下来通过一个圆圈做一个案例,看通过不同的腐蚀迭代次数产生的效果怎么样。
pie = cv2.imread('pie.png')
cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((30,30),np.uint8)
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
形态学-膨胀操作
如果我希望我的图像进行一些腐蚀操作造成图片产生了一些损害,那么cv2.dilate
膨胀参数会进行一定的填充。
img = cv2.imread('dige.png')
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8)
# 去掉线条腐蚀操作
dige_erosion = cv2.erode(img,kernel,iterations = 1)
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8)
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)
cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()
pie = cv2.imread('pie.png')
kernel = np.ones((30,30),np.uint8)
# 不同的迭代程度
dilate_1 = cv2.dilate(pie,kernel,iterations = 1)
dilate_2 = cv2.dilate(pie,kernel,iterations = 2)
dilate_3 = cv2.dilate(pie,kernel,iterations = 3)
res = np.hstack((dilate_1,dilate_2,dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
开运算与闭运算
开运算:先腐蚀去掉毛刺,再膨胀填充图片
img = cv2.imread('dige.png')
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
闭运算:先膨胀,再腐蚀
img = cv2.imread('dige.png')
kernel = np.ones((5,5),np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()
梯度运算
梯度运算=膨胀-腐蚀。
pie = cv2.imread('pie.png')
# 定义一个7*7的卷积核
kernel = np.ones((7,7),np.uint8)
# 膨胀5次
dilate = cv2.dilate(pie,kernel,iterations = 5)
# 腐蚀5次
erosion = cv2.erode(pie,kernel,iterations = 5)
# 展示结果
res = np.hstack((dilate,erosion))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 展示梯度运算
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()
礼帽与黑帽
礼帽 = 原始输入-开运算结果 (只保留刺)
黑帽 = 闭运算-原始输入 (保留一点点轮廓)
#礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
#黑帽
img = cv2.imread('dige.png')
blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()