前言
本章内容都是和图像处理相关的,学习颜色空间的变换,几何变换,图像平滑,形态学变换,边缘检测,轮廓检测等知识。
正文
1、 颜色空间转换
OpenCV中有数百种关于不同颜色空间之间的转换的方法。当前计算机视觉中有三种常用的色彩空间:灰度、BGR以及HSV;
.灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理特别有效,例如人脸检测
.BGR,即蓝-绿-红色彩空间,每一个像素点都由一个三元数组表示,分别代表蓝、绿、红三种颜色。
.HSV,H(Hue)是色调,S(Saturation)是饱和度,V(Value)表示黑暗的程度。
在诸多方法中常用的就两种:BGR和Gray之间,BRG和HSV之间。用到的函数是cv2.cvtColor(inputimg,flag).其中flag就是转换类型。对于BRG到Gray的转换,flag为cv2.COLOR_BGR2GRAY;对于BGR到HSV的转换,flag为cv2.COLOR_BGR2HSV。
注意:在OpenCV的HSV格式中,H(色彩/色度)的取值范围是[0,179],S(饱和度)的取值范围[0,255],V(亮度)的范围是[0,255],但是不同的软件使用的值可能不同,需要对比归一化;
下面看一个关于物体跟踪的例子:
将图像转换到HSV,可以利用这一点来提取带有某个特定颜色的物体。在HSV颜色空间要比在BGR空间中更容易表示一个特定的颜色。例如我们要提取一个蓝颜色的物体,有一下几个步骤:
1.从视频中获取每一帧图像
2.将图像转换到HSV空间
3.设置HSV阈值到蓝色范围
4.获取蓝色物体,比如在蓝色物体周围画个圈。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
ret, frame = cap.read()# 获取每一帧
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)# 转换到HSV
lower_blue = np.array([110,50,50])# 设定蓝色的阈值
upper_blue = np.array([130,255,255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)# 根据阈值构建掩模
res = cv2.bitwise_and(frame, frame, mask=mask)# 对原图像和掩模进行位运算
# 显示图像
cv2.imshow('frame', frame)
cv2.imshow('mask', mask)
cv2.imshow('res', res)
k = cv2.waitKey(5)&0xFF
if k == 27:
break
cv2.destroyAllWindows()
2、 几何变换
2.1 扩展缩放
扩展缩放只是改变图像的尺寸大小。OpenCV提供的函数cv2.resize()可以实现这个功能。图像的尺寸可以自己手动设置,也可以指定缩放因子。可以选择使用不同的插值方法。在缩放时推荐使用cv2.INTER_AREA,在扩展时推荐使用cv2.INTER_CUBIC(慢)和cv2.INTER_LINEAR。例如:
img = cv2.imread("./image/test2.jpg")
res1 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_CUBIC)
# or 这两种方式效果一样 (fx=2, fy=2为缩放因子,所以dst为None)
height, width = img.shape[:2]
res2 = cv2.resize(img, (2*width,2*height), interpolation=cv2.INTER_CUBIC)
2.2 平移
平移就是将对象换一个位置,如果你要沿(x,y)方向移动,移动的距离是(tx,ty),你可以以下面的方式构建移动矩阵:
可以使用Numpy数组构建这个矩阵(数据类型是np.float32),然后传给cv2.warpAffine()。次函数的第三个参数是输出图像的大小,它的格式应该是图像的(宽,高),图像的宽对应列数,高对应行数。例如:
M = np.float32([[1,0,100],[0,1,100]])
ret = cv2.warpAffine(img, M, (img.shape[0], img.shape[1]))
2.3 旋转
旋转和平移一样,只是旋转因子发生改变,为了获取旋转矩阵,需要使用一个函数cv2.getRotationMatrix2D(),如下:
M = cv2.getRotationMatrix2D((x,y), 45, 0.6)
参数1:旋转中心
参数2:旋转角度
参数3:旋转后的缩放因子(可以通过设置旋转中心,缩放因子以及窗口大小来防止旋转后超出边界问题)
2.4 仿射变换
在仿射变换中,原图中所有的平行线在结果图像中同样平行。为了创建这个矩阵我们需要从原图中找到三个点以及他们在输出图像中的位置(也就是原始的三个点核放射后点落的位置)。然后cv2.getArrineTransform会创建一个2x3的矩阵,最后这个矩阵会传给函数cv2.warpAffine();
2.5 视角变换
对于视角变换,我们需要一个3x3变换矩阵。在变换前后直线还是直线。要构建这个变换矩阵,我们需要在输入图像上找4个点,以及他们输出图像上对应的位置。这四点中任意三个不能共线。这个变换矩阵可以有函数cv2.getPerspectiveTransform()构建,然后把这哥矩阵传给函数cv2.warpPerspective()
3、 图像阈值
3.1 简单阈值
这个方法很简单,只要像素值高于阈值时,我们给这个像素赋予一个新的值,这个函数就是cv2.threshhold()。参数1就是原图像(原图像应该是灰度图),参数2是用来对像素进行分类的阈值。参数3就是当像素值高于(有时是小于)阈值时赢赋予的新的像素值。OpenCV提供了多种不同的阈值方法,这是有参数4决定的。参数4如下:
1. cv2.THRESH_BINARY(二值阈值化)
2. cv2.THRESH_BINARY_INV(反向二值化并翻转)
3. cv2.THRESH_TRUNC(截断阈值化)
4. cv2.THRESH_TOZERO(超过阈值被置0)
5. cv2.THRESH_TOZERO_INV(低于阈值被置为0)
此函数有两个返回值,第二个返回值即是阈值化之后的图像。第一个是retVal;
3.2 自适应阈值
上面使用的是全局阈值,整幅图像采用同一个数作为阈值。但这种做法并不使用与所有情况,尤其是当同一副图像的不同部分具有不同的亮度时,这种情况下就需要采用自适应阈值。此时的阈值时根据图像上的每一个小区域计算与其对应的阈值。因此在同一副图像上的不同区域采用的是不同的阈值,从而得到更好的结果。
函数:cv2.adaptiveThreshold()
参数1:src 原图像(灰度图)
参数2:x 指当像素值高于(有时是小于)阈值时应该被赋予的新的像素值
参数3:adaptive_method 指: CV_ADAPTIVE_THRESH_MEAN_C 或 CV_ADAPTIVE_THRESH_GAUSSIAN_C
参数4:threshold_type 指取阈值的类型,必须是下列之一cv2.THRESH_BINARY或cv2.THRESH_BINARY_INV