图像金字塔是图像中多尺度表达的一种,最主要用于图像的分割,是一种以多分辨率来解释图像的有效且概念简单的结构。简单来说,图像金字塔是同一图像不同分辨率的子图集合(有800×800、480×640…)
图像金字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐渐降低、且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。
金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低
高斯金字塔固定了缩放比,即如果你是800×800的图,无法缩放成500×500
我们将要学习用什么方法,如何去生成这些图像金字塔
常见两类图像金字塔:
高斯金字塔是通过高斯平滑和亚采样(一个图形中取出一小块)获得的一系列下采样图像
原理非常简单:如下图所示
原始图像分辨率M*N
——> 处理图像后分辨率M/2 * N/2
;即每次处理后,结果是原来的1/4(不要求是偶数,会自动四舍五入)
注意:向下采样(分辨率减小,在上图中表现为方向向上
)会丢失信息
关键API:cv2.pyrDown(src[, dst[, dstsize[, borderType]]])
其中:
src
:需要操作的图片dst
:返回值,不用写,我们用一个参数接受即可dstsize
:返回图片的大小# 高斯金字塔 ——> 向下采样
import cv2
import numpy as np
img = cv2.imread('./lena.png')
# 分辨率减小的操作:下采样
dst = cv2.pyrDown(img)
# 还可再变化多次
dst2 = cv2.pyrDown(dst)
# 展示
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.imshow('dst2',dst2)
cv2.waitKey(0)
cv2.destroyAllWindows()
其实清晰度几乎没变,这就是图像金字塔的厉害之处:虽然丢掉了偶数行和偶数列,但是经过了高斯核函数卷积后,相当于把一个像素点匀到周围了,因此变化不大
操作和向下采样一样!
关键API:cv2.pyrUp(src[, dst[, dstsize[, borderType]]])
其中:
src
:需要操作的图片dst
:返回值,不用写,我们用一个参数接受即可dstsize
:返回图片的大小# 高斯金字塔 ——> 向上采样
import cv2
import numpy as np
img = cv2.imread('./Hello.jpeg')
# 分辨率减小的操作:下采样
dst = cv2.pyrUp(img)
# 还可再变化多次
# dst2 = cv2.pyrUp(dst)
# 展示
cv2.imshow('img',img)
cv2.imshow('dst',dst)
# cv2.imshow('dst2',dst2)
cv2.waitKey(0)
cv2.destroyAllWindows()
拉普拉斯金字塔图像 = 原始图像 - 上采操作函数(下采操作函数(原始图像))
将降采样之后的图像在进行上采样操作,然后与之前还没降采样的原图进行做差得到残差图!为还原图像做信息的准备!
也就是说,拉普拉斯金字塔是通用原图像减去先缩小后再放大的图像(高斯金字塔) 的一系列图像构成的,减去后得到的结果就是拉普拉斯金字塔的图像。保留的是残差!
拉普拉斯金字塔是由高斯金字塔构成的,没有专门的函数
# 拉普拉斯金字塔
# 原图 - 先缩小再放大的图(这样才能变回原图大小,方便做差)
import cv2
import numpy as np
img = cv2.imread('./lena.png')
# 先缩小
temp = cv2.pyrDown(img)
# 再放大
dst = cv2.pyrUp(temp)
# 原图 和 高斯金字塔 的差就是 拉普拉斯金字塔
lap0 = img - dst
# 展示
# cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.imshow('lap0',lap0)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
在统计学中,直方图是一种对数据分布情况的图形表示,是一种二维统计图表
图像直方图是用于表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。
可以借助观察该直方图了解需要如何调整亮度分布的直方图。这种直方图中,横坐标的左侧为纯黑、较暗的区域,而右侧为较亮、纯白的区域。
因此,一张较暗图片的图像直方图的数据多集中于左侧和中间部分,而整体明亮,只有少量阴影的图像则相反
我们从图像直方图可以看出:该幅图像存在较多很暗或者很亮的点(具有这些灰度级的像素个数较多),反而亮暗平衡的点较少**(具有这些灰度级的像素个数较少)**
看懂了之后我们就可以自主分析下面三张图啦(懒得写了…)
举个:
有个3×3的图片,其中
归一化图:
range
:我们统计灰度值的范围,一般为0-255
总的来说:直方图就是图像中各种灰度级出现的次数而画出的图
OpenCV
统计直方图关键API:cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
images
:原始图像(可以不是黑白图),加s
表示可以同时对多张图片进行直方图统计 ——> 此处要加中括号,表示是一个图像集合channels
:指定通道,需要用中括号"[ ]
"括起来
[0]
[ 0 ], [ 1 ], [ 2 ]
,分别对应B,G,Rmask
:掩码图像
None
histSize
:BINS
(柱状图中的柱子)的数量
[256]
(因为是从0开始,因此有256个数字)ranges
:像素值范围,例如[0,255]
accumulate
:累积标识
False
(一般我们只操作一个图)True
,则直方图在开始分配时不会被清零plt.plot(返回值)
进行绘图!# OpenCV统计直方图
import cv2
import numpy as np
img = cv2.imread('./lena.png')
hist = cv2.calcHist([img],[0],None,[256],[0,255])
print(hist)
OpenCV
绘制直方图# 绘制直方图
# 使用Opencv的统计方法
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./lena.png')
# 统计直方图数据,不用再去做灰度图(参数channels可以对通道进行统计)
hist_B = cv2.calcHist([img],[0],None,[256],[0,255])
hist_G = cv2.calcHist([img],[1],None,[256],[0,255])
hist_R = cv2.calcHist([img],[2],None,[256],[0,255])
# 上方得到三个数据,我们对应地画三个图,标注不同的颜色
plt.plot(hist_B,color = 'b',label = 'Blue') # 不用再用hist(),因为返回的本来就是直方图数据
plt.plot(hist_G,color = 'g',label = 'Green')
plt.plot(hist_R,color = 'r',label = 'Red')
plt.legend() # 在轴上放说明
# 展示(加不加都行)
plt.show()
结果:
对应横轴是灰度值转化来的(我们没有给定横轴的值,matplotlib自动索引的,相当于 cv2.cvtColor(img,cv2.COLOR_GRAY2BRR)
)
我们可以发现:整个图都是偏红色(红色低频较少,在高频区较多),蓝色在偏低的位置(只有帽子上有一点),绿色在高频区较少(整幅图几乎没有绿色)
如果你只对图片中的某一部分感兴趣(例如图像中的人脸、手…),就可以用掩膜进行操作,选出图中的roi区域
,对该区域使用cv2.calcHist(mask)
进行直方图计算
img.shape
)的全黑图片:mask = np.zeros(image.shape,np.uint8)
mask[100:200,200:300] = 355
# 使用掩膜的直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./lena.png')
# 变成黑白的图
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 生成掩膜图像
mask = np.zeros(gray.shape,np.uint8) # 生成和原图大小一样的全黑图 uint8:8位全部用来表示数字
# 设置想要统计直方图的区域(roi)
mask[200:400,200:400] = 255
# 统计直方图数据 ——> 拿原图和进行掩膜操作后的数据进行对比
hist_gray = cv2.calcHist([gray],[0],None,[256],[0,255])
hist_mask = cv2.calcHist([gray],[0],mask,[256],[0,255])
# 使用matplotlib画出直方图
plt.plot(hist_gray,label = 'gray',color = 'g')
plt.plot(hist_mask,label = 'mask',color = 'r')
plt.legend()
plt.show()
##---------------------------------------------------------------------------------------------
# 我们想提前看一下掩膜在图片中的作用效果
cv2.imshow('gray',gray)
cv2.imshow('mask',mask)
# gray 和 gray 与运算的结果还是本身 mask的作用:前面先做与运算,结果再和mask做与运算
# 与运算的特点:两个数相“与”,0与任何数都是0,255和非0的“与”都是非0本身(原图)
cv2.imshow('gray&mask',cv2.bitwise_and(gray,gray,mask = mask))
##---------------------------------------------------------------------------------------------
# 退出条件
cv2.waitKey(0)
cv2.destroyAllWindows()