cv2 inrange灰度图_OpenCV学习笔记二:OpenCV中的图像处理

1 颜色空间转换

1.1. OpenCV有超过150种进行颜色空间转换的方法,最常用BGR与GRAY/HSV转换

1.2. HSV:Hue色调,Saturation饱和度,Value明度,HSV比GBR更容易表示特定颜色

1.3. 函数:cv2.cvtColor()

1.4. cv2.inRange()可根据阈值,生成特定颜色的掩模

2 几何变换

2.1. 扩展缩放:cv2.resize()

2.2. 平移/旋转:cv2.warpAffine() + 2x3移动矩阵

2.3. 旋转矩阵:cv2.getRotationMatrix2D()=>构建旋转矩阵

2.4. 仿射变换矩阵:cv2.getAffineTransform()=>构建仿射变换矩阵2x3

2.5. 透视变换矩阵:cv2.getPerspectiveTransform()=>3x3透视变换矩阵

2.6. 透视变换:cv2.warpPerspective()+ 3x3移动矩阵,常用于图像矫正

2.7. 仿射变换可保证物体形状平直性和平行性,透视不能保证平行性,仿射是透视特例

3 图像阈值

3.1. 简单阈值:cv2.threshold()

3.2. 自适应阈值:cv2.adaptiveThreshold()

3.3. Otsu’s二值化:大津法,最大类间方差法,该算法返回最优阈值,不适合非双峰图像

4 图像平滑

4.1. 与一维信号一样,我们也可以对2D图像实施低通滤波器(LPF)来去除噪声、模糊图像,使用高通滤波器(HPF)找到图像的边缘。

4.2. 卷积操作:cv2.filter2D() + 卷积核

4.3. 图像模糊(图像平滑)使用LPF来实现。OpenCV提供了四种模糊技术:

4.3.1 平均:平均值代替中心元素=》cv2.blur() 和cv2.boxFilter()

4.3.2 高斯模糊:卷积核换成高斯核=》cv2.GaussianBlur(),自己也可以构造高斯核:cv2.getGaussianKernel()

4.3.3 中值模糊:中值代替中心元素=》cv2.medianBlur()

4.3.4 双边滤波:同时考虑空间高斯权重(确保邻域像素对中心点有影响)和灰度值相似权重(确保只有与中心点灰度值相近的才会用来做模糊运算),边界处灰度值变化大,不会被模糊掉,保持边界清晰=》cv2.bilateralFilter()

5 形态学转换

5.1. 前景为白色,背景为黑色。两个基本形态学操作为:腐蚀和膨胀

5.2. 腐蚀:卷积核沿图像滑动,若卷积核对应图像所有像素为1,则中心元素就保持原像素值,否则变为0(白色变少,黑色变多)=》cv2.erode()

5.3. 膨胀:与腐蚀相反,与卷积核对应的原图像的像素值只要一个为1,则中心元素值就是1,否则为0.(白色变多,黑色变少)=>cv2.dilate()

5.4. 开运算:先腐蚀再膨胀,可消除噪声=》cv2.morphologyEx()

5.5. 闭运算:先膨胀再腐蚀,可填小黑洞=》cv2.morphologyEx()

5.6. 形态学梯度:膨胀与腐蚀之差=》cv2.morphologyEx()

5.7. 顶帽(Top Hat):原图与开运算之差

5.8. 黑帽:闭运算与原图之差

5.9. 结构化元素:告诉核的形状核大小=>cv2.getStructuringElement()==》生成核

6 图像梯度

6.1. 梯度滤波器也就是HPF,Sobel,Scharr其实就是求一阶或者二阶导数,Laplacian求二阶导数。Scharr是使用小卷积核求解梯度角度时,对Sobel的优化。梯度也为图像

6.2. Sobel算子:高斯平滑与微分操作的结合体,可设置求导方向和阶数,ksize=-1时会使用Scharr滤波器,效果比Sobel好。

6.3. Laplacian算子:OpenCV在计算拉普拉斯算子时直接调用Sobel算子

6.4. 图像深度:指存储每个像素所用的位数,也用于度量图像色彩的分辨率.

6.5. 图像求导可能有负数,原深度图为np.uint8时,负数会截断为0,边界丢失.因此需要将数据类型设置成更高的,然后取其绝对值转换回来.

7 Canny边缘检测

7.1. 1986年 John提出

7.2. 原理由很多步组成:

7.2.1 噪声去除:边缘检测易受噪声影响,高斯滤波器去噪声

7.2.2 计算图像梯度:Sobel计算水平及竖直方向一阶导数(图像梯度Gx,Gy)

梯度一般总与边界垂直,分四类:竖直,水平,两对角线(?这个地方没理解)

7.2.3非极大值抑制:对整幅图扫描,去除非边界上的点,看这个点的梯度是否是周围同梯度方向的点中最大的.

7.2.4 滞后阈值:设置两个阈值,灰度值高于最大的被认为是真的边界,低于最小值的直接被抛弃,介于两者之间的,若与真正边界相连,则为边界,否则抛弃

7.3. 函数:cv2.Canny()

8 图像金字塔

8.1. 有时需要对同一图像不同分辨率的子图像进行处理,最大的放底部,最小的放顶部,依次形成金字塔,共有两类:高斯金字塔和拉普拉斯金字塔.

8.2. 下采样: cv2.pyrDown()从高分辨率大尺寸的图像向上构建金子塔,尺寸变小分辨率变低, 会缩小图像丢失图像信息,过程为:

8.2.1 与高斯模板进行卷积

8.2.2 去除偶数行和偶数列

8.3. 上采样:cv2.pyrUp()从低分辨率小尺寸图像向下构建金字塔,尺寸变大但是分辨率不会增加, 会放大图像也会丢失信息,过程为:

8.3.1在每个方向上扩大为原来的两倍,新增行列用0填充

8.3.2 使用同样的高斯模板(数值上乘以4)与新的图像进行卷积

8.4. 拉普拉斯金字塔由高斯金字塔计算而来,公式为:

,通过原图像减去先缩小后放大的图像的一些列图像构成的.配合高斯金字塔使用,可以预测残差,对图像最大程度还原.

8.5. 图像金字塔的一个应用就是图像融合.

9 OpenCV中的轮廓

9.1. 轮廓:将连续的点连在一起的曲线,具有相同的颜色和灰度.

9.2. 轮廓在形状分析和物体的检测和识别中很有用

9.3. 为了更准确,需要二值化图像.在寻找之前,需要阈值化处理或者Canny边界检测. 查找轮廓的函数会修改原始图片,请注意保存,白色为前景

9.4. 查找轮廓: cv2.findContours() 绘制轮廓:cv2.drawContours()=>第三个参数为轮廓索引

9.5. 轮廓特征:矩, 轮廓面积, 轮廓周长, 轮廓近似, 凸包, 边界矩形,最小外接圆等

9.6. 轮廓性质:长宽比, Extent,Solidity,等效直径,方向,掩模,最大最小位置,平均颜色/灰度等

9.7. 更多函数:

9.7.1 凸缺陷: cv.2convexHull()=>找凸包, cv2.convexityDefect()=>判断

9.7.2 点到对象轮廓最短距离:cv2.pointPolygonTest()

9.7.3 形状匹配: cv2.matchShape()

9.8. 轮廓的层次结构==>知道其层次结构

10 直方图(Histogram)

10.1. 直方图是对图像的另一种解释.x是灰度值,y是图像中具有同一灰度值的点个数

10.2. BINS:将x轴分为很多小组,每个小组称为BIN; DIMS:收集数据的参数个数;RANGE:要统计的灰度值的范围

10.3. 函数:cv2.calcHist()

10.4. ravel()方法,flatten方法都是将数据转化成一维,前者返回view,后者返回copy

10.5. 直方图均匀化:一副高质量的图像的像素值分布应该很广泛,cv2.equalizeHist()

10.6. 当图像集中在某一个灰度值范围内时,直方图均匀化很有用.当像素变化很大,分布很广时,查看专门的调整对比度和亮度的文章(教程中给出链接了)

10.7. 直方图均衡化会改变图像的对比度,但很多时候效果不好.原因在于图像并不集中在某一个区域,为此我们需要自适应的直方图均衡化,即将图像分成很多小块,对于每一小块,像素比较集中;但是有噪声就会被放大,就需要使用对比度限制;为了去除每小块间”人造”边界,使用双线性插值, cv2.createCLACHE()

10.8. 2D直方图:只考虑灰度值,使用1.10中的一维直方图,2D直方图我们就考虑两个图像特征,对于彩色图片,我们通常考虑每个颜色的颜色(Hue)和饱和度(Saturation)

10.8.1函数同一维:cv2.calcHist(),参数变成二维channels=[0,1],bins=[180,256]

10.8.2 注意,颜色Hue的取值为0到180

10.9. 直方图反向投影

10.9.1 用途:图像分割,寻找感兴趣区域

10.9.2 输出:与输入图像(待搜索)同样大小的图像,输出图像的每一像素代表输入图像中的对应点在目标图像中出现的概率,用频数来表示。经常与camshift算法等一起使用。

10.9.3 实现:首先创建查找目标直方图,目标尽量占满这张图像,最好使用颜色图,因为物体的颜色比它的灰度更好地用于图像分割和对象识别;将这个直方图投影到输入图像中,即找出输入图像的每一像素在目标直方图中的概率,得到与输入同大小的概率图像;设置适当阈值对概率图进行二值化。

10.9.4 函数:cv2.calcBackProject() 参数与cv2.calcHist基本相同。在做反向投影之前需要对目标直方图进行归一化处理,使之值在0~255之间,因为直方图中的值可能超过255!

11 图像变换

11.1. 傅里叶变换:经常用来分析不同滤波器的频率特性。2D离散傅里叶变换(DFT)分析图像的频域特性,实现DFT的一个快速算法称为快速傅里叶变换(FFT)。

11.2. 对图像同时进行X方向和Y方向的傅里叶变换,我们会得到这幅图像的频域表示(频谱图),如果变化非常快称为高频信号,变换慢称为低频信号。在图像中边界和噪声是图像中的高频分量(指的是快而非多)。

11.3. 函数:cv2.dft()和cv2.idft()

11.4. DFT性能优化:当数据大小是2的指数时效率高,2,3,4的倍数时也高,当图像大小不是这些数据的时候可以手动补0以加快速度(注:Numpy里面函数会自动加)

12 模板匹配

12.1. 模板匹配:在一副大图中搜索查找模板图像位置的方法。和2D卷积一样,用模板图像在输入图像(大图)上滑动,在每一位置比较模板图和在大图中对应的子区域,返回灰度图像,像素值表示此区域与模板的匹配程度。

12.2. 函数:cv2.matchTemplate()匹配; cv2.minMaxLoc()返回最小最大位置(左上角的点)

12.3. 多对象匹配:不用cv2.minMaxLoc(),而是使用阈值自己来找匹配位置

13 Hough直线变换

13.1. 霍夫变换在检测各种形状的技术中非常流行。要检测的形状可以用数学表达式写出,就可以使用霍夫变换检测它,即使要检测的形状存在一点破坏或扭曲。

13.2. 过程:每条直线可以用

来表示,首先需要建立一个二维数组(累加器),行表示

,列表示

,数组大小决定结果的准确性,数组越大说明分得越细。取直线上的某一个点,然后遍历所有的

,得到不同的

,形成

点对,如果点对在累加器中,则累加器相应位置加1,不断更新累加器,搜索累加器的最大值,找出其位置,就找到了直线。

13.3. 在获取变化前需要对图像二值化或者进行Canny边缘检测,累加器中的值高于某一阈值时,才会被认为是一条直线,可看做检测到的直线的最短长度(像素值)。

13.4. 函数:cv2.HoughLines()=>返回

13.5. 霍夫变换优化:Probabilistic Hough Transform,不是对每一点计算,而是随机选取,但是这种变换我们必须降低阈值。

13.6. 函数cv2.HoughLinesP()返回值是直线的起点和终点。参数MaxLineGap表示最大间隔,如果小于此值,则两条直线可以看成是一条直线。

14 Hough圆环变换

14.1. 一个圆环需要三个参数确定:圆心坐标和半径,所以累加器必须是三维的,但这样做效率低,Opencv用比较巧妙的办法:霍夫梯度法,可使用边界的梯度信息。

14.2. 函数:cv2.HoughCircles()

15 分水岭算法图像分割

15.1. 原理:灰度图可看成拓扑平面,灰度值高看成峰,低看成谷。往山谷里面灌不同颜色的水,随着水位上升,山谷会汇集,为防止汇集,就做一个堤坝,不停灌水并且不停修建堤坝直到所有山峰被水淹没,构建的堤坝就是对图像的分割。

15.2. 上述方法会出现过分割,这是由于噪声和图像中的其他不规律因素造成的,为减少影响,OpenCV采用基于掩模的分水岭算法,这种算法需要设置哪些山谷点会汇合,哪些不会,我们要做的就是对已知对象打上不同标签:某区域一定是前景或对象则使用某个颜色(灰度值)标记,某区域肯定不是对象而是背景,则用另一种颜色标记,剩下不确定的就为0,然后再实施分水岭算法,每一次灌水,就更新一下标签,不同颜色标签相遇,则构成堤坝,直到所有山峰淹没,边界对象(堤坝)值为-1

15.3. 距离变换:计算图像中非零点像素到最近零像素点的距离,算法通过连续腐蚀实现

15.4. 使用连通域函数:cv2.connectedComponents()可以对不同区域进行标记,需要注意的是,此函数将背景标记为0,其他对象从1开始正整数标记,分水岭算法中0表示不确定,可将连通域函数结果整体加1来处理。

15.5. 函数:cv2.watershed()

16 使用GrabCut算法进行交互式前景提取

16.1. 一种交互式程序用于提取前景

16.2. 高斯混合模型(GMM):多个高斯分布函数的线性组合理论上可拟合出任意类型,通常由于解决同一集合下的数据包含多个不同的分布的情况。

16.3. 过程:用户输入矩形框,框外为背景,框内为未知;计算机对输入图形进行标记;使用GMM对前景和背景建模,学习并创建新的像素分布;根据像素分布创建一幅图:像素点为节点,另加Source_node和Sink_node,前景跟前者相连,背景跟后者相连;像素与Source_node和Sink_node的连接权重由同属于一类(同属于前景或背景)的概率决定,像素点间的权重由相似性决定;使用mincut算法,对上面所得图像进行分割。

16.4. 函数:cv2.grabCut()

你可能感兴趣的:(cv2,inrange灰度图)