OpenCV(二)基于python
发布日期:2021-05-04 20:59:05 浏览次数:20 分类:技术文章

本文共 5275 字,大约阅读时间需要 17 分钟。

文章目录


一. 阈值

代码

from matplotlib import imageimport cv2import matplotlib.pyplot as pltimg=cv2.imread('./material/image/e.jpg',cv2.IMREAD_GRAYSCALE)# img 只能是单通道的# 127 是阈值# maxval 即255 是最大值# type 二值法的类型# ret 是阈值,thresh1是阈值处理后的图像ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY)        #超过阈值取最大值,否则取0ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)    #和上边反过来ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC)         #超出阈值设为阈值,否则不变ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO)        #超过阈值不变,否则取0ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_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.xticks([]),plt.yticks([])plt.show()

效果图:

在这里插入图片描述


二. 平滑处理

平缓处理,就是有用来去除噪音点的,可以通俗的理解为磨光

均值滤波,就是用九个数的平均数,代替中间的,中值滤波就是用 中位数 的代替两边的,所以一般来讲,应该是中值滤波器效果比较好。

代码:

from matplotlib import imageimport cv2import matplotlib.pyplot as pltimg=cv2.imread('./material/image/g.jpg')# 均值滤波# 使用 3*3 的滤波器blur=cv2.blur(img,(3,3))# 方框滤波和均值滤波其实是一样的# 高斯滤波  离中间点越近,影响越大,权重越大aussian=cv2.GaussianBlur(img,(5,5),1)#中值滤波median=cv2.medianBlur(img,5)# 画出看看images=[img,blur,aussian,median]for i in range(4):    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')    plt.xticks([]),plt.yticks([])plt.show()

效果图:

在这里插入图片描述


三.梯度处理

3.1梯度的概念

在这里插入图片描述

就以上边的图为例,可以看出来,红点的地方,左边和右边的像素点的值,差距是非常大的(一个是255,一个0),那么就可以说,这个区域是存在 梯度

在一般的实际应用中,梯度就是用来做边缘检测的。相当于把边界线标出来(边界线就是 中间的那个数)

3.2图像梯度 - Sobel 算子

在这里插入图片描述

Gx这样相当于始终是右边减左边,所以有些时候可以取绝对值

Gx 为例,梯度运算和上边平滑处理是一样,这个也是用来算 P5 值的,所以 P4和P6 会对P5 的影响比较大,权重为2,而P1和P3 的权重为1 。

在这里插入图片描述

3.3代码:

import cv2from _00_pubulic import cv_showfrom matplotlib import imageimport matplotlib.pyplot as plt#读进来一张照片img=cv2.imread('./material/image/a.jpg',cv2.IMREAD_GRAYSCALE)cv_show(img,'img')#进行x轴方向的检测 即(1,0)表示的是x 轴的检测sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)cv_show(sobelx,"sobelx")#转成绝对值在看x轴的检测sobelx=cv2.convertScaleAbs(sobelx)cv_show(sobelx,"sobelx")#进行y方向的检测sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)cv_show(sobely,"sobelx")#竖着的和横着的相加sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)cv_show(sobelxy,"sobelxy")

原图:

在这里插入图片描述


竖直方向进行梯度处理(x轴放下的处理)

在这里插入图片描述


Y轴方向上的梯度处理

在这里插入图片描述


x轴的处理结果和y方向的处理结果相加

在这里插入图片描述

x轴方向,转换成绝对值后的结果:

在这里插入图片描述

建议先后求出 x ,y,的梯度,然后相加,不建议直接求梯度

3.其他算子

在这里插入图片描述

注意:

  • Scharr 算子相当于比 Sobel 算子更细了,可以查出更细小的变化
  • laplacian 算子一般不会单独使用,因为对噪音点比较敏感

四.边缘检测

只看一个经典的边缘检测算法:Canny 边缘检测


(一) Canny边缘检测的步骤:

  • 使用高斯滤波器,以平滑图像,滤掉噪音
  • 计算每个像素点的梯度强度和梯度方向
  • 应用极大值抑制。来消除边缘检测带来的杂散响应
  • 应用双阈值,来检测真正和潜在的边缘
  • 采用抑制孤立的弱边缘最终完成边缘检测

(二)具体过程

1.高斯滤波器

在这里插入图片描述


计算梯度和方向

在这里插入图片描述


非极大值抑制:判断不是最大值的梯度,不是最大的就抑制:

canny中非最大抑制(Non-maximum suppression)其实就是回答这样一个问题: “当前的梯度值在梯度方向上是一个局部最大值吗?” 所以,要把当前位置的梯度值与梯度方向上两侧的梯度值进行比较.

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


双阈值检测

在这里插入图片描述


(三) 代码

import cv2from _00_pubulic import cv_showfrom matplotlib import imageimport matplotlib.pyplot as pltimport numpy as np#读进来一张照片img=cv2.imread('./material/image/a.jpg',cv2.IMREAD_GRAYSCALE)cv_show(img,'img')#使用Canny边缘检测算法  80,150 是两个阈值v1=cv2.Canny(img,80,150)v2=cv2.Canny(img,50,100)res=np.hstack((v1,v2))cv_show(res,'res')

原图和效果图

在这里插入图片描述

可以看出来,右边的边缘检测更细腻

在这里插入图片描述

五. 图像金字塔与边缘检测

(一)图像金字塔

在这里插入图片描述

主要分为两种

  • 高斯金字塔
  • 拉普拉斯金字塔

上下采样的代码

#读进来一张照片img=cv2.imread('./material/image/a.jpg',cv2.IMREAD_GRAYSCALE)print(img.shape)# (300,530)# 上采样up=cv2.pyrUp(img)cv_show(up,'up')print(up.shape)# 下采样down=cv2.pyrDown(img)cv_show(down,'down')

(二)轮廓检测

轮廓检测和边缘检测的区别:虽然边缘检测把边界找出来,然后零零散散的拼成一个轮廓,但是他毕竟不是一个整体,轮廓检测是一个整体性的。

轮廓构建的方法

轮廓都是用边缘检测得到的点来勾画出来的,轮廓逼近法,主要有两种

  • CHAIN_APPROX_NONE:
  • CHAIN_APPROX_SIMPLE:

代码:

import cv2from _00_pubulic import cv_showimport matplotlib.pyplot as pltimport numpy as np#读进来一张图img=cv2.imread('./material/image/e.jpg')gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换成灰度图# thresh_binary 是非黑即白的分类方式ret,threshimg=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)cv_show(threshimg,'thresh')# 执行边缘检测# 参数的含义:cv2.retr_tree 是检测所有的轮廓# chain——approx——none 是把所有点都画出来,# contours 是返回的轮廓信息# herarchy 是层级contours,hierarchy=cv2.findContours(threshimg,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)# 绘制轮廓(在原图上把轮廓画出来)# 注意不要是使用 copy ,要不原图会变draw_img=img.copy()res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)cv_show(res,'res')

效果图:

在这里插入图片描述

(三)轮廓特征

轮廓特征,就是比如轮廓的面积或者边长等等特征。
#轮廓特征 (先找到一个轮廓)cnt=contours[139]#面积a=cv2.contourArea(cnt)print(a)#周长 。true 表示闭合a=cv2.arcLength(cnt,True)print(a)

六.直方图

(一)直方图

直方图的均衡化:

直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法

在这里插入图片描述


(二)将图片转换成直方图的代码

#读进来一张图,0表示是灰度图img=cv2.imread('./material/image/e.jpg',0)# channels:表示的是通道数,如果是会对就是[0], 彩色图就是 [0][1][2]分别对应着BGR# mask 就是表示其中的一部分# [0,256]表示的取值范围# histhist=cv2.calcHist([img],[0],None,[256],[0,256])print(hist.shape)# 把图画出来plt.hist(img.ravel(),256)plt.show()# 进行均衡化操作equ=cv2.equalizeHist(img)plt.hist(equ.ravel(),256)plt.show()

运行结果:


在这里插入图片描述

在这里插入图片描述

均衡化之后的结果:

在这里插入图片描述

(三)自适应直方图

在这里插入图片描述

直接进行全局适应,会出现上边的问题,会把人脸变模糊,所以,可以把上面的图片进行画区域进行均衡化处理

代码:

# 自适应均衡化clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8)) # 声明一个方法res_clahe=clahe.apply(img) # 把方法应用到图片上# 把三张图摞在一起画出来res=np.hstack((img,equ,res_clahe))cv_show(res,'res')

效果图如下:

在这里插入图片描述


七.傅里叶变换

傅里叶变换的作用:

  • 高频:变化剧烈的灰度分量,例如边界
  • 低频:变化缓慢的灰度图分量,例如一片大海

滤波:

  • 低通滤波器:只保留低频,会让图片变得模糊
  • 高通滤波器:只保留高频,会让图像的细节增强

八.图像特征

(一)图像特征 -harris 角点检测

在这里插入图片描述

B是平面,C是边界,A是角点,从图中可以看出,只有A在沿 x ,y 轴移动的时候,会发生剧烈变化,所以可以认定为焦点 (当然,真正的推算的数学公式是比较复杂的,用到再看)

  • 边界可以大致找到位置
  • 角点可以迅速定位到位置

(二)图像特征-sift

1.图像的尺寸空间:

在一定的范围内,无论物体是大是小,人眼都可以分辨出来,然而计算机要有相同的功能却很难,所以要让机器对物体不同尺度下有一个统一的认知,就需要考虑一下图像在不同的尺度下都存在的特点。

尺寸空间的获取通常通过高斯模糊来实现:

在这里插入图片描述
权重模糊的程度,是通过 ??来显示的
也就是说,无论是清楚或者模糊,你都得能认出来才行

在这里插入图片描述

2.多分辨率金字塔

通过上采样和下采样,把图分成大小不同的几张,且每张都要做高斯滤波。

在这里插入图片描述


高斯差分金字塔:

就是通过做差,看哪个差距大,就说明哪个更容易区分。

具体查看参考文献:

在这里插入图片描述


上一篇:.net core 中使用 EFcore做ORM
下一篇:OpenCV (一)基于Python

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月03日 01时03分50秒