OpenCV学习<一>
二.图像处理
2.1灰度图和HSV 颜色空间
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('../photo/cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img_hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
cv2.imshow("img_gray",img_gray)
cv2.imshow("img_hsv",img_hsv)
while cv2.waitKey(0) != -1 :
cv2.destroyAllWindows()
cv2.imwrite('../save/cat_2_1_img_gray.jpg',img_gray)
cv2.imwrite('../save/cat_2_1_img_hsv.jpg', img_hsv)
break
2.1.1灰度图
相较于彩色图而言,使用灰度图最直接的原因就是减少计算量,包含色彩的图片,特征量,计算量会成指数倍数增加,比如一个点,灰度的话,就256个维度而已,但是如果算上RGB色彩的话,那就是1600万以上维度。
函数: cv.cvtColor(img,type)
作用:将图像从一个色彩空间转换为另一个色彩空间。
参数:img:处理的图像
type:转换的类型,灰度图为COLOR_BGR2GRAY
2.1.2HSV颜色空间
函数: cv.cvtColor(img,type)
作用:将图像从一个色彩空间转换为另一个色彩空间。
参数:img:处理的图像
type:转换的类型,HSV图为COLOR_BGR2HSV
在 HSV 颜色空间下,比 BGR 更容易跟踪某种颜色的物体,常用于分割指定颜色的物体。
HSV 表达彩色图像的方式由三个部分组成:
Hue(色调、色相)
Saturation(饱和度、色彩纯净度)
Value(明度)
用下面这个圆柱体来表示 HSV 颜色空间,圆柱体的横截面可以看做是一个极坐标系 ,H 用极坐标的极角表示,S 用极坐标的极轴长度表示,V 用圆柱中轴的高度表示。
Hue 用角度度量,取值范围为0~360°,表示色彩信息,即所处的光谱颜色的位置。,表示如下:
颜色圆环上所有的颜色都是光谱上的颜色,从红色开始按逆时针方向旋转,Hue=0 表示红色,Hue=120 表示绿色,Hue=240 表示蓝色等等。
在 GRB中 颜色由三个值共同决定,比如黄色为即 (255,255,0);在HSV中,黄色只由一个值决定,Hue=60即可。
HSV 圆柱体的半边横截面(Hue=60):
其中水平方向表示饱和度,饱和度表示颜色接近光谱色的程度。饱和度越高,说明颜色越深,越接近光谱色饱和度越低,说明颜色越浅,越接近白色。饱和度为0表示纯白色。取值范围为0~100%,值越大,颜色越饱和。
竖直方向表示明度,决定颜色空间中颜色的明暗程度,明度越高,表示颜色越明亮,范围是 0-100%。明度为0表示纯黑色(此时颜色最暗)。
可以通俗理解为:
在Hue一定的情况下,饱和度减小,就是往光谱色中添加白色,光谱色所占的比例也在减小,饱和度减为0,表示光谱色所占的比例为零,导致整个颜色呈现白色。
明度减小,就是往光谱色中添加黑色,光谱色所占的比例也在减小,明度减为0,表示光谱色所占的比例为零,导致整个颜色呈现黑色。
2.2图像阈值处理和图像平滑处理
import cv2
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('../photo/cat.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
img_hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
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()
2.2.1图像阈值处理
函数: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的反转
2.2.2图像平滑处理
2.2.2.1均值滤波
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../photo/lenaNoise.png')
img_blur = cv2.blur(img,(3,3))
cv2.imshow('img', img)
cv2.imshow('img_blur', img_blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数:result = cv2.blur(src,ksize)
作用:使用规范化框滤镜模糊图像。该函数使用内核平滑图像,实际上就是模糊处理图像
参数:src:处理的图像
ksize:表示核大小。核必须是大于1的奇数,如3、5、7等。
均值滤波是指任意一点的像素值,都是周围
个像素值的均值。例如下图中,红色点的像素值是其周围蓝色背景区域像素值之和除25,25=5x5 是蓝色区域的大小。
均值滤波详细的计算方法如下图所示:
其中5x5的矩阵称为核,针对原始图像内的像素点,采用核进行处理,得到结果图像,如下图所示:
提取 1/25 可以将核转换为如下形式:
2.2.2.2中值滤波
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../photo/lenaNoise.png')
img_medianBlur = cv2.medianBlur(img,3)
cv2.imshow('img', img)
cv2.imshow('img_medianBlur', img_medianBlur)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数:dst = cv2.medianBlur(src,ksize)
作用:使用规范化框滤镜模糊图像。该函数使用内核平滑图像,实际上就是模糊处理图像
参数:src :表示源图像;
ksize :表示核大小。核必须是大于1的奇数,如3、5、7等。
在使用邻域平均法去噪的同时也使得边界变得模糊。而中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。选一个含有奇数点的窗口
,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。计算过程如下图所示:
2.2.2.3高斯滤波
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../photo/lenaNoise.png')
img_GaussianBlur = cv2.GaussianBlur(img,(3,3),0)
cv2.imshow('img', img)
cv2.imshow('img_GaussianBlur', img_GaussianBlur)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数:dst = cv2.GaussianBlur(src, ksize, sigmaX)
作用:使用规范化框滤镜模糊图像。该函数使用内核平滑图像,实际上就是模糊处理图像
参数:
src: 表示原始图像;
ksize: 表示核大小;
sigmaX: 表示X方向方差。直接赋值0即可
注:核大小(N, N)必须是奇数,X方向方差主要控制权重。
1)核大小为 3x3
2)核大小为 5x5
为了克服简单局部平均法的弊端(图像模糊),目前已提出许多保持边缘、细节的局部平滑算法。它们的出发点都集中在如何选择邻域的大小、形状和方向、参数加平均及邻域各店的权重系数等。
图像高斯平滑也是邻域平均的思想对图像进行平滑的一种方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。高斯平滑与简单平滑不同,它在对邻域内像素进行平均时,给予不同位置的像素不同的权值,下图的所示的 3x3 和 5x5 邻域的高斯模板。
(1)核大小为 3x3
(1)核大小为 5x5
高斯滤波让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值。如下图所示,中心位置权重最高为0.4。
2.2.2.4方框滤波
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../photo/lenaNoise.png')
img_boxFilter = cv2.boxFilter(img,-1,(3,3),1)
cv2.imshow('img', img)
cv2.imshow('img_boxFilter', img_boxFilter)
cv2.waitKey(0)
cv2.destroyAllWindows()
函数:dst = cv2.boxFilter( src, ddepth, ksize, anchor, normalize, borderType )
作用:使用规范化框滤镜模糊图像。该函数使用内核平滑图像,实际上就是模糊处理图像
参数:
dst:返回值,表示经过方框滤波处理后的结果。
src:需要被处理的图像,即原始图像。它能够有任意数量的通道,并能对各个通道独立处理。图像深度可以是 CV_8U、 CV_16U、CV_16S、CV_32F 或者 CV_64F 中的一种。
ddepth:处理后结果图像的深度,一般使用-1表示与原始图像使用相同的图像深度。
ksize:滤波核的大小。滤波核大小是指在滤波处理过程中所选择的邻域图像的高度和宽度。例如,滤波核的值可以为(3,3),表示以3×3大小的邻域均值作为图像均值滤波处理的结果,如下图2-1所示。
图2-1 3×3大小的滤波核
anchor:锚点,默认值为(-1, -1),表示当前计算均值的点位于核的中心点位置。该值使用默认值即可,在特殊情况下可以指定不同的点作为锚点。
normalize:表示在滤波时是否进行归一化(这里指将计算结果规范化为当前像素值范围内的值)处理,该参数是一个逻辑值,可能为真(值为 1)或假(值为 0)
当参数normalize=0时,表示不需要进行归一化处理,直接使用邻域像素值的和。
当参数normalize=1时,表示要进行归一化处理,要用邻域像素值的和除以面积。
与均值滤波不同的是,方框滤波不会计算像素的均值。在均值滤波中,滤波结果的像素值是任意一个点的邻域平均值,等于各邻域像素值之和除以邻域面积。而在方框滤波中,可以自由选择是否对均值滤波的结果进行归一化,即可以自由选择滤波结果是邻域像素值之和的平均值,还是邻域像素值之和。
以5×5的邻域为例,在进行方框滤波时,如果计算的是邻域像素值的均值,则滤波关系如图1-1所示;如果计算的是邻域像素值之和,则滤波关系如图1-2所示。
图1-1 方框滤波关系示例–计算邻域像素值均值
图1-2 方框滤波关系示例–计算邻域像素值之和
根据上述关系,如果计算的是领域像素值的均值,则使用的卷积核如图1-3所示
图1-3 计算邻域像素值均值所用的卷积核示例
如果计算的是邻域像素值之和,则使用的卷积核如图1-4所示:
图1-4 计算邻域像素值之和所用的卷积核示例