Dream的茶话会|Python OpenCV图像处理(??转换+梯度??边缘检测+图像融合,aplacian金字塔合成新物种)
文章图片
Hello,大家好我叫是Dream呀,一个有趣的Python博主,小白一枚,多多关照
CSDN Python领域新星创作者,大二在读,欢迎大家找我合作学习
入门须知:这片乐园从不缺乏天才,努力才是你的最终入场券!
最后,愿我们都能在看不到的地方闪闪发光,一起加油进步
“一万次悲伤,依然会有Dream,我一直在最温暖的地方等你”,唱的就是我!哈哈哈~
???
有趣的图像处理:
- 一、形态学转换
-
- 1. 侵蚀
- 2. 扩张
- 3.形态学梯度
- 二、图像梯度
-
- 1. Sobel 和 Scharr 算子
- 2. Laplacian 算子
- 三、Canny边缘检测
-
- 1.查找图像的强度梯度
-
- 1.1非极大值抑制
- 1.2磁滞阈值
- 2.OpenCV中的Canny Edge检测
-
- 2.1不加高斯滤波
- 2.2加高斯滤波
- 2.3调整高斯滤波
- 四、图像金字塔
-
- 1 图像金字塔简介
- 2 向下取样——pyrDown()
-
- 2.1 基础理论
- 2.2 代码示例
- 3 向上取样——pyrUp()
-
- 3.1 基础理论
- 3.2 代码示例
- 4.图像融合
-
- 4.1理论代码:
- 4.2融合效果:
一、形态学转换 1. 侵蚀 侵蚀的基本思想就像土壤侵蚀一样,它侵蚀前景物体的边界(尽量使前景保持白色)。它是做什么的呢?内核滑动通过图像(在2D卷积中)。原始图像中的一个像素(无论是1还是0)只有当内核下的所有像素都是1时才被认为是1,否则它就会被侵蚀(变成0)。
结果是,根据内核的大小,边界附近的所有像素都会被丢弃。因此,前景物体的厚度或大小减小,或只是图像中的白色区域减小。它有助于去除小的白色噪声(正如我们在颜色空间章节中看到的),分离两个连接的对象等。
腐蚀主要就是调用原图:cv2.erode(img,kernel,iterations)
,这个函数的参数是:
第一个参数:img指需要腐蚀的图
第二个参数:kernel指腐蚀操作的内核,默认是一个简单的3X3矩阵,我们也可以利用getStructuringElement()函数指明它的形状
第三个参数:iterations指的是腐蚀次数,省略是默认为1
文章图片
代码:
import cv2 as cv
import numpy as np
img = cv.imread('yuanxing.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv.erode(img,kernel,iterations=2)
cv.imshow('xuxux',erosion)
cv.waitKey(0)
效果图:
文章图片
2. 扩张 它与侵蚀正好相反。如果内核下的至少一个像素为“ 1”,则像素元素为“ 1”。因此,它会增加图像中的白色区域或增加前景对象的大小。通常,在消除噪音的情况下,腐蚀后会膨胀。因为腐蚀会消除白噪声,但也会缩小物体。因此,我们对其进行了扩展。由于噪音消失了,它们不会回来,但是我们的目标区域增加了。在连接对象的损坏部分时也很有用。
代码:
import cv2 as cv
import numpy as np
img = cv.imread('yuanxing.png',1)
kernel = np.ones((5,5),np.uint8)
# erosion=cv.erode(img,kernel,iterations = 1)
erosion=cv.dilate(img,kernel,iterations=1)
cv.imshow('erosion',erosion)cv.waitKey(0)
效果图:
文章图片
3.形态学梯度 这是图像扩张和侵蚀之间的区别。结果将看起来像对象的轮廓:
代码:
import cv2 as cv
import numpy as np
img = cv.imread('yuanxing.png',1)
kernel = np.ones((5,5),np.uint8)gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)
cv.imshow('erosion',gradient)cv.waitKey(0)
效果图:
文章图片
二、图像梯度
1. Sobel 和 Scharr 算子前言:
在本章中,我们将学习: - 查找图像梯度,边缘等 - 我们将看到以下函数:cv.Sobel(),cv.Scharr(),cv.Laplacian()等
OpenCV提供三种类型的梯度滤波器或高通滤波器,即Sobel,Scharr和Laplacian。我们将看到他们每一种。
Sobel算子
是高斯平滑加微分运算的联合运算,因此它更抗噪声。逆可以指定要采用的导数方向,垂直或水平(分别通过参数yorder和xorder)。逆还可以通过参数ksize指定内核的大小。如果ksize = -1,则使用3x3 Scharr滤波器,比3x3 Sobel滤波器具有更好的结果。2. Laplacian 算子
文章图片
# -*-coding:utf-8 -*-
# @Author:到点了,心疼徐哥哥
# 奥利给干!!!import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('qipan.jpg',0)
# 其中,0表示将图片以灰度读出来。
laplacian = cv.Laplacian(img,cv.CV_64F)
# 图像边缘处理sobel细节
# 利用Sobel方法可以进行sobel边缘检测
# img表示源图像,即进行边缘检测的图像
# cv2.CV_64F表示64位浮点数即64float。
# 这里不使用numpy.float64,因为可能会发生溢出现象。用cv的数据则会自动
# 第三和第四个参数分别是对X和Y方向的导数(即dx,dy),对于图像来说就是差分,这里1表示对X求偏导(差分),0表示不对Y求导(差分)。其中,X还可以求2次导。
# 注意:对X求导就是检测X方向上是否有边缘。
# 第五个参数ksize是指核的大小。# 这里说明一下,这个参数的前四个参数都没有给谁赋值,而ksize则是被赋值的对象
# 实际上,这时可省略的参数,而前四个是不可省的参数。注意其中的不同点
sobelx = cv.Sobel(img,cv.CV_64F,1,0,ksize=5)
sobely = cv.Sobel(img,cv.CV_64F,0,1,ksize=5)
plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()
文章图片
在我们的最后一个示例中,输出数据类型为cv.CV_8U或np.uint8。但这有一个小问题。黑色到白色的过渡被视为正斜率(具有正值),而白色到黑色的过渡被视为负斜率(具有负值)。因此,当您将数据转换为np.uint8时,所有负斜率均??设为零。简而言之,您会错过这一边缘信息。
如果要检测两个边缘,更好的选择是将输出数据类型保留为更高的形式,例如cv.CV_16S,cv.CV_64F等,取其绝对值,然后转换回cv.CV_8U。
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('box.png',0)
# Output dtype = cv.CV_8U
sobelx8u = cv.Sobel(img,cv.CV_8U,1,0,ksize=5)
# Output dtype = cv.CV_64F. Then take its absolute and convert to cv.CV_8U
sobelx64f = cv.Sobel(img,cv.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)
plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])
plt.show()
文章图片
三、Canny边缘检测
目标
在本章中,我们将学习 - Canny边缘检测的概念 - OpenCV函数: cv.Canny()
理论: Canny Edge Detection是一种流行的边缘检测算法。它由John F. Canny发明
这是一个多阶段算法,我们将经历每个阶段。
降噪:
由于边缘检测容易受到图像中噪声的影响,因此第一步是
使用5x5高斯滤波器消除图像中的噪声。我们已经在前面的章节中看到了这一点。
1.查找图像的强度梯度 然后使用Sobel核在水平和垂直方向上对平滑的图像进行滤波,以在水平方向(Gx)和垂直方向(Gy)上获得一阶导数。从这两张图片中,我们可以找到每个像素的边缘渐变和方向,如下所示:
文章图片
1.1非极大值抑制
在获得梯度大小和方向后,将对图像进行全面扫描,以去除可能不构成边缘的所有不需要的像素。为此,在每个像素处,检查像素是否是其在梯度方向上附近的局部最大值。查看下面的图片:
点A在边缘(垂直方向)上。渐变方向垂直于边缘。点B和C在梯度方向上。因此,将A点与B点和C点进行检查,看是否形成局部最大值。如果是这样,则考虑将其用于下一阶段,否则将其抑制(置为零)。 简而言之,你得到的结果是带有“细边”的二进制图像。
1.2磁滞阈值
该阶段确定哪些边缘全部是真正的边缘,哪些不是。为此,我们需要两个阈值minVal和maxVal。强度梯度大于maxVal的任何边缘必定是边缘,而小于minVal的那些边缘必定是非边缘,因此将其丢弃。介于这两个阈值之间的对象根据其连通性被分类为边缘或非边缘。如果将它们连接到“边缘”像素,则将它们视为边缘的一部分。
2.OpenCV中的Canny Edge检测 OpenCV将以上所有内容放在单个函数 cv.Canny() 中。我们将看到如何使用它。第一个参数是我们的输入图像。第二个和第三个参数分别是我们的minVal和maxVal。第三个参数是perture_size。它是用于查找图像渐变的Sobel内核的大小。默认情况下为3。最后一个参数是L2gradient,它指定用于查找梯度幅度的方程式。如果为True,则使用上面提到的更精确的公式,否则使用以下函数:默认情况下,它为False。
2.1不加高斯滤波
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('haojin.jpg',0)
# img1 = cv.GaussianBlur(img, (1,1),0)
edges = cv.Canny(img,50,100)
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()
文章图片
2.2加高斯滤波
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('haojin.jpg',0)
img1 = cv.GaussianBlur(img, (5,5),0)
edges = cv.Canny(img1,50,100)
plt.subplot(121),plt.imshow(img1,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()
文章图片
2.3调整高斯滤波
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('haojin.jpg',0)
img1 = cv.GaussianBlur(img, (1,1),0)
edges = cv.Canny(img1,50,100)
plt.subplot(121),plt.imshow(img1,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()
文章图片
四、图像金字塔
目标1 图像金字塔简介 以多个分辨率来表示图像的一种有效且概念简单的结构是
在本章中, - 我们将学习图像金字塔 - 我们将使用图像金字塔创建一个新的水果“Orapple” - 我们将看到以下功能:cv.pyrUp(),cv.pyrDown()
图像金字塔
。图像金字塔最初用于机器视觉和图像压缩,一个图像金字是一系列以金字塔形状排列的、分辨率逐步降低的图像集合。如图下图所示,它包括了四层图像,将这一层一层的图像比喻成金字塔。图像金字塔可以通过梯次向下采样获得,直到达到某个终止条件才停止采样,在向下采样中,
层级越高,则图像越小
,分辨率越低。文章图片
生成图像金字塔主要包括两种方式:向下取样 和 向上取样。
如下图所示:
向下取样:将图像从G0转换为G1、G2、G3,图像分辨率不断降低的过程;
向上取样:将图像从G3转换为G2、G1、G0,图像分辨率不断增大的过程。
文章图片
2 向下取样——pyrDown() 2.1 基础理论
在图像向下取样中,一般分两步:
- (1)对图像Gi进行高斯卷积核(高斯滤波);
- (2)删除所有的偶数行和列。
文章图片
其中,高斯核卷积运算(高斯滤波) 就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值(权重不同)经过加权平均后得到。常见的 33 和 55 高斯核如下:
文章图片
注:由于每次向下取样会删除偶数行和列,所以它会不停地丢失图像的信息。2.2 代码示例
在OpenCV中,向下取样使用的函数为pyrDown(),其函数用法如下所示:
dst = pyrDown(src[, dst[, dstsize[, borderType]]])其中,参数:
src 表示输入图像;
dst 表示输出图像,和输入图像具有一样的尺寸和类型;
dstsize 表示输出图像的大小,默认值为Size();
borderType 表示像素外推方法,详见cv::bordertypes 。
取一次样:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取原始图像
img = cv2.imread('juzi.png')# 图像向下取样
r = cv2.pyrDown(img)# 显示图像
cv2.imshow('original', img)
cv2.imshow('PyrDown', r)cv2.waitKey()
cv2.destroyAllWindows()
文章图片
多次向下采样:
# -*-coding:utf-8 -*-
# @Author:到点了,心疼徐哥哥
# 奥利给干!!!
# -*- coding: utf-8 -*-
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt#读取原始图像
img=cv.imread('pinguo.png')#图像向下取样
r1=cv.pyrDown(img)
r2=cv.pyrDown(r1)
r3=cv.pyrDown(r2)#显示图像
cv.imshow('original',img)
cv.imshow('pyrDown1',r1)
cv.imshow('pyrDown2',r2)
cv.imshow('pyrDown3',r3)
cv.waitKey()
cv.destroyWindow()
文章图片
3 向上取样——pyrUp() 3.1 基础理论
在图像向上取样是由小图像不断放图像的过程。它将图像在每个方向上扩大为原图像的2倍,新增的行和列均用0来填充,并使用与“向下取样”相同的卷积核乘以4,再与放大后的图像进行卷积运算,以获得“新增像素”的新值。
文章图片
注:向上取样和向下取样无法互逆的。
3.2 代码示例
和上文中的向下取样其时并无大异。
在OpenCV中,向上取样使用 pyrUp() 函数,其函数用法如下所示:
dst = pyrUp(src[, dst[, dstsize[, borderType]]])
其中,参数:取一次样:
src 表示输入图像;
dst 表示输出图像,和输入图像具有一样的尺寸和类型;
dstsize 表示输出图像的大小,默认值为Size();
borderType 表示像素外推方法,详见cv::bordertypes 。
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt# 读取原始图像
img = cv2.imread('juzi.png')# 图像向下取样
r = cv2.pyrUp(img)# 显示图像
cv2.imshow('original', img)
cv2.imshow('PyrDown', r)cv2.waitKey()
cv2.destroyAllWindows()
文章图片
多次取样:
# -*-coding:utf-8 -*-
# @Author:到点了,心疼徐哥哥
# 奥利给干!!!
# -*- coding: utf-8 -*-
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt#读取原始图像
img=cv.imread('pinguo.png')#图像向下取样
r1=cv.pyrUp(img)
r2=cv.pyrUp(r1)
r3=cv.pyrUp(r2)#显示图像
cv.imshow('original',img)
cv.imshow('pyrDown1',r1)
cv.imshow('pyrDown2',r2)
cv.imshow('pyrDown3',r3)
cv.waitKey()
cv.destroyWindow()
4.图像融合 4.1理论代码:
# -*-coding:utf-8 -*-
# @Author:到点了,心疼徐哥哥
# 奥利给干!!!
# -*- coding: utf-8 -*-
from cv2 import cv2
import numpy as npA = cv2.imread('pinguo.png')
# 注意:为了使后面可以逐渐减半,这里的尺寸必须为2的次幂
A = cv2.resize(A, (256, 256), interpolation=cv2.INTER_CUBIC)
B = cv2.imread('juzi.png')
B = cv2.resize(B, (256, 256), interpolation=cv2.INTER_CUBIC)# 生成高斯金字塔
G = A.copy()
gpA = [G]
for i in range(5):
G = cv2.pyrDown(G)
gpA.append(G)G = B.copy()
gpB = [G]
for i in range(5):
G = cv2.pyrDown(G)
gpB.append(G)# 产生Laplacian金字塔
lpA = [gpA[5]]
for i in range(5, 0, -1):
GE = cv2.pyrUp(gpA[i])
L = cv2.subtract(gpA[i - 1], GE)
lpA.append(L)lpB = [gpB[5]]
for i in range(5, 0, -1):
GE = cv2.pyrUp(gpB[i])
L = cv2.subtract(gpB[i - 1], GE)
lpB.append(L)# 合并
LS = []
for la, lb in zip(lpA, lpB):
rows, cols, dpt = la.shape
ls = np.hstack((la[:, 0:cols // 2], lb[:, cols // 2:]))
LS.append(ls)# 重新构建图像
ls_ = LS[0]
for i in range(1, 6):
ls_ = cv2.pyrUp(ls_)
ls_ = cv2.add(ls_, LS[i])# 连接
real = np.hstack((A[:, :cols // 2], B[:, cols // 2:]))cv2.imshow("LS", ls_)
cv2.imshow("Real", real)cv2.waitKey()
cv2.destroyAllWindows()
4.2融合效果:
文章图片
往期文章推荐:
还看不懂Python OpenCV?不,我不允许!隔壁大爷都说看得懂!??环境配置+问题分析+视频图像入门??万字只为你~
Python OpenCV实战画图——这次一定能行!爆肝万字,建议点赞收藏~??????
??大家中秋节快乐??接下来请欣赏Python Opencv实战之图像阈值和模糊处理,万字实战,收藏起来吧~
Python OpenCV ??超级有趣?? 颜色转换 + 几何变换,一网打尽???~
【Dream的茶话会|Python OpenCV图像处理(??转换+梯度??边缘检测+图像融合,aplacian金字塔合成新物种)】 好啦,这就是今天要分享给大家的全部内容了
??????如果你喜欢的话,就不要吝惜你的一键三连了~
文章图片
文章图片
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量