色彩空间也称色彩模型、颜色空间、色彩模型等,它是图像在计算机内部的一种存储方式,常见的色彩空间包括RGB、GRAY、XYZ、YCrCb、HSV。每种色彩空间都有其擅长的问题解决领域,所以在解决具体色彩问题时往往需要进行色彩空间类型转换。
基本格式:
dst=cv2.cvtColor(src,code[,dstCn])
转换后的图像=cv2.cvtColor(原图,色彩空间类型转换码 [,目标图像的通道数 该项可不写])
色彩空间转换代码:
import cv2
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('BGR',img)
img2=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
cv2.imshow('GRAY',img2)
cv2.waitKey(0)
RGB色彩空间转换
GRAY色彩空间转换
YCrCb色彩空间转换
Y:亮度 Cr:红色 Cb:蓝色
HSV色彩空间转换
H:色调 S:饱和度 V:亮度
几何变换是指对图像执行放大、缩小、旋转等各种操作
缩小
基本格式:
dst=cv2.resize(src,dsize[,dst[,fx[,fy[,interpolation]]]])
dsize表示转换后的图像大小
fx表示水平方向的缩放比例
fy表示垂直方向的缩放比例
注意点:
例子:
import cv2
img=cv2.imread('E:\pictures\\3.jpg')
sc=[1,0.2,0.5,1.5,2] //自己设置的缩放比例存入列表中
cv2.imshow('show',img)
while True:
key=cv2.waitKey()
if 48<= key <=52: //ascii,0,1,2,3,4
x=y=sc[key-48] //列表下表取值
img2=cv2.resize(img,None,fx=x,fy=y)
cv2.imshow('show2',img2)
dst=cv2.flip(src,flipCode)
flipCode表示翻转类型,为0时绕X轴旋转,大于0时绕y轴旋转,小于0时绕x轴和y轴旋转
import cv2
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
while True:
key=cv2.waitKey()
if key==48:
img2=img
elif key==49:
img2=cv2.flip(img,0)
elif key==50:
img2=cv2.flip(img,1)
elif key==51:
img2=cv2.flip(img,-1)
cv2.imshow('flip',img2)
放射变换包含了平移、旋转、缩放等操作,是一种二维坐标到二维坐标之间的线性变换。
这四小结调用的函数都一样,只是转换矩阵不同
主要特点:原图像中的所有平行线在转换后的图像中仍然平行
OpenCV的cv2.warpAffine()函数用于实现图像的仿射变换,基本格式如下:
dst=cv2.warpAffine(src,M,dsize)
src:原图
M:矩阵
dsize:转换后的图像大小
省略可选参数时,图像转换的矩阵运算公式如下:
dst(x,y)=src(M11X + M12y + M13 , M21x + M22y + M23)
平移
平移是指图像沿水平或者垂直方向移动一定的像素。假设将图像水平移动m个像素,垂直移动n个像素
转换矩阵M如下:
M=| 1 0 m |
| 0 1 n |
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
height=img.shape[0]
width=img.shape[1]
dsize=(width,height)
m=np.float32([[1,0,100],[0,1,50]]) //M矩阵
img2=cv2.warpAffine(img,m,dsize) //调用函数
cv2.imshow('show2',img2)
cv2.waitKey(0)
缩放
宽度缩放比例为h,高度缩放比例为v
根据图像转换的矩阵运算公式可以得出执行缩放的转换矩阵M
M=| h 0 0 |
| 0 v 0 |
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
height=img.shape[0]
width=img.shape[1]
dsize=(width,height)
m=np.float32([[0.5,0,0],[0,0.5,0]])
img2=cv2.warpAffine(img,m,dsize)
cv2.imshow('show2',img2)
cv2.waitKey(0)
旋转
cv2.getRotationMatrix2D() 函数可用于计算执行旋转操作的旋转矩阵,基本格式如下
m=cv2.getRotationMatrix2D(center , angle , scale)
center表示原图像中作为旋转中心的坐标
angle表示旋转角度,正数表示按逆时针旋转,负数表示按顺时针旋转
scale表示目标图像与原图像的大小比例
比如:将图像中心作为旋转中心顺时针旋转60度,并将图像缩小50度,对应计算转换矩阵的语句如下
m=cv2.getRotationMatrix2D((width/2,height/2),-60,0.5)
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
height=img.shape[0]
width=img.shape[1]
dsize=(width,height)
m=cv2.getRotationMatrix2D((width/2,height/2),-60,0.5)
img2=cv2.warpAffine(img,m,dsize)
cv2.imshow('show2',img2)
cv2.waitKey(0)
三点映射变换
三点映射变换会将图像转换为任意的平行四边形,cv2.getAffineTransform()函数用来计算转换矩阵
m=cv2.getAffineTransform(src,dst)
src为原图像中3个点的坐标 (分别为左上,右上,左下)
dst为原图像中3个点在目标图像中对应坐标
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
height=img.shape[0]
width=img.shape[1]
dsize=(width,height)
src=np.float32([[0,0],[width-20,0],[0,height-1]])
dst=np.float32([[60,60],[width-100,80],[100,height-120]])
m=cv2.getAffineTransform(src,dst)
img2=cv2.warpAffine(img,m,dsize)
cv2.imshow('show2',img2)
cv2.waitKey(0)
透视变换会将图像转换为任意的四边形
它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x’,y’)空间的映射
变换之前的点是z值为1的点,它三维平面上的值是x,y,1,在二维平面上的投影是x,y,通过矩阵变换成三维中的点X,Y,Z,再通过除以三维中Z轴的值,转换成二维中的点x’,y’.
主要特点:原始图像中的所有直线在转换后的图像中仍然是直线
仿射变换后平行四边形的各边仍操持平行,透视变换结果允许是梯形等四边形
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\5.jpg')
cv2.imshow('show',img)
height=img.shape[0]
width=img.shape[1]
dsize=(width,height)
src=np.float32([[20,368],[450,105],[1294,198],[1233,721]])
dst=np.float32([[420,0],[955,0],[955,760],[420,760]])
m=cv2.getPerspectiveTransform(src,dst)
img2=cv2.warpPerspective(img,m,dsize)
cv2.imshow('show2',img2)
cv2.waitKey(0)
图像模糊也称图像平滑处理,主要处理图像中与周围差异较大的点,将其像素值调整为与周围点像素值近似的值,目的主要是消除图像噪音和边缘
均值滤波是以当前点为中心,用其周围N*N个点像素值的平均值来替代当前点的像素值
用于计算平均值的N*N个点成为邻域,用于滤波计算的卷积核大小与邻域相同
可以平滑图像,速度较快,算法简单。但是无法去掉噪声,只能微弱的减弱它。
卷积核:在图像处理时分配给像素邻域的空间权重的方阵
用于实现均值滤波的函数的基本格式:
dst=cv2.blur(src,ksize[,anchor[,borderType]])
ksize为卷积核大小,表示为(width,height),通常长和高一样,且为正奇数
anchor为锚点,默认值为(-1,-1),表示锚点位于卷积核中心
borderType为边界值处理方式
例子:
import cv2
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
img2=cv2.blur(img,(3,3))
cv2.imshow('show2',img2)
cv2.waitKey(0)
它是按像素点与中心点的不同距离,赋予像素点不同的权重值,越靠近中心点权重值越大,反之越小,根据权重值计算邻域内所有像素点的和,将其作为中心点的像素值。
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。
用于实现高斯滤波的函数的基本格式如下:
dst=cv2.GussianBlur(src,ksize,sigmaX[,sigmaY[,borderType]])
sigmaX为水平方向上的权重值
sigmaY为垂直方向上的权重值
如果sigmaY为0,则令其等于sigmaX;
如果sigmaX和sigmaY均为0,则按照公式计算,width和height为ksize的
sigmaX=0.3*((width-1)*0.5-1)+0.8
sigmaY=0.3*((height-1)*0.5-1)+0.8
import cv2
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
img2=cv2.GaussianBlur(img,(5,5),0,0)
cv2.imshow('show2',img2)
cv2.waitKey(0)
以均值滤波为基础,可以选择是否对滤波结果进行归一化
如果进行归一化,则滤波结果为邻域内点的像素值之和的平均值,否则滤波结果为像素值之和。
用于实现方框滤波的的boxFilter()函数的基本格式如下:
dst=cv2.boxFilter(src,ddepth,ksize[,anchor[,normalize[,borderType]]])
ddepth为目标图像的深度,一般使用-1表示与原图像的深度一致
normalize为True时进行归一化(默认的),为False不进行
import cv2
img=cv2.imread('E:\pictures\\3.jpg')
cv2.imshow('show',img)
img2=cv2.boxFilter(img,-1,(3,3),normalize=False)
img3=cv2.boxFilter(img,-1,(3,3),normalize=True)
img4=cv2.boxFilter(img,-1,(11,11),normalize=False)
cv2.imshow('show2',img2)
cv2.imshow('show3',img3)
cv2.imshow('show4',img4)
cv2.waitKey(0)
未归一化滤波结果得到的像素值可能会超过允许的最大值,从而被截断为最大值。
中值滤波将邻域内的所有像素值排序,取中间值作为邻域中心点的像素值。非常适合消除椒盐噪声
实现中值滤波的medianBlur函数基本格式如下:
dst - cv2.madianBlur(src,ksize)
ksize为卷积核大小,不同于之前的卷积核大小为(width,height),他的大小不是坐标形式
import cv2
img=cv2.imread('E:\pictures\\1.png')
cv2.imshow('show',img)
img2=cv2.medianBlur(img,3)
cv2.imshow('show2',img2)
cv2.waitKey(0)
双边滤波在计算像素值的同事会考虑距离和色差信息, 上面的几个滤波器,都将边缘平化掉了,为了防止这个现象,可以用双边滤波器。它是一种保边去噪的滤波器从而可在消除噪声的同时保护边缘信息。
如果像素点与当前点色差较小,赋予其较大的权重,否则赋予其较小的权重。
图像边缘等强度梯度较大的地方,可以保持梯度。
用于实现双边滤波的bilateralFilter()函数基本格式如下:
dst=cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace[,borderType])
d表示以当前点为中心的邻域的直径,一般为5
sigmaColor为双边滤波选择的色差范围
sigmaSpace为空间坐标中sigma值,值越大表示越多的像素点参与滤波计算。当d>0时忽略sigmaSpace,由d决定
邻域大小,否则d由sigmaSpace计算得出,与sigmaSpace成比例
import cv2
img=cv2.imread('E:\pictures\\1.png')
cv2.imshow('show',img)
img2=cv2.bilateralFilter(img,20,500,500)
cv2.imshow('show2',img2)
cv2.waitKey(0)
以上的滤波可以通过参数来确定卷积核,2D卷积可使用自定义的卷积核来执行滤波操作
用于实现2D卷积的filter2D()函数的基本格式如下:
dst=cv2.filter2D(src,ddepth,kernel[,anchor[,delta[,borderType]]])
ddepth表示目标图像dst的深度,一般使用-1表示与原图像src一致
kernel为单通道卷积核(一维数组)
anchor为图像处理的锚点
delta为修正值,未省略时,将加上该值作为最终的滤波结果
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\1.png')
k1=np.array([[3,3,3,3,3],[3,9,9,9,3],[3,11,12,13,3],[3,8,8,8,3],[3,3,3,3,3]])/25
k2=np.ones((5,5),np.float32)/25
cv2.imshow('show',img)
img2=cv2.filter2D(img,-1,k1)
cv2.imshow('show2',img2)
img2=cv2.filter2D(img,-1,k2)
cv2.imshow('show3',img2)
cv2.waitKey(0)
第二,三张图均为自定义的卷积核,第三张的图定义的和卷积核大小为5*5时均值滤波的卷积核一样
阈值处理用于剔除图像中像素值高于或低于指定值的像素点
全局阈值处理是指将大于阈值的像素值设置为255,将其他像素值设置为0;或者将大于阈值的像素值设置为0,将其他像素值设置为255
例如:
实现全局阈值处理的threshold()函数的基本格式如下:
retval,dst=cv2.threshold(src,thresh,maxval,type)
retval为返回的阈值
thresh为设置的阈值
maxval是阈值类型为THRESH_BINARY和THRESH_BINARY_INV时使用的最大值
type为阈值类型
二值化阈值处理
type的参数值为cv2.THRESH_BINARY。将大于阈值的像素值设置为255,将其他像素值设置为0。
import cv2
img=cv2.imread('E:\pictures\\4.jpg')
cv2.imshow('show',img)
ret,img2=cv2.threshold(img,150,255,cv2.THRESH_BINARY)
cv2.imshow('show2',img2)
cv2.waitKey(0)
反二值化阈值处理
type的参数值为cv2.THRESH_BINARY_INV。将大于阈值的像素值设置为0,将其他像素值设置为255。
import cv2
img=cv2.imread('E:\pictures\\4.jpg')
cv2.imshow('show',img)
ret,img2=cv2.threshold(img,150,255,cv2.THRESH_BINARY_INV)
cv2.imshow('show2',img2)
cv2.waitKey(0)
截断阈值处理
type的参数值为cv2.THRESH_TRUNC。将大于阈值的像素值设置为阈值,其他像素值不变。
超阈值零处理
type的参数值为cv2.THRESH_TOZERO。将大于阈值的像素值设置为0,其他像素值不变。
import cv2
img=cv2.imread('E:\pictures\\4.jpg')
cv2.imshow('show',img)
ret,img2=cv2.threshold(img,155,255,cv2.THRESH_TOZERO)
cv2.imshow('show2',img2)
cv2.waitKey(0)
低阈值零处理
type的参数值为cv2.THRESH_TOZERO_INV。将小于阈值的像素值设置为0,其他像素值不变。
import cv2
img=cv2.imread('E:\pictures\\4.jpg')
cv2.imshow('show',img)
ret,img2=cv2.threshold(img,155,255,cv2.THRESH_TOZERO_INV)
cv2.imshow('show2',img2)
cv2.waitKey(0)
Otsu算法阈值处理
对于色彩不均衡的图像,Otus算法阈值处理方式更好,它会遍历当前图像的所有阈值,再选择最佳阈值。
cv2.threshold()函数通过在阈值类型参数后面加上cv2.THRESH_OTSU来实现Otsu算法阈值处理
import cv2
img=cv2.imread('E:\pictures\\4.jpg',cv2.IMREAD_GRAYSCALE) //要注意先转换为单通道灰度图像
cv2.imshow('show',img)
ret,img2=cv2.threshold(img,155,255,cv2.THRESH_BINARY)
cv2.imshow('show2',img2)
ret,img3=cv2.threshold(img,155,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imshow('show3',img3)
cv2.waitKey(0)
三角算法阈值处理
cv2.threshold()函数通过在阈值类型参数后面加上cv2.THRESH_TRIANGLE来实现三角算法阈值处理
import cv2
img=cv2.imread('E:\pictures\\4.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('show',img)
ret,img2=cv2.threshold(img,155,255,cv2.THRESH_BINARY)
cv2.imshow('show2',img2)
ret,img3=cv2.threshold(img,155,255,cv2.THRESH_BINARY+cv2.THRESH_TRIANGLE)
cv2.imshow('show3',img3)
cv2.waitKey(0)
自适应阈值处理
也称局部阈值处理,他通过计算每个像素点邻域的加权平均值来确定阈值,并用该阈值处理当前像素点
用于实现自适应阈值处理的adaptiveThreshold()函数基本格式如下:
dst=cv2.adaptiveThreshold(src,maxValue,adaptiveMethod,thresholdType,blockSize,C)
maxValue为最大值
adaptiveMethod为自适应方法
thresholdType为阈值处理方式
blockSize为计算局部阈值的邻域的大小
C为常量,自适应阈值为blockSize指定邻域的加权平均值减去C
import cv2
img=cv2.imread('E:\pictures\\12.jpg',cv2.IMREAD_GRAYSCALE)
cv2.imshow('show',img)
img2=cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,5,10)
cv2.imshow('show2',img2)
cv2.waitKey(0)
相比于前面的全局阈值处理,全局阈值处理适用于色彩均衡的图像,自适应阈值处理则使用于明暗差异较大的图片。
对比如下:
形态变换主要用于二值图像的形状操作,形态变换的实现原理基于数字形态学。数学形态学也称形态学,它主要从图像内部提取信息来描述图像形态
形态变换主要包括腐蚀、膨胀和高级形态操作
形态操作会使用一个内核(结构元)遍历图像,根据内核和图像的位置关系决定内核中心对应的图像像素点的输出结果。内核可以是自定义的矩阵(Numpy数组),也可以是cv2.getStructuringElement函数返回的矩阵
腐蚀操作遍历图像时,会根据内核和图像的位置决定内核中心对应的图像像素点的输出结果。
当内核部分或全部处于前景之外时,内核中心对应单元格的值设置为0
只有内核完全处于前景内部时,内核中心对应单元格的值才设置为1
用于实现腐蚀操作的cv2.erode()函数的基本格式如下:
dst=cv2.erode(src,kernel[,anchor[,iteration[,borderType[,borderValue]]]])
kernel为内核
anchor为锚点,默认值为(-1,-1),表示锚点为内核中心
iterations为腐蚀操作的迭代次数
borderType为边界类型,默认值为BORDER_CONSTANT
borderValue为边界值,一般由OpenCV自动确定
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\5.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
img2=cv2.erode(img,kernel,iterations=1)
cv2.imshow('show2',img2)
cv2.waitKey(0)
膨胀操作与腐蚀操作刚好相反,它对图像的边界进行扩张
执行遍历操作时,只有在内核完全处于前景外部时,内核中心对应像素点的值才设置为0,否则设置为1
用于实现膨胀操作的cv2.dilate()函数的基本格式如下:
dst=cv2.dilate(src,kernel[,anchor[,iterations[,borderType[,borderValue]]]])
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\6.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
img2=cv2.dilate(img,kernel,iterations=1)
cv2.imshow('show2',img2)
cv2.waitKey(0)
高级形态操作基于腐蚀和膨胀操作,包括开运算、闭运算、形态学梯度运算、黑猫运算、礼帽运算等
用于实现形态学操作的cv2.morphologyEx()函数的基本格式如下:
dst=cv2.morphologyEx(src,op,kernel[,anchor[,iterations[,borderType[,borderValue]]]])
op为形态操作类型
开运算
先对图像进行腐蚀操作再对结果执行膨胀操作
op参数值为cv2.MORPH_OPEN时执行开运算
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\10.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
op=cv2.MORPH_OPEN
img2=cv2.morphologyEx(img,op,kernel,iterations=5)
cv2.imshow('show2',img2)
cv2.waitKey(0)
闭运算
与开运算相反,先进行膨胀操作,再对结果执行腐蚀操作
op参数值为cv2.MORPH_CLOSE时执行闭运算
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\10.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
op=cv2.MORPH_CLOSE
img2=cv2.morphologyEx(img,op,kernel,iterations=3)
cv2.imshow('show2',img2)
cv2.waitKey(0)
形态学梯度运算
原理是用图像的膨胀操作结果减去腐蚀操作结果
op参数值为cv2.MORPH_GRADIENT时执行形态学梯度运算操作
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\10.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
op=cv2.MORPH_GRADIENT
img2=cv2.morphologyEx(img,op,kernel,iterations=1)
cv2.imshow('show2',img2)
cv2.waitKey(0)
黑帽运算
原理是用图像的闭运算结果减去原图像
op参数值为cv2.MORPH_BLACKHAT时执行形态学的黑帽运算操作
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\10.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
op=cv2.MORPH_BLACKHAT
img2=cv2.morphologyEx(img,op,kernel,iterations=5)
cv2.imshow('show2',img2)
cv2.waitKey(0)
礼帽运算
原理是用原图像减去图像的开运算结果
op参数值为cv2.MORPH_TOPHAT时执行形态学的礼帽运算操作
import cv2
import numpy as np
img=cv2.imread('E:\pictures\\10.png')
cv2.imshow('show',img)
kernel=np.ones((5,5),np.uint8)
op=cv2.MORPH_TOPHAT
img2=cv2.morphologyEx(img,op,kernel,iterations=5)
cv2.imshow('show2',img2)
cv2.waitKey(0)