OpenCV-python numpy使用和基本作图

2023-12-13 16:07:10

一、实验目的

本实验是利用python中的numpy库中的函数,对数组进行各种各样的操作和对图像进行各种操作。对数组进行的操作包括熟悉numpy的基本操作——学习如何创建、访问和修改NumPy数组,了解数组的属性和方法;学习如何改变数组的形状,例如改变维度、转置数组、重塑数组等;还有学习如何使用NumPy的索引和切片操作,对数组进行元素的访问和修改。对图像的操作包括学习如何实现颜色变换、画基本图形、文字绘制、为图像添加边框以及在图像中查找轮廓。通过该实验,可以帮助我们掌握numpy的基本操作和常用函数,理解数组的概念和运算;同时可以深入了解OpenCV图像处理模块的功能和应用,并对不同的图像处理算法和技术有所了解,实验过程也可以帮助我更加熟悉OpenCV提供的函数和方法,为将来在计算机视觉和图像处理领域的实际应用中打下基础。

二、实验内容

1.numpy基本操作

2.基本图形的绘制

三、实验过程

Numpy

NumPy - 简介

NumPy 是一个 Python 包。 它代表 “Numeric Python”。 它是一个由多维数组对象和用于处理数组的例程集合组成的库。

Numeric,即 NumPy 的前身,是由 Jim Hugunin 开发的。 也开发了另一个包 Numarray ,它拥有一些额外的功能。 2005年,Travis Oliphant 通过将 Numarray 的功能集成到 Numeric 包中来创建 NumPy 包。 这个开源项目有很多贡献者。

1.NumPy 操作

使用NumPy,开发人员可以执行以下操作:

  • 数组的算数和逻辑运算。

  • 傅立叶变换和用于图形操作的例程。

  • 与线性代数有关的操作。 NumPy 拥有线性代数和随机数生成的内置函数。

2.NumPy Ndarray 对象

NumPy 最重要的一个特点是其 N 维数组对象 ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。

ndarray 对象是用于存放同类型元素的多维数组。

ndarray 中的每个元素在内存中都有相同存储大小的区域。

ndarray 内部由以下内容组成:

  • 一个指向数据(内存或内存映射文件中的一块数据)的指针。

  • 数据类型或 dtype,描述在数组中的固定大小值的格子。

  • 一个表示数组形状(shape)的元组,表示各维度大小的元组。

  • 一个跨度元组(stride),其中的整数指的是为了前进到当前维度下一个元素需要"跨过"的字节数。

ndarray 的内部结构:
ndarray

跨度可以是负数,这样会使数组在内存中后向移动,切片中 obj[::-1] 或 obj[:,::-1] 就是如此。

创建一个 ndarray 只需调用 NumPy 的 array 函数即可:

名称描述
object数组或嵌套的数列
dtype数组元素的数据类型,可选
copy对象是否需要复制,可选
order创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)
subok默认返回一个与基类类型一致的数组
ndmin指定生成数组的最小维度NumPy 数据类型

numpy 支持的数据类型比 Python 内置的类型要多很多,基本上可以和 C 语言的数据类型对应上,其中部分类型对应为 Python 内置的类型。下表列举了常用

3.NumPy 基本类型

名称描述
bool_布尔型数据类型(True 或者 False)
int_默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc与 C 的 int 类型一样,一般是 int32 或 int 64
intp用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8字节(-128 to 127)
int16整数(-32768 to 32767)
int32整数(-2147483648 to 2147483647)
int64整数(-9223372036854775808 to 9223372036854775807)
uint8无符号整数(0 to 255)
uint16无符号整数(0 to 65535)
uint32无符号整数(0 to 4294967295)
uint64无符号整数(0 to 18446744073709551615)
float_float64 类型的简写
float16半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_complex128 类型的简写,即 128 位复数
complex64复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128复数,表示双 64 位浮点数(实数部分和虚数部分)

numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 np.bool_,np.int32,np.float32,等等。

4.NumPy 数组属性

本章节我们将来了解 NumPy 数组的一些基本属性。

NumPy 数组的维数称为秩(rank),秩就是轴的数量,即数组的维度,一维数组的秩为 1,二维数组的秩为 2,以此类推。

在 NumPy中,每一个线性的数组称为是一个轴(axis),也就是维度(dimensions)。比如说,二维数组相当于是两个一维数组,其中第一个一维数组中每个元素又是一个一维数组。所以一维数组就是 NumPy 中的轴(axis),第一个轴相当于是底层数组,第二个轴是底层数组里的数组。而轴的数量——秩,就是数组的维数。

很多时候可以声明 axis。axis=0,表示沿着第 0 轴进行操作,即对每一列进行操作;axis=1,表示沿着第1轴进行操作,即对每一行进行操作。

NumPy 的数组中比较重要 ndarray 对象属性有:

属性说明
ndarray.ndim秩,即轴的数量或维度的数量
ndarray.shape数组的维度,对于矩阵,n 行 m 列
ndarray.size数组元素的总个数,相当于 .shape 中 n*m 的值
ndarray.dtypendarray 对象的元素类型
ndarray.itemsizendarray 对象中每个元素的大小,以字节为单位
ndarray.flagsndarray 对象的内存信息
ndarray.realndarray元素的实部
ndarray.imagndarray 元素的虚部
ndarray.data包含实际数组元素的缓冲区,由于一般通过数组的索引获取元素,所以通常不需要使用这个属性。
ndarray.ndim

ndarray.ndim 用于返回数组的维数,等于秩。

ndarray.shape

ndarray.shape 表示数组的维度,返回一个元组,这个元组的长度就是维度的数目,即 ndim 属性(秩)。比如,一个二维数组,其维度表示"行数"和"列数"。

ndarray.shape 也可以用于调整数组大小。

ndarray.itemsize

ndarray.itemsize 以字节的形式返回数组中每一个元素的大小。

例如,一个元素类型为 float64 的数组 itemsize 属性值为 8(float64 占用 64 个 bits,每个字节长度为 8,所以 64/8,占用 8 个字节),又如,一个元素类型为 complex32 的数组 item 属性为 4(32/8)。

ndarray.flags

ndarray.flags 返回 ndarray 对象的内存信息

5.NumPy 创建数组

ndarray 数组除了可以使用底层 ndarray 构造器来创建外,也可以通过以下几种方式来创建。

numpy.empty

numpy.empty 方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的数组:

numpy.empty(shape, dtype = float, order = ‘C’)

参数说明:

参数描述
shape数组形状
dtype数据类型,可选
order有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
numpy.zeros

创建指定大小的数组,数组元素以 0 来填充:

numpy.zeros(shape, dtype = float, order = ‘C’)

参数说明:

参数描述
shape数组形状
dtype数据类型,可选
order‘C’ 用于 C 的行数组,或者 ‘F’ 用于 FORTRAN 的列数组
numpy.ones

创建指定形状的数组,数组元素以 1 来填充:

numpy.ones(shape, dtype = None, order = ‘C’)

参数说明:

参数描述
shape数组形状
dtype数据类型,可选
order‘C’ 用于 C 的行数组,或者 ‘F’ 用于 FORTRAN 的列数组

6.NumPy 从已有的数组创建数组

本章节我们将学习如何从已有的数组创建数组。

numpy.asarray

numpy.asarray 类似 numpy.array,但 numpy.asarray 参数只有三个,比 numpy.array 少两个。

numpy.asarray(a, dtype = None, order = None)

参数说明:

参数描述
a任意形式的输入参数,可以是,列表, 列表的元组, 元组, 元组的元组, 元组的列表,多维数组
dtype数据类型,可选
order可选,有"C"和"F"两个选项,分别代表,行优先和列优先,在计算机内存中的存储元素的顺序。
numpy.frombuffer

numpy.frombuffer 用于实现动态数组。

numpy.frombuffer 接受 buffer 输入参数,以流的形式读入转化成 ndarray 对象。

numpy.frombuffer(buffer, dtype = float, count = -1, offset = 0)

**注意:**buffer 是字符串的时候,Python3 默认 str 是 Unicode 类型,所以要转成 bytestring 在原 str 前加上 b。

参数说明:

参数描述
buffer可以是任意对象,会以流的形式读入。
dtype返回数组的数据类型,可选
count读取的数据数量,默认为-1,读取所有数据。
offset读取的起始位置,默认为0。
numpy.fromiter

numpy.fromiter 方法从可迭代对象中建立 ndarray 对象,返回一维数组。

numpy.fromiter(iterable, dtype, count=-1)

参数描述
iterable可迭代对象
dtype返回数组的数据类型
count读取的数据数量,默认为-1,读取所有数据

7.NumPy 从数值范围创建数组

这一章节我们将学习如何从数值范围创建数组。

numpy.arange

numpy 包中的使用 arange 函数创建数值范围并返回 ndarray 对象,函数格式如下:

numpy.arange(start, stop, step, dtype)

根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个 ndarray。

参数说明:

参数描述
start起始值,默认为0
stop终止值(不包含)
step步长,默认为1
dtype返回ndarray的数据类型,如果没有提供,则会使用输入数据的类型。
numpy.linspace

numpy.linspace 函数用于创建一个一维数组,数组是一个等差数列构成的,格式如下:

np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

参数说明:

参数描述
start序列的起始值
stop序列的终止值,如果endpointtrue,该值包含于数列中
num要生成的等步长的样本数量,默认为50
endpoint该值为 true 时,数列中包含stop值,反之不包含,默认是True。
retstep如果为 True 时,生成的数组中会显示间距,反之不显示。
dtypendarray 的数据类型
numpy.logspace

numpy.logspace 函数用于创建一个于等比数列。格式如下:

np.logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)

base 参数意思是取对数的时候 log 的下标。

参数描述
start序列的起始值为:base ** start
stop序列的终止值为:base ** stop。如果endpointtrue,该值包含于数列中
num要生成的等步长的样本数量,默认为50
endpoint该值为 true 时,数列中中包含stop值,反之不包含,默认是True。
base对数 log 的底数。
dtypendarray 的数据类型

8.NumPy 切片和索引

ndarray对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作一样。ndarray 数组可以基于 0 - n 的下标进行索引,切片对象可以通过内置的 slice 函数,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。实例 import numpy as np a = np.arange(10) s = slice(2,7,2) # 从索引 2 开始到索引 7 停止,间隔为2 print (a[s])

输出结果为:

[2 4 6]

以上实例中,我们首先通过 arange() 函数创建 ndarray 对象。 然后,分别设置起始,终止和步长的参数为 2,7 和 2。

我们也可以通过冒号分隔切片参数 start:stop:step 来进行切片操作:实例 import numpy as np a = np.arange(10) b = a[2:7:2] # 从索引 2 开始到索引 7 停止,间隔为 2 print(b)

输出结果为:

[2 4 6]

冒号 : 的解释:如果只放置一个参数,如 [2],将返回与该索引相对应的单个元素。如果为 [2:],表示从该索引开始以后的所有项都将被提取。如果使用了两个参数,如 [2:7],那么则提取两个索引(不包括停止索引)之间的项。实例 import numpy as np a = np.arange(10) # [0 1 2 3 4 5 6 7 8 9] b = a[5] print(b)

输出结果为:5

9.NumPy 高级索引

NumPy 比一般的 Python 序列提供更多的索引方式。

除了之前看到的用整数和切片的索引外,数组可以由整数数组索引、布尔索引及花式索引。

NumPy 中的高级索引指的是使用整数数组、布尔数组或者其他序列来访问数组的元素。相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。

整数数组索引

整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。

以下实例获取数组中 (0,0),(1,1)(2,0) 位置处的元素

实例 import numpy as np x = np.array([[1, 2], [3, 4], [5, 6]]) y = x[[0,1,2], [0,1,0]] print (y)

输出结果为:

[1 4 5]

布尔索引

我们可以通过一个布尔数组来索引目标数组。

布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。

以下实例获取大于 5 的元素:

实例 import numpy as np x = np.array([[ 0, 1, 2],[ 3, 4, 5],[ 6, 7, 8],[ 9, 10, 11]]) print (‘我们的数组是:’) print (x) print (‘\n’) # 现在我们会打印出大于 5 的元素 print (‘大于 5 的元素是:’) print (x[x > 5])

输出结果为:

我们的数组是:[[ 0 1 2] [ 3 4 5] [ 6 7 8] [ 9 10 11]]

大于 5 的元素是:[ 6 7 8 9 10 11]

10.NumPy 迭代数组

NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。

迭代器最基本的任务的可以完成对数组元素的访问。

接下来我们使用 arange() 函数创建一个 2X3 数组,并使用 nditer 对它进行迭代。

实例 import numpy as np a = np.arange(6).reshape(2,3) print (‘原始数组是:’) print (a) print (‘\n’) print (‘迭代输出元素:’) for x in np.nditer(a): print (x, end=", " ) print (‘\n’)

输出结果 原始数组是: [[0 1 2] [3 4 5]] 迭代输出元素: 0, 1, 2, 3, 4, 5,

修改数组中元素的值

nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值的修改,必须指定 readwrite 或者 writeonly 的模式。

实例 import numpy as np a = np.arange(0,60,5) a = a.reshape(3,4) print (‘原始数组是:’) print (a) print (‘\n’) for x in np.nditer(a, op_flags=[‘readwrite’]): x[…]=2*x print (‘修改后的数组是:’) print (a)

输出结果为: 原始数组是:[[ 0 5 10 15] [20 25 30 35] [40 45 50 55]] 修改后的数组是:[[ 0 10 20 30] [ 40 50 60 70] [ 80 90 100 110]]

使用外部循环

nditer 类的构造器拥有 flags 参数,它可以接受下列值:

参数描述
c_index可以跟踪 C 顺序的索引
f_index可以跟踪 Fortran 顺序的索引
multi_index每次迭代可以跟踪一种索引类型
external_loop给出的值是具有多个值的一维数组,而不是零维数组
    import numpy as np 
    a = np.arange(0,60,5) 
    a = a.reshape(3,4)  
    print ('原始数组是:')
    print (a)
    print ('\n')
    print ('修改后的数组是:')
    for x in np.nditer(a, flags =  ['external_loop'], order =  'F'):  
       print (x, end=", " )

输出结果: 原始数组是: [[ 0 5 10 15] [20 25 30 35] [40 45 50 55]] 修改后的数组是: [ 0 20 40], [ 5 25 45], [10 30 50], [15 35 55],

11.Numpy数组操作

修改数组形状
函数描述
reshape不改变数据的条件下修改形状
flat数组元素迭代器
flatten返回一份数组拷贝,对拷贝所做的修改不会影响原始数组
ravel返回展开数组
numpy.reshape

numpy.reshape 函数可以在不改变数据的条件下修改形状,格式如下:

numpy.reshape(arr, newshape, order=‘C’)

  • arr:要修改形状的数组
  • newshape:整数或者整数数组,新的形状应当兼容原有形状
  • order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘k’ – 元素在内存中的出现顺序
numpy.ndarray.flatten

numpy.ndarray.flatten 返回一份数组拷贝,对拷贝所做的修改不会影响原始数组,格式如下:

ndarray.flatten(order=‘C’)

numpy.ravel

numpy.ravel() 展平的数组元素,顺序通常是"C风格",返回的是数组视图(view,有点类似 C/C++引用reference的意味),修改会影响原始数组。

该函数接收两个参数:

numpy.ravel(a, order=‘C’)

参数说明:

  • order:‘C’ – 按行,‘F’ – 按列,‘A’ – 原顺序,‘K’ – 元素在内存中的出现顺序。

翻转数组

函数描述
transpose对换数组的维度
ndarray.Tself.transpose() 相同
rollaxis向后滚动指定的轴
swapaxes对换数组的两个轴
numpy.transpose

numpy.transpose 函数用于对换数组的维度,格式如下:

numpy.transpose(arr, axes)

参数说明:

  • arr:要操作的数组
  • axes:整数列表,对应维度,通常所有维度都会对换。
numpy.rollaxis

numpy.rollaxis 函数向后滚动特定的轴到一个特定位置,格式如下:

numpy.rollaxis(arr, axis, start)

参数说明:

  • arr:数组
  • axis:要向后滚动的轴,其它轴的相对位置不会改变
  • start:默认为零,表示完整的滚动。会滚动到特定位置。
numpy.swapaxes

numpy.swapaxes 函数用于交换数组的两个轴,格式如下:

numpy.swapaxes(arr, axis1, axis2)

  • arr:输入的数组
  • axis1:对应第一个轴的整数
  • axis2:对应第二个轴的整数

准备工作

安装pycharm和需要的软件包来进行代码的编辑
在这里插入图片描述

直接编辑代码导入,然后进行包的下载

小插曲

下载包的时候一直报错

去查询了一下报错原因pip安装报403错误 解决方法

于是我就把镜像地址又改了回来

pip config set global.index-url https://pypi.python.org/simple/

当然最后我检查了,大概不是清华园的问题(也可能是)

是pycharm本身的pip没有更新的问题

在这里更新完后就没有这个问题了,不用更改清华园的镜像
在这里插入图片描述
可以先更新一下项目pip,如果还是不对,就把镜像地址改回来

numpy包

这里numpy是在python处理大数据学过的一个库

对应OpenCv来说

使用Python运行OpenCV的程序时,OpenCV使用NumPy数组存储图像数据。基于NumPy可以很方便的执行基于数组的图像运算,比如图像的加法运算、加权加法运算和位运算等。

图像处理

颜色转换

cvtColor函数

dst=cv2.cvtColor(src,code[, dst[, dstCn]])

其中

dst(destination)就表示我们经过函数处理后得到的目的图像,此时是矩阵形式;

src(source)表示我们要进行转换的源图像对象,也是矩阵形式

code是opencv中色彩空间定义的宏常量,展示了我们要图像转换所要达到的结果,常用的有COLOR_BGR2GRAY、COLOR_GRAY2BGR、COLOR_BGR2HSV、COLOR_BGR2RGB等,但是实际上可以调用的参数多达247种。

dstCn为目标图像的通道数,如果设置为0,会自动从源图像计算目标图像的通道数;

以下是代码实例

    from numpy import *
    import numpy as np
    import cv2
    
    # 将图片转为灰度图
    src_image = cv2.imread("test.jpg")
    gray_imagee = cv2.cvtColor(src_image, cv2.COLOR_BGR2GRAY)
    # 将图片转为HSV
    hsv_image = cv2.cvtColor(src_image, cv2.COLOR_BGR2HSV)
    # 展示一下
    cv2.imshow("src_image", src_image)
    cv2.imshow("gary_image", gray_imagee)
    cv2.imshow("hsv_image", hsv_image)
    cv2.waitKey(0)

src_iamge
在这里插入图片描述

hsv_image

在这里插入图片描述

gary_iamge

在这里插入图片描述

这样显示在显示器有点大,也可以写入

通过cv2.imwrite(“1.jpg”,hsv_iamge)函数来进行文件的保存然后查看会好一点

画矩形

rectangle()用法:

    cv2.rectangle(img, pt1, pt2, color, thickness, lineType, shift)

参数说明:

  • img:在哪个图像上画线

  • pt1, pt2:开始点, 结束点:指定线的开始与结束位置

  • color:颜色

    • (0, 0, 255):红

    • (0, 255, 0):绿

    • (255, 0, 0):蓝

  • thickness:线宽

  • lineType:线型(可取值-1, 4, 8, 18), 默认为8

  • shift:坐标缩放比例

代码

    # 画矩形
    img = np.zeros((480, 640, 3), np.uint8)
    
    cv2.rectangle(img, (20, 20), (400, 400), (0, 255, 0), 5)
    
    cv2.imshow('draw', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示

在这里插入图片描述

画圆

circle()用法:

cv2.circle()(img, center, radius, color, thickness, lineType, shift)

参数说明:

  • img:在哪个图像上绘制圆

  • center:圆心坐标

  • radius:半径大小

  • color:颜色

  • thickness:线宽

  • lineType:线型

  • shift:坐标缩放比例

代码

    # 画圆
    img = np.zeros((480, 640, 3), np.uint8)
    
    cv2.circle(img, (320, 240), 100, (255, 0, 0), 5, 16)
    
    cv2.imshow('draw', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示

在这里插入图片描述

画椭圆

ellipse()用法:

cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType, shift)

参数说明:

  • img:在哪个图像上绘制椭圆

  • center:中心点

  • axes:长宽的一半

  • angle:角度

  • startAngle:从哪个角度开始

  • endAngle:从哪个角度结束

  • color:颜色

  • thickness:线宽

  • lineType:线型

  • shift:坐标缩放比例

代码

    # 画椭圆
    img = np.zeros((480, 640, 3), np.uint8)
    
    cv2.ellipse(img, (320, 240), (100, 50), 0, 0, 360, (255, 255, 255), 5, 16)
    
    cv2.imshow('draw', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示
在这里插入图片描述

画线段

line()用法:

cv2.line(img, pt1, pt2, color, thickness, lineType, shift)

参数说明:

line()用法rectangle()用法 完全一致。

代码

    # 画线段
    img = np.zeros((480, 640, 3), np.uint8)
    
    # 划线, 坐标点(x, y)
    cv2.line(img, (20, 20), (400, 400), (0, 0, 255), 5, 16)
    
    cv2.imshow('draw', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示

在这里插入图片描述

画和填充多边形

polylines():绘制多边形

cv2.polylines(img, pts, isClosed, color, thickness, lineType, shift)

参数说明:

  • img:在哪个图像上绘制和填充多边形

  • pts:多边形的点集,必须是int32位

  • isClosed:是否闭合

  • color:颜色

  • thickness:线宽

  • lineType:线型

  • shift:坐标缩放比例

代码

    img = np.zeros((480, 640, 3), np.uint8)
    
    pts = np.array([(300, 10), (150, 100), (450, 100)], np.int32)
    cv2.polylines(img, [pts], True, (0, 255, 255), 5, 16)
    
    cv2.imshow('draw', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示

在这里插入图片描述

fillPoly:填充多边形

cv2.fillPoly(img, pts, color)

fillPoly用法polylines用法 完全一致。

代码

    img = np.zeros((480, 640, 3), np.uint8)
    
    pts = np.array([(300, 10), (150, 100), (450, 100)], np.int32)
    cv2.fillPoly(img, [pts], (0, 255, 255), 16)
    
    cv2.imshow('draw', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

效果展示

在这里插入图片描述

绘制文字

putText:绘制文字

    putText(img,text,org,fontFace,fontScale,color,thickness,lineType,bottomLeftOrigin)

参数说明:

  • text要绘制的文字内容

  • org 文字在画布中的左下角坐标

  • fontFace 字体样式

  • fontScale 字体大小

  • lineType 线型

  • bottomLeftOrigin 绘制文字时的方向

代码

    import numpy as np # 导入Python中的numpy模块
    import cv2
    
    # np.zeros():创建了一个画布
    # (100, 300, 3):一个100 x 300,具有3个颜色空间(即Red、Green和Blue)的画布
    # np.uint8:OpenCV中的灰度图像和RGB图像都是以uint8存储的,因此这里的类型也是uint8
    canvas = np.zeros((100, 300, 3), np.uint8)
    # 在画布上绘制文字“mrsoft”,文字左下角的坐标为(20, 70)
    # 字体样式为FONT_HERSHEY_TRIPLEX
    # 字体大小为2,线条颜色是绿色,线条宽度为5
    cv2.putText(canvas, "sorry", (20, 70), cv2.FONT_HERSHEY_TRIPLEX, 2, (0, 255, 0), 5)
    cv2.imshow("Text", canvas) # 显示画布
    cv2.waitKey()
    cv2.destroyAllWindows()

效果展示

在这里插入图片描述

为图像添加边框

copyMakeBorder:为图像添加边框

    cv.copyMakeBorder(src, top, bottom, left, right, borderType, None, value)

参数说明:

  • src: 即将被扩充边界的原始图像

  • top, bottom, left, right: 在图像上、下、左、右分别要扩充的行(列)数

  • borderType: 扩充的边界类型

    • cv2.BORDER_CONSTANT: 用常数像素值填充扩充的边界(0或黑色)

    • cv2.BORDER_REPLICATE: 原始边缘的行或列被复制到扩充的边界

  • value: 当使用cv.BORDER_CONSTANT时,设置的要填充的像素值

代码

    import cv2
    import numpy as np
    from matplotlib import pyplot as plt
    
    BLUE = [255, 0, 0]
    img1 = cv2.imread('test.jpg')
    
    replicate = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_REPLICATE)
    reflect = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_REFLECT)
    reflect101 = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_REFLECT_101)
    wrap = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_WRAP)
    constant = cv2.copyMakeBorder(img1, 100, 100, 100, 100, cv2.BORDER_CONSTANT, value=BLUE)
    
    plt.subplot(231), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')
    plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
    plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
    plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
    plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
    plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
    plt.show()

效果展示

在这里插入图片描述

轮廓检测和画出轮廓

findContours:轮廓检测:

contours,hierarchy =cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])  

参数说明:

  • image:参数是寻找轮廓的图像;

  • mode:参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):

    • cv2.RETR_EXTERNAL:表示只检测外轮廓

    • cv2.RETR_LIST:检测的轮廓不建立等级关系

    • cv2.RETR_CCOMP:建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。

    • cv2.RETR_TREE:建立一个等级树结构的轮廓。

  • method:轮廓的近似办法:

    • cv2.CHAIN_APPROX_NONE:存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1

    • cv2.CHAIN_APPROX_SIMPLE:压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息

    • cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法

返回值:

cv2.findContours()函数返回两个值,一个是轮廓本身,还有一个是每条轮廓对应的属性。

  • contour返回值: 返回一个list,list中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。

  • hierarchy返回值: 返回一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓 c o n t o u r s [ i ] contours[i] contours[i]对应4个hierarchy元素 h i e r a r c h y [ i ] [ 0 ] h i e r a r c h y [ i ] [ 3 ] hierarchy[i][0] ~hierarchy[i][3] hierarchy[i][0] hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数

drawContours:画出轮廓

drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None):

参数说明:

  • Image:输入原始的图像;

  • Contours:坐标点(这个根据查找轮廓函数即可得到);

  • contourIdx;设置轮廓的顺序号;-1表示绘制所有的轮廓;

  • Color:绘制使用的颜色;

  • Thickness:绘制使用的线宽;-1表示全部填充;

  • lineType:绘制使用的线类型;

  • Hierarchy:设置层级;

  • maxLevel:如果为0,则仅绘制指定的轮廓。

    • 如果为1,则函数将绘制轮廓和所有嵌套轮廓。如果为2,则函数绘制等高线、所有嵌套等高线、所有嵌套到嵌套等高线,等等。这仅当存在可用的层次结构时,才考虑参数。
  • Offset:将所有绘制的轮廓移动指定的量。

代码

    import cv2
    
    img = cv2.imread('test.jpg')
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
    
    
    # 检测轮廓
    contours, hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    
    # 画轮廓
    cv2.drawContours(img, contours, -1, (0, 0, 255), 3)
    
    cv2.imshow("img", img)
    cv2.waitKey(0)

效果展示

?

四、实验结果

实验结果已经在实验过程中写出,实验结果的所有截图均可在实验过程中查看,这里不做过多展示

五、实验结论

在本实验中,涵盖了NumPy数组操作和OpenCV图像处理两个重要方面。在NumPy数组操作部分,学到了如何使用 NumPy 创建各种类型的数组,包括一维数组、二维数组等,以及如何访问和修改数组中的元素,了解了数组对象的一些属性,比如形状、大小等,以及数组对象的一些方法,比如求和、平均值、最大值、最小值等,学习了如何改变数组的形状,包括改变维度、转置数组、重塑数组等操作,通过学习 reshape、transpose、rollaxis、swapaxes 等函数实现了这些操作,以及掌握了如何使用索引和切片对数组进行元素的访问和修改,包括基本索引、切片索引、布尔索引等方法。在opencv图像处理部分,了解了如何在OpenCV中实现图像的颜色空间转换,这对于图像处理中很多任务都是必不可少的;学习到如何在图像上绘制基本的几何图形,在图像上添加文字,以及如何为图像添加边框以及使用OpenCV查找图像中的轮廓,对OpenCV图像处理模块的功能和应用有了更深入的理解。通过本实验的学习,深入理解了 NumPy 数组的概念、数组的重塑和操作方法,加深了对数组运算和操作的理解。同时,还学习了OpenCV图像处理模块的功能和应用,掌握了实现颜色变换、绘制基本图形、文字绘制、为图像添加边框以及在图像中查找轮廓等技术。为后续更复杂的数据、图像处理和科学计算打下了良好的基础。

文章来源:https://blog.csdn.net/y_k_j_c/article/details/134842441
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。