opencv(1)图像处理
2、图像操作
图片裁剪
裁剪是利用array自身的下标截取实现
HSV空间
除了区域,图像本身的属性操作也非常多,比如可以通过HSV空间对色调和明暗进行调节。HSV空间是由美国的图形学专家A. R. Smith提出的一种颜色空间,HSV分别是色调(Hue),饱和度(Saturation)和明度(Value)。在HSV空间中进行调节就避免了直接在RGB空间中调节是还需要考虑三个通道的相关性。OpenCV中H的取值是[0, 180),其他两个通道的取值都是[0, 256)
直方图
无论是HSV还是RGB,我们都较难一眼就对像素中值的分布有细致的了解,这时候就需要直方图。如果直方图中的成分过于靠近0或者255,可能就出现了暗部细节不足或者亮部细节丢失的情况。
Gamma变换
Gamma变换可以提升暗部细节。Gamma变换是矫正相机直接成像和人眼感受图像差别的一种常用手段,简单来说就是通过非线性变换让图像从对曝光强度的线性响应变得更接近人眼感受到的响应。
3、几何变换
平移
图像的平移,沿着x方向tx距离,y方向ty距离,那么需要构造移动矩阵:
通过numpy来产生这个矩阵,并将其赋值给仿射函数cv2.warpAffine().
仿射函数cv2.warpAffine()接受三个参数,需要变换的原始图像,移动矩阵M 以及变换的图像大小(这个大小如果不和原始图像大小相同,那么函数会自 动通过插值来调整像素间的关系)。
图片缩放
图像的扩大与缩小有专门的一个函数,cv2.resize(),那么关于伸缩需要确定的就是缩放比例,可以是x与y方向相同倍数,也可以单独设置x与y的缩放比例。另外一个就是在缩放以后图像必然就会变化,这就又涉及到一个插值问题。那么这个函数中,缩放有几种不同的插值(interpolation)方法,在缩小时推荐cv2.INTER_ARER,扩大是推荐cv2.INTER_CUBIC和cv2.INTER_LINEAR。默认都是cv2.INTER_LINEAR。
图像的旋转
图像的旋转矩阵一般为:
但是单纯的这个矩阵是在原点处进行变换的,为了能够在任意位置进行旋转变换,opencv采用了另一种方式:
为了构造这个矩阵,opencv提供了一个函数:
cv2.getRotationMatrix2D(),这个函数需要三个参数,旋转中心,旋转角度,旋转后图像的缩放比例。
图像的仿射
图像的仿射变换涉及到图像的形状位置角度的变化,是深度学习预处理中常到的功能。仿射变换具体到图像中的应用,主要是对图像的缩放,旋转,剪切,翻转和平移的组合。在OpenCV中,仿射变换的矩阵是一个2×3的矩阵,其中左边的2×2子矩阵是线性变换矩阵,右边的2×1的两项是平移项:
对于图像上的任一位置(x,y),仿射变换执行的是如下的操作:
需要注意的是,对于图像而言,宽度方向是x,高度方向是y,坐标的顺序和图像像素对应下标一致。所以原点的位置不是左下角而是右上角,y的方向也不是向上,而是向下。
由于仿射变换比较复杂,一般直接找很难找到这个矩阵,opencv提供了根据变换前后三个点的对应关系来自动求解M。这个函数是
M=cv2.getAffineTransform(pos1,pos2),其中两个位置就是变换前后的对应位置关系。输出的就是仿射矩阵M。然后在使用函数cv2.warpAffine()。
图像的透射
透视需要的是一个3*3的矩阵,同理opencv在构造这个矩阵的时候还是采用一种点对应的关系来通过函数自己寻找的,因为我们自己很难计算出来。这个函数是M = cv2.getPerspectiveTransform(pts1,pts2),其中pts需要变换前后的4个点对应位置。得到M后在通过函数cv2.warpPerspective(img,M,(200,200))进行。
4、图像的阈值处理
图像的阈值处理一般使得图像的像素值更单一、图像更简单。阈值可以分为全局性质的阈值,也可以分为局部性质的阈值,可以是单阈值的也可以是多阈值的。当然阈值越多是越复杂的。
简单阈值
简单阈值当然是最简单,选取一个全局阈值,然后就把整幅图像分成了非黑即白的二值图像了。函数为cv2.threshold()
这个函数有四个参数,第一个原图像,第二个进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有:
• cv2.THRESH_BINARY(黑白二值)
• cv2.THRESH_BINARY_INV(黑白二值反转)
• cv2.THRESH_TRUNC (得到的图像为多像素值)
• cv2.THRESH_TOZERO
• cv2.THRESH_TOZERO_INV
该函数有两个返回值,第一个retVal(得到的阈值值(在后面一个方法中会用到)),第二个就是阈值化后的图像。
自适应阈值
简单阈值是一种全局性的阈值,只需要规定一个阈值值,整个图像都和这个阈值比较。而自适应阈值可以看成一种局部性的阈值,通过规定一个区域大小,比较这个点与区域大小里面像素点的平均值(或者其他特征)的大小关系确定这个像素点是属于黑或者白(如果是二值情况)。使用的函数为:cv2.adaptiveThreshold()
该函数需要填6个参数:
- 第一个原始图像
- 第二个像素值上限
- 第三个自适应方法Adaptive Method:
— cv2.ADAPTIVE_THRESH_MEAN_C :领域内均值
— cv2.ADAPTIVE_THRESH_GAUSSIAN_C :领域内像素点加权和,权重为一个高斯窗口 - 第四个值的赋值方法:只有cv2.THRESH_BINARY 和cv2.THRESH_BINARY_INV
- 第五个Block size:规定领域大小(一个正方形的领域)
- 第六个常数C,阈值等于均值或者加权值减去这个常数(为0相当于阈值 就是求得领域内均值或者加权值)
这种方法理论上得到的效果更好,相当于在动态自适应的调整属于自己像素点的阈值,而不是整幅图像都用一个阈值
Otsu’s二值化
cv2.threshold函数是有两个返回值的,前面一直用的第二个返回值,也就是阈值处理后的图像,那么第一个返回值(得到图像的阈值)将会在这里用到。
前面对于阈值的处理上,我们选择的阈值都是127,那么实际情况下,怎么去选择这个127呢?有的图像可能阈值不是127得到的效果更好。那么这里我们需要算法自己去寻找到一个阈值,而Otsu’s就可以自己找到一个认为最好的阈值。并且Otsu’s非常适合于图像灰度直方图具有双峰的情况,他会在双峰之间找到一个值作为阈值,对于非双峰图像,可能并不是很好用。那么经过Otsu’s得到的那个阈值就是函数cv2.threshold的第一个参数了。因为Otsu’s方法会产生一个阈值,那么函数cv2.threshold的的第二个参数(设置阈值)就是0了,并且在cv2.threshold的方法参数中还得加上语句cv2.THRESH_OTSU。那么什么是双峰图像(只能是灰度图像才有),就是图像的灰度统计图中可以明显看出只有两个波峰
5、图像的平滑与滤波
对于图形的平滑与滤波,但从滤波角度来讲,一般主要的目的都是为了实现对图像噪声的消除,增强图像的效果。
图像的滤波可以看成是滤波模板与原始图像对应部分的的卷积运算。
对于2D图像可以进行低通或者高通滤波操作,低通滤波(LPF)有利于去噪,模糊图像,高通滤波(HPF)有利于找到图像边界。
统一的2D滤波器cv2.filter2D
Opencv提供的一个通用的2D滤波函数为cv2.filter2D(),滤波函数的使用需要一个核模板,对图像的滤波操作过程为:将和模板放在图像的一个像素A上,求与之对应的图像上的每个像素点的和,核不同,得到的结果不同,而滤波的使用核心也是对于这个核模板的使用,需要注意的是,该滤波函数是单通道运算的,也就是说对于彩色图像的滤波,需要将彩色图像的各个通道提取出来,对各个通道分别滤波才行。
这里说一个与matlab相似的情况,matlab中也有一个类似的滤波函数imfilter,对于滤波函数的应用其实不只在于滤波,对于许多图像的整体处理上,其实都可以用滤波函数来组合实现,得到更快的效果。
注意事项
把单通道图片保存后,再默认读取时,仍然是3通道,相当于把单通道值复制到3个通道保存