改变颜色空间
对于颜色转换,我们使用cv函数。cvtColor(input_image, flag),其中flag决定转换的类型。
在HSV中比在BGR颜色空间中更容易表示颜色。
#打印所有cvtColor的flag
flags=[i for i in dir(cv) if i.startswith("COLOR_")]
print(flags)
注意:HSV中,色相取值范围0-179,饱和度和明度的值都是0-255
对象跟踪
cap=cv.VideoCapture(0)
while(1):
#获取帧
_,frame=cap.read()
#BGR颜色空间转换为HSV
hsv=cv.cvtColor(frame,cv.COLOR_BGR2HSV)
#设置紫色HSV读数范围
lower_purple=np.array([125,43,46])
upper_purple=np.array([155,255,255])
#只取紫色范围的像素
mask=cv.inRange(hsv,lower_purple,upper_purple)
#把范围加到获取的帧上
res=cv.bitwise_and(frame,frame,mask=mask)
#展示
cv.imshow("frame",frame)
cv.imshow("mask",mask)
cv.imshow("res",res)
k=cv.waitKey(0)
cv.destroyAllWindows()
查找颜色的hsv值,通过已知的GBR值,利用cv.cvtColor进行转换。
red=np.uint8([[[0,0,255]]])
hsv_red=cv.cvtColor(red,cv.COLOR_BGR2HSV)
print(hsv_red)
结果:[[[ 0 255 255]]]
一般把[H-10,100,100]作为下界,[H+10,255,255]作为上界。
跟踪多种颜色
cap=cv.VideoCapture(0)
while(1):
_,frame=cap.read()
hsv=cv.cvtColor(frame,cv.COLOR_BGR2HSV)
lower_purple=np.array([125,43,46])
upper_purple=np.array([155,255,255])
lower_green = np.array([50, 100, 100])
upper_green = np.array([70, 255, 255])
mask1=cv.inRange(hsv,lower_purple,upper_purple)
mask2=cv.inRange(hsv,lower_green,upper_green)
mask=mask1+mask2
res=cv.bitwise_and(frame,frame,mask=mask)
cv.imshow("frame",frame)
cv.imshow("mask",mask)
cv.imshow("res",res)
k=cv.waitKey(0)
cv.destroyAllWindows()
效果:(绿色范围不够大)
图像几何变换
缩放:
img=cv.imread("gy.jpg")
res=cv.resize(img,None,fx=1/2,fy=2,interpolation=cv.INTER_CUBIC)
cv.imshow("res",res)
cv.imshow("img",img)
cv.waitKey(0)
结果:
移动:
rows,cols,_=img.shape
#平移的距离,水平100像素,垂直50像素
M=np.float32([[1,0,100],[0,1,50]])
dst=cv.warpAffine(img,M,(cols,rows))
cv.imshow("remove",dst)
cv.waitKey(0)
结果:
旋转:
M=cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst=cv.warpAffine(img,M,(cols,rows))
仿射变换
#创建三个坐标
pts1=np.float32([[50,50],[200,50],[50,200]])
pts2=np.float32([[10,100],[200,50],[100,250]])
#仿射变换,从坐标pts1变换到pts2
M=cv.getAffineTransform(pts1,pts2)
dst=cv.warpAffine(img,M,(cols,rows))
透视变换:
#定义两个点集
pts1=np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2=np.float32([[0,0],[300,0],[0,300],[300,300]])
#透视变换从pts1到pts2
M=cv.getPerspectiveTransform(pts1,pts2)
dst=cv.warpPerspective(img,M,(300,300))
图像阈值
普通阈值
img=cv.imread("gy.jpg",0)
#(原图,阈值,最大值,阈值类型)
ret,thresh1=cv.threshold(img,127,255,cv.THRESH_BINARY)
ret,thresh2=cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
ret,thresh3=cv.threshold(img,127,255,cv.THRESH_TRUNC)
ret,thresh4=cv.threshold(img,127,255,cv.THRESH_TOZERO)
ret,thresh5=cv.threshold(img,127,255,cv.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()
自适应阈值
cv.ADAPTIVE_THRESH_MEAN_C::阈值是邻近区域的平均值减去常数C。
cv.ADAPTIVE_THRESH_GAUSSIAN_C:阈值是邻域值的高斯加权总和减去常数C。
img=cv.imread("text.jpg",0)
# 高斯滤波后再采用Otsu阈值,3*3卷积核
blur = cv.GaussianBlur(img,(3,3),0)
ret,th = cv.threshold(blur,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
plt.imshow(th,'gray')
plt.title("test"), plt.xticks([]), plt.yticks([])
plt.show()
图像平滑
图像过滤
和音频一样,图像也可以进行滤波。
LPF使图像更模糊
HPF使边缘更锐利
实际上是一个2维卷积核进行卷积操作
img=cv.imread("text.jpg")
#卷积核(DL里面叫过滤器filter)
kernel=np.ones((5,5),np.float32)/25
dst=cv.filter2D(img,-1,kernel)
plt.subplot(121),plt.imshow(img),plt.title("Original")
plt.subplot(122),plt.imshow(dst),plt.title("Averaging")
plt.show()
图像模糊
平均
用一个二维卷积核,对图像进行卷积,计算卷积内像素平均值,再将其他值用平均值代替。(PS.我还是喜欢叫它过滤器2333)
img=cv.imread("text.jpg")
#(图片,卷积核)
blur=cv.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title("Original")
plt.subplot(122),plt.imshow(blur),plt.title("Blured")
plt.show()
高斯模糊
高斯模糊多一个σ (sigma),同样是用卷积核对图像进行卷积,但是代替的是根据高斯函数计算的,偏移量sigma影响偏移量的值,模糊的地方就有微小差异。
img=cv.imread("text.jpg")
blur=cv.GaussianBlur(img,(9,9),0)
plt.subplot(121),plt.imshow(img),plt.title("Original")
plt.subplot(122),plt.imshow(blur),plt.title("Blured")
plt.show()
中位模糊
函数cv.medianBlur() 提取内核区域下所有像素的中值,并将中心元素替换为该中值。这对于消除图像中的椒盐噪声非常有效。有趣的是,在上述过滤器中,中心元素是新计算的值,该值可以是图像中的像素值或新值。但是在中值模糊中,中心元素总是被图像中的某些像素值代替。有效降低噪音。其内核大小应为正奇数整数。
img=cv.imread("text.jpg")
#(图片,卷积核)
blur=cv.medianBlur(img,9)
plt.subplot(121),plt.imshow(img),plt.title("Original")
plt.subplot(122),plt.imshow(blur),plt.title("Blured")
plt.show()
双边滤波
双边滤波采用两个高斯滤波器,不会像高斯滤波器那样把边缘模糊掉。所以它在过滤掉噪声的时候,也保留了锐利的边缘。
img=cv.imread("text.jpg")
blur=cv.bilateralFilter(img,15,100,100)
plt.subplot(121),plt.imshow(img),plt.title("Original")
plt.subplot(122),plt.imshow(blur),plt.title("Blured")
plt.show()