Opencv 入门(二)

1. 图像阈值

  • ret, dst = cv2.threshold(src, thresh, maxval, type)

src:输入图,只能为单通道图像,通常是灰度图
dst:输出图
thresh:阈值
maxval:当像素值超过了阈值(或小于阈值,根据type来决定),所赋予的值
type:二值化操作类型

  • type:包含5种类型:cv2.THRESH_BINARY;cv2.THRESH_BINARY_INV;cv2.THRESH_TRUNC;cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV;

    • cv2.THRESH_BINARY:大于阈值部分取maxval(最大值),否则取0
    • cv2.THRESH_BINARY_INV:反转
    • cv2.THRESH_TRUNC:大于阈值部分设为阈值,否则不变(截断)
    • cv2.THRESH_TOZERO:大于阈值部分不变,否则变0
    • cv2.THRESH_TOZERO_INV:反转
img_gray = cv.cvtColor(img1, cv.COLOR_BGR2GRAY)
ret, thresh1 = cv.threshold(img_gray, 217, 255, cv.THRESH_BINARY)
ret, thresh2 = cv.threshold(img_gray, 217, 255, cv.THRESH_BINARY_INV)
ret, thresh3 = cv.threshold(img_gray, 217, 255, cv.THRESH_TRUNC)
ret, thresh4 = cv.threshold(img_gray, 217, 255, cv.THRESH_TOZERO)
ret, thresh5 = cv.threshold(img_gray, 217, 255, cv.THRESH_TOZERO_INV)

titles = ["Original image", "BINARY", "BINARY_INV", "TRUNC", "TOZERO", "TOZERO_INV"]
images = [img1, 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()

在这里插入图片描述


Matplotlib Pyplot 的常用方法

Pyplot 是 Matplotlib 的子库,提供了和 MATLAB 类似的绘图 API。

绘制曲线 plot()

绘图标记
颜色字符:‘b’ 蓝色,‘m’ 洋红色,‘g’ 绿色,‘y’ 黄色,‘r’ 红色,‘k’ 黑色,‘w’ 白色,‘c’ 青绿色,’#008000’ RGB 颜色符串。多条曲线不指定颜色时,会自动选择不同颜色。
线型参数:’‐’ 实线,’‐‐’ 破折线,’‐.’ 点划线,’:’ 虚线。
标记字符:’.’ 点标记,’,’ 像素标记(极小点),‘o’ 实心圈标记,‘v’ 倒三角标记,’^’ 上三角标记,’>’ 右三角标记,’<’ 左三角标记…等等。

x = np.array([0, 10, 10])
y = np.array([0, 100, 0])
# plt.plot(x, y, 'r')
plt.plot(x, y, 'o')
plt.plot(x, y, '--')

在这里插入图片描述

_y = np.array([3, 8, 1, 10, 5, 7])
## x 默认[0, 1, 2, ..., n - 1]

在这里插入图片描述

# 在 plt.plot() 参数中包含两对 x,y 值,第一对是 x,y,这对应于正弦函数,
# 第二对是 x,z,这对应于余弦函数。 
x = np.arange(0, 4 * np.pi, 0.1)   # start,stop,step 
y = np.sin(x) 
z = np.cos(x) 
plt.plot(x,y,x,z) 

在这里插入图片描述

  1. 标签和标题

使用 xlabel()ylabel() 方法来设置 x 轴和 y 轴的标签。
使用 title() 方法来设置标题。
提供了 loc 参数来设置标题显示的位置,可以设置为: ‘left’, ‘right’, 和 ‘center’, 默认值为 ‘center’。

x = np.arange(0, 2 * np.pi, 0.2)
y = np.sin(x)
plt.title('sinx')
plt.xlabel('x')
plt.ylabel('y')
plt.plot(x, y)

在这里插入图片描述


绘制网格线 grid()

matplotlib.pyplot.grid(b=None, which=‘major’, axis=‘both’, **kwargs)

  • b:可选,默认为 None,可以设置布尔值,true 为显示网格线,false 为不显示,如果设置 **kwargs 参数,则值为 true。
  • which:可选,可选值有 ‘major’、‘minor’ 和 ‘both’,默认为 ‘major’,表示应用更改的网格线。
  • axis:可选,设置显示哪个方向的网格线,可以是取 ‘both’(默认),‘x’ 或 ‘y’,分别表示两个方向,x 轴方向或 y 轴方向。
  • **kwargs:可选,设置网格样式,可以是 color=‘r’, linestyle=’-’ 和 linewidth=2,分别表示网格线的颜色,样式和宽度。
plt.grid(axis = 'y', color = 'r', linestyle = '--', linewidth = 0.5)

在这里插入图片描述

绘制多图

subplot()subplots() 绘制多个子图。
subplot() 方法在绘图时需要指定位置,subplots() 方法可以一次生成多个,在调用时只需要调用生成对象的 ax 即可。

  • subplot(nrows, ncols, index, **kwargs)

    • 行列,及该图是第index
#plot 1:
x1 = np.array([0, 6])
y1 = np.array([0, 100])
plt.subplot(1, 2, 1)
plt.plot(x1, y1)
plt.title("plot 1")
#plot 2:
x2 = np.array([1, 2, 3, 4])
y2 = np.array([1, 4, 9, 16])
plt.subplot(1, 2, 2)
plt.plot(x2, y2)
plt.title("plot 2")
plt.suptitle("subplot Test")
plt.show()

在这里插入图片描述

  • subplots() #

绘制散点图

matplotlib.pyplot.scatter(x, y, s=None, c=None, marker=None, cmap=None, …)

  • x,y:长度相同的数组
  • s:点的大小,默认 20。可以是个数组,数组每个参数为对应点的大小。
  • c:点的颜色,默认蓝色 ‘b’。可以是个 RGB 或 RGBA 二维行数组。
  • marker:点的样式,默认小圆圈 ‘o’。
  • cmap:Colormap,默认 None,标量或者是一个 colormap 的名字,只有 c 是一个浮点数数组的时才使用。如果没有申明就是 image.cmap。
# 随机数生成器的种子
np.random.seed(20030121)
N = 30
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
sizes = (30 * np.random.rand(N))**2  # [0, 900)
# np.random.rand() -->> [0, 1) 随机数,服从均匀分布
plt.scatter(x, y, s=sizes, c=colors, cmap='viridis', alpha=0.5) # alpha = 透明度
plt.title("Scatter Test") # 设置标题
plt.colorbar() # 显示颜色条,cmap 默认 'viridis'
plt.show()

在这里插入图片描述


绘制柱形图

matplotlib.pyplot.bar(x, height, width=0.8, bottom=None, *, align=‘center’, data=None, **kwargs)
水平方向:bar()
垂直方向:barh()

  • x:浮点型数组,柱形图的 x 轴数据
  • height:浮点型数组,柱形图的高度
  • width:浮点型数组,柱形图的宽度
  • bottom:浮点型数组,底座的 y 坐标,默认 0
  • align:柱形图与 x 坐标的对齐方式,‘center’ 以 x 位置为中心,这是默认值’edge’:将柱形图的左边缘与 x 位置对齐。要对齐右边缘的条形,可以传递负数的宽度值及 align=‘edge’
x = np.array(["a", "b", "c", "d"])
y = np.array([12, 22, 6, 18])
plt.subplot(1, 2, 1), plt.title('h'), plt.barh(x, y, color=["#4CAF50","red","hotpink","#556B2F"], height=0.5)
plt.subplot(1, 2, 2), plt.title('v'), plt.bar(x, y, color=["#4CAF50","red","hotpink","#556B2F"], width=0.5)
plt.suptitle('bar chart')
plt.show()

在这里插入图片描述


绘制饼图

pit( … )

y = np.array([35, 25, 25, 15]) # 逆时针绘制
plt.pie(y,
        labels=['A','B','C','D'], # 设置饼图标签
        colors=["#d5695d", "#5d8ca8", "#65a479", "#a564c9"], # 设置饼图颜色
        explode=(0, 0.2, 0, 0), # 第二部分突出显示,值越大,距离中心越远
        autopct='%.2f%%', # 格式化输出百分比
       )
plt.title("Pie Test")

在这里插入图片描述


2. 图像平滑处理

也称模糊处理,常见用来减少图像上的噪点或者失真。

线性滤波

  • 均值滤波(领域平均滤波)
  • 方框滤波
  • 高斯滤波

均值滤波

  • cv2.blur(src,ksize,dst,anchor,borderType)
    • src: 输入图像对象矩阵,可以为单通道或多通道
    • ksize:卷积核的大小,格式为(宽,高)
    • dst:输出图像矩阵,大小和数据类型都与src相同
    • anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置
    • borderType:填充边界类型

对目标像素及周边像素取平均值后再填会目标像素来实现滤波目的的方法。

# 均值滤波
blur = cv.blur(img1, (3, 3))

ksize = (5, 5)
blur = cv.blur(img1, ksize, cv.BORDER_DEFAULT)

方框滤波

  • cv2.boxFilter(src,ddepth,ksize,dst,anchor,normalize,borderType)
    • src: 输入图像对象矩阵
    • ddepth:数据格式,位深度
    • ksize:高斯卷积核的大小,格式为(宽,高)
    • dst:输出图像矩阵,大小和数据类型都与src相同
    • anchor:卷积核锚点,默认(-1,-1)表示卷积核的中心位置
    • normalize:是否归一化 (若卷积核3*5,归一化卷积核需要除以15)
    • borderType:填充边界类型

若归一化,等价于均值滤波
若不归一,即截断在255

# 方框滤波
blur = cv.boxFilter(img1, -1, (3, 5))

高斯滤波

高斯卷积核是一个近似服从高斯分布的矩阵,随着距离中心点的距离增加,其值变小。这样进行平滑处理时,图像矩阵中锚点处像素值权重大,边缘处像素值权重小。
下为一个3*3的高斯卷积核:

  • dst =cv2.GaussianBlur(src,ksize,sigmaX,sigmay,borderType)
    • src: 输入图像矩阵,可为单通道或多通道,多通道时分别对每个通道进行卷积
    • dst:输出图像矩阵,大小和数据类型都与src相同
    • ksize:高斯卷积核的大小,宽,高都为奇数,且可以不相同
    • sigmaX: 一维水平方向高斯卷积核的标准差
    • sigmaY: 一维垂直方向高斯卷积核的标准差,默认值为0,表示与sigmaX相同
    • borderType:填充边界类型
# 高斯滤波
dst = cv.GaussianBlur(img1, (3, 5), 1)

在这里插入图片描述

对于上面的高斯卷积核,可以由如下两个矩阵相乘进行构建,说明高斯核是可分离卷积核,因此高斯卷积操作可以分成先进行垂直方向的一维卷积,再进行一维水平方向卷积。

在这里插入图片描述

  • cv2.getGaussianKernel(ksize,sigma,ktype)
    • ksize:奇数,一维核长度
    • sigma:标准差
    • ktype:数据格式,应该为CV_32F 或者 CV_64F
# 先知道有这么个函数

非线性滤波

  • 中值滤波
  • 双边滤波

中值滤波

中值平滑也有核,但并不进行卷积计算,而是对核中所有像素值排序得到中间值,用该中间值来代替锚点值。中值平滑特别适合用来去除椒盐噪声。

  • cv2.medianBlur(src,ksize,dst)
    • src: 输入图像对象矩阵,可以为单通道或多通道
    • ksize:核的大小,格式为 3 # 注意不是(3,3)
    • dst:输出图像矩阵,大小和数据类型都与src相同
img_median = cv.medianBlur(img1, 3)

## 白点噪声都被平滑掉了

在这里插入图片描述


双边滤波

双边滤波在平滑的同时还能保持图像中物体的轮廓信息。
双边滤波在高斯平滑的基础上引入了灰度值相似性权重因子,所以在构建其卷积核核时,要同时考虑空间距离权重灰度值相似性权重
在进行卷积时,每个位置的邻域内,根据和锚点的距离d构建距离权重模板,根据和锚点灰度值差异r构建灰度值权重模板,结合两个模板生成该位置的卷积核。

  • dst = cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace,borderType)
    • src: 输入图像对象矩阵,可以为单通道或多通道
    • d:用来计算卷积核的领域直径,如果d<=0,从sigmaSpace计算d
    • sigmaColor:颜色空间滤波器标准偏差值,决定多少差值之内的像素会被计算(构建灰度值模板)
    • sigmaSpace:坐标空间中滤波器标准偏差值。如果d>0,设置不起作用,否则根据它来计算d值(构建距离权重模板)
bilateralFilter = cv.bilateralFilter(img1, 0, 0.3, 20)

import numpy as np
np.hstack() # 矩阵进行水平连接
np.vstack() # 矩阵进行垂直连接

res = np.hstack((blur, dst, img_median, bilateralFilter))
# 均值, 高斯, 中值, 双边

在这里插入图片描述


3. 形态学

腐蚀 & 膨胀

 消除噪声
 分割(isolate)独立的图像元素,以及连接(join)相邻的元素。
 寻找图像中的明显的极大值区域或极小值区域。

1. 腐蚀

  • cv2.erode(img, kernel, iterations)

    • kernel:腐蚀操作的内核,默认是一个简单的3X3矩阵。也可以利用getStructuringElement()函数指明它的形状
    • iterations:腐蚀次数,省略是默认为1

进行腐蚀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最小相素值提取,并代替锚点位置的相素。

kernel = np.ones((5, 5), np.uint8);
# 内核 np.ones((k,k), mp.uint8);
erosion = cv.erode(img2, kernel, iterations = 1)
plt.subplot(1, 2, 1), plt.imshow(img2)
plt.subplot(1, 2, 2), plt.imshow(erosion)
plt.show()

在这里插入图片描述


2. 膨胀

  • cv2.dilation(img, kernel, iterations)

进行膨胀操作时,将内核 B 划过图像,将内核 B 覆盖区域的最大相素值提取,并代替锚点位置的相素。显然,这一最大化操作将会导致图像中的亮区开始”扩展” 。

dilation = cv.dilate(erosion, kernel, iterations = 1)
plt.subplot(1, 2, 1), plt.imshow(erosion)
plt.subplot(1, 2, 2), plt.imshow(dilation)
plt.show()

## 腐蚀完进行膨胀

在这里插入图片描述


3. 开运算

  • cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

先腐蚀再膨胀,被用来去除噪声。


4. 闭运算

  • cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

先膨胀再腐蚀,经常被用来填充前景物体中的小洞、小黑点。

opening = cv.morphologyEx(img, cv.MORPH_OPEN,kernel) # 开运算
closeing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel) # 闭运算

在这里插入图片描述

5. 形态学梯度

  • cv2.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

膨胀图与腐蚀图之差,dilate - erode
保留物体的边缘轮廓,凸显边缘

pie = img3.copy()
# show('', pie)
kernel = np.ones((5, 5), np.uint8)
dilate = cv.dilate(pie, kernel, iterations = 5)
erosion = cv.erode(pie, kernel, iterations = 5)
res = np.hstack((dilate, erosion))
show('res', res)

在这里插入图片描述

gradient = cv.morphologyEx(pie, cv.MORPH_GRADIENT, kernel)

在这里插入图片描述


6. 顶帽

= 原始 - 开运算

tophat = cv.morphologyEx(img2, cv.MORPH_TOPHAT, kernel)

7. 黑帽

= 闭运算 - 原始

black = cv.morphologyEx(img2, cv.MORPH_BLACKHAT, kernel)

附上好文

猜你喜欢

转载自blog.csdn.net/qq_52678569/article/details/122286946