OpenCV 图像处理(学习笔记) 电脑版发表于:2024/1/8 16:39 ![](https://img.tnblog.net/arcimg/hb/3c9a034e352c4476b4ec6d8cc07a0263.png) >#OpenCV 图像处理(学习笔记) [TOC] ## 灰度图 ```python 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) ```python # 查看灰度图 cv2.imshow("img_gray", img_gray) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/17437604bf264a94a5939bb25c8ef461.png) ## HSV tn2>H - 色调(主波长)。 S - 饱和度(纯度/颜色的阴影)。 V 值(强度) ```python hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV) cv2.imshow("hsv", hsv) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/6b6c6a0fad8d48d09f6b3f386ec890a6.png) ## 图像阈值 tn2>`cv2.threshold`是一个阈值函数处理,如果图像的矩阵大于一定的阈值,应该怎么处理。 ```python ret, dst = cv2.threshold(src, thresh, maxval, type) ``` tn2>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的反转 ```python 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() ``` ![](https://img.tnblog.net/arcimg/hb/55b7ee7565c54a35a394933a01979845.png) ## 图像平滑 ![](https://img.tnblog.net/arcimg/hb/565fb153e7534700a63b7bf1a9883927.png) tn2>原图如下: ```python img = cv2.imread('lenaNoise.png') cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/f28f63bb5a4243feb367cfae54c1e898.png) ### 均值滤波 tn2>简单的平均卷积操作. 均值滤波可去掉一些噪声滤波。 首先提供一个全部都是1的卷积核,这里矩阵为`3*3`的大小,去与每一个3*3的数相互乘再相加最后再除以它们的数量(这里是9). ```python blur = cv2.blur(img, (3, 3)) cv2.imshow('blur', blur) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/9723895375464e03a55277c4c6fb7b61.png) ### 方框滤波 tn2>基本和均值一样,可以选择归一化。 方框滤波与均值滤波唯一区别在于多了一个`normalize`的参数一旦为False,就是不除以9,会导致数值越界。 ```python box = cv2.boxFilter(img,-1,(3,3), normalize=True) cv2.imshow('box', box) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/6d665cfb973948388d4a65c4e9bbfecf.png) ```python # 基本和均值一样,可以选择归一化,容易越界 box = cv2.boxFilter(img,-1,(3,3), normalize=False) cv2.imshow('box', box) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/8d56b1e48060471780cc1cb7f7eec89c.png) ### 高斯滤波 tn2>高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的。 高斯滤波简单来讲一个中间的`5*5`的卷积核中间是1,离得比较近的是0.8,然后远一点的是0.6,依次递减。 ```python aussian = cv2.GaussianBlur(img, (5, 5), 1) cv2.imshow('aussian', aussian) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/ffc2a45234714c31b915e834bd062124.png) ### 中值滤波 tn2>相当于用中值代替 中值滤波,通过从小到大进行排序然后取出中间的值,然后把中间的结果去进行处理。 ```python median = cv2.medianBlur(img, 5) # 中值滤波 cv2.imshow('median', median) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/51eba112e1df4932b072c020eccf1b8b.png) ```python # 展示所有的 res = np.hstack((blur,aussian,median)) #print (res) cv2.imshow('median vs average', res) cv2.waitKey(0) cv2.destroyAllWindows() ``` tn2>我这里截图截得不全见谅。 ![](https://img.tnblog.net/arcimg/hb/65c33a023c17417fa6218d8ee7cd04f0.png) ## 形态学-腐蚀操作 tn2>使当前边缘越来越小,通过一定的卷积核在一定范围内抹去不同的一小块。 ```python img = cv2.imread('dige.png') cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/9dd1b3560db049eaa871f93bf047a45f.png) ```python # 卷积核 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() ``` ![](https://img.tnblog.net/arcimg/hb/7a85456b229d4609b7217b31b9c23367.png) tn2>接下来通过一个圆圈做一个案例,看通过不同的腐蚀迭代次数产生的效果怎么样。 ```python pie = cv2.imread('pie.png') cv2.imshow('pie', pie) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/643c012a247945d7ad6cd2c8f130eddb.png) ```python 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() ``` ![](https://img.tnblog.net/arcimg/hb/0d96bd186101493cb0a83185dfb03dce.png) ## 形态学-膨胀操作 tn2>如果我希望我的图像进行一些腐蚀操作造成图片产生了一些损害,那么`cv2.dilate`膨胀参数会进行一定的填充。 ```python img = cv2.imread('dige.png') cv2.imshow('img', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/96e1afc71d8b415fb411cb523ec0e032.png) ```python kernel = np.ones((3,3),np.uint8) # 去掉线条腐蚀操作 dige_erosion = cv2.erode(img,kernel,iterations = 1) cv2.imshow('erosion', erosion) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/f25f07b81ef744b0be77887f470f78a2.png) ```python 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() ``` ![](https://img.tnblog.net/arcimg/hb/31b41fdaec714ffb8cdc218dfae3914a.png) ```python 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() ``` ![](https://img.tnblog.net/arcimg/hb/fff591cdadd948578502ab7a051edc28.png) ## 开运算与闭运算 tn2>开运算:先腐蚀去掉毛刺,再膨胀填充图片 ```python 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() ``` ![](https://img.tnblog.net/arcimg/hb/e36a44cd39ea4694afb8261dd64c8fda.png) tn2>闭运算:先膨胀,再腐蚀 ```python 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() ``` ## 梯度运算 tn2>梯度运算=膨胀-腐蚀。 ```python 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() ``` ![](https://img.tnblog.net/arcimg/hb/6ee27ac1ce4743da9509f38fcdd16336.png) ```python # 展示梯度运算 gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel) cv2.imshow('gradient', gradient) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/0abb2657c99c4cecaf169778b191f089.png) ## 礼帽与黑帽 tn2>礼帽 = 原始输入-开运算结果 (只保留刺) 黑帽 = 闭运算-原始输入 (保留一点点轮廓) ```python #礼帽 img = cv2.imread('dige.png') tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel) cv2.imshow('tophat', tophat) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/1e25195793c8410d936533923fdb539f.png) ```python #黑帽 img = cv2.imread('dige.png') blackhat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel) cv2.imshow('blackhat ', blackhat ) cv2.waitKey(0) cv2.destroyAllWindows() ``` ![](https://img.tnblog.net/arcimg/hb/1623143678474d9e93086505a67cfade.png)