本章简明
像素获取:
确定像素的位置
获取像素的BGR值
修改像素的BGR值
使用NumPy模块操作像素:
NumPy模块概述
数组的类型
创建数组:array()方法
操作数组
数组的索引和切片
创建图像
拼接图像
讲解
像素点的获取
我们要如何获取图片中指定位置的像素点信息呢?在Windows下Python-openCV学习(二)-------图像处理基本操作中我们使用cv2.imread方法打开一个图像,其返回值就是图片的相关信息。
我们用画图打开一张图片,可以看到长像素范围为(0,1913),宽像素范围为(0,874)
我们可以建立这样一个坐标系来表示每一个像素点。
Y轴(0,1913),X轴(0,874),那么像素点的位置就可表示为 (Y,X)。我们选取(1913,974)点作为目标点。
下面看一下如何获取这个像素点的信息:
import cv2
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
px=image[1913,974]
print(px)
运行:
报错提示超出315长度限制,这说明我们使用画图软件打开的图片得到的图片像素大小是不准确的。
我们直接查看图片的文件属性
Y轴(0,314),X轴(0,235),那么像素点的位置就可表示为 (Y,X)。我们选取(314,235)点作为目标点。
再测试一下:
import cv2
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
px=image[314,235]
print(px)
输出
我们得到一个数组,[ 9 10 6]。这就是这个像素点的BGR值(就是RGB值,只是顺序翻了)。
还记得上章的这一段代码嘛:
import cv2
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
print("图像的shape属性",image.shape)
print("图像的size属性",image.size)
print("图像的数据类型",image.dtype)
输出:
图像的shape属性 (315, 236, 3)
图像的size属性 223020
图像的数据类型 uint8
可以看到shape属性中第一个就是垂直像素,第二个水平像素,第三个通道数目。这里通道数为3是因为彩色图片都是由三基色(红绿蓝)构成,每种颜色表示一个通道,所以彩色图片通道数为3。openCV中是三基色的排列顺序是蓝绿红,既是BGR。按顺序存放在列表中,因此我们可以对获取像素点BGR的代码如下优化,读取指定颜色通道的数值。
import cv2
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
bx=image[314,235,0]
gx=image[314,235,1]
rx=image[314,235,2]
print(f'像素点B值 {bx}')
print(f'像素点G值 {gx}')
print(f'像素点R值 {rx}')
输出:
像素点B值 9
像素点G值 10
像素点R值 6
操作像素点
上面我们已经学习了如何获取像素点信息,下面我们看看如何来操作像素点,实质就是修改图片像素点的RGB数值。
修改一个像素点的信息比较难以观察,我们修改上图中那个矩形中的像素点信息。
对于BGR色彩空间的图像,BGR三通道数值相等时就可以得到灰度图像
其中三通道都为0为纯黑色,三通道都为255为纯白色
import cv2
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
for i in range(image.shape[0]-20,image.shape[0]):
for j in range(image.shape[1]-20,image.shape[1]):
image[i,j]=[255,255,255]
cv2.imshow("text",image)
cv2.waitKey()
cv2.destroyAllWindows()
运行:
使用NumPy模块操作像素
什么是NumPy?
NumPy 是一个 Python 包。 它代表 “Numeric Python”。 它是一个由多维数组对象和用于处理数组的例程集合组成的库。
Numeric,即 NumPy 的前身,是由 Jim Hugunin 开发的。 也开发了另一个包 Numarray ,它拥有一些额外的功能。 2005年,Travis Oliphant 通过将 Numarray 的功能集成到 Numeric 包中来创建 NumPy 包。 这个开源项目有很多贡献者。
NumPy是C语言实现的,所以其运算速度非常快。具体功能如下:
1、有一个强大的N维数组对象ndarray
2、广播功能方法
3、线性代数、傅里叶变换、随机数生成、图形操作等
4、整合C/C++/Fortran代码工具
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_
float_ 是float64 类型的简写
---------------------------------------------------------------------------------------------
float16
半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32
单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64
双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_
complex128 类型的简写,即 128 位复数
complex64
复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128
复数,表示双 64 位浮点数(实数部分和虚数部分)
使用NumPy创建数组
1、常规array方法
numpy.array(object,dtype,copy,order,subok,ndmin)
参数:
object :任何具有数组接口方法的对象
dtype : 数据类型
copy : 布尔型,可选参数。默认值为True,则object参数被复制;否则,只有当__array__返回副本,
object参数为嵌套序列,或者需要副本满足数据类型和顺序要求时,才会生成副本。
order : 元素在内存中出现的顺序,其值为K,A,C,F。如果object参数不是数组,则新创建的数组将按行排
列(C),如果值为F,按列排列;如果object参数是一个数组,则以下顺序成立:
C(按行) F(按列) A(原顺序) F(元素在内存中出现的位置)。
subok : 默认情况下,返回的数组被强制为基类数组。 如果为true,则返回子类。
ndmin : 指定生成数组的最小维数
下面我们来看几个小例子:
1.1 创建一维数组和二维数组
import numpy as np
n1=np.array([1,2,3])
n2=np.array([[1,2],[3,4]])
print("一维数组")
print(n1)
print("二维数组")
print(n2)
输出:
一维数组
[1 2 3]
二维数组
[[1 2]
[3 4]]
1.2 创建指定类型数组
#创建浮点类型数组
import numpy as np
stl=[1,2,3]
n1=np.array(stl,dtype=np.float_)
print(n1)
输出
[1. 2. 3.]
1.2 创建三维数组
方法一
import numpy as np
n1=np.array([[[1,2,3],[4,5,6]]])
print(n1)
方法二
import numpy as np
n1=np.array([1,2,3],ndmin=3)
print(n1)
输出
[[[1 2 3]]]
2、创建指定维度和数据类型未初始化数组
numpy.empty(shape, dtype, order)
参数:
shape :int 或 int的tuple
空数组的Shape,例如,(2, 3)或2
dtype :data-type, 可选
数组所需的输出数据类型,例如, numpy.int8 默认值为numpy.float64.
order :{‘C’, ‘F’}, 可选, 默认: ‘C’
是否以行优先(C样式)或列优先(Fortran样式)的顺序存储多维数据在内存中。
创建一个未初始化的,两行三列未初始化,int类型数组
import numpy as np
n1=np.empty((2,3),dtype=np.int_)
print(n1)
输出
[[-707327008 32764 -707322496]
[ 32764 0 0]]
3、创建纯0填充的数组
numpy.zeros(shape, dtype=float, order='C')
参数:
shape:int或int元组
新阵列的形状,例如,或。(2, 3)2
dtype:数据类型,可选
数组的所需数据类型,例如numpy.int8。默认是 numpy.float64。
order : {'C','F'},可选,默认:'C'
是否在内存中以行主(C风格)或列主(Fortran风格)顺序存储多维数据。
创建三行三列数据类型为无符号整形的纯0数组
import numpy as np
n1=np.zeros((3,3),dtype=np.uint8)
print(n1)
输出:
[[0 0 0]
[0 0 0]
[0 0 0]]
4、创建纯1填充数组
numpy.ones(shape, dtype=float, order='C')
shape : int或int的序列
新数组的形状,例如,(2, 3)或2
dtype : 数据类型,可选
数组的所需数据类型,例如numpy.int8。默认是 numpy.float64。
order : {'C','F'},可选,默认值:C
是否在内存中以行主(C-风格)或列主(Fortran-风格)顺序存储多维数据。
创建三行三列数据类型为无符号整形的纯1数组
import numpy as np
n1=np.ones([3,3],dtype=np.uint8)
print(n1)
输出
[[1 1 1]
[1 1 1]
[1 1 1]]
5、创建随机数组
np.random.randint(low,high,size)
参数:
low:随机数最小取值范围
high:可选参数,随机数最大取值范围,若high为空,取值范围为(0,low),不为空为(low,high).
high>low
size:可选参数,数组维度
随机生成10个1~3且不包括3的整数
import numpy as np
n1=np.random.randint(1,3,10)
print(n1)
输出
[2 1 1 2 2 2 1 1 1 2]
随机生成1~3,以内的二维数组
import numpy as np
n1=np.random.randint(1,3,size=(2,3))#两行三列
print(n1)
输出:
[[1 2 2]
[2 2 1]]
操作数组
1、加减乘除幂运算
import numpy as np
n1=np.array([1,2],dtype=np.float_)
n2=np.array([3,4],dtype=np.float_)
print(f'n1:\n{n1}')
print(f'n2:\n{n2}')
print('----')
print(f'n1+n2 \n{n1+n2}')
print('----')
print(f'n2-n1 \n{n2-n1}')
print('----')
print(f'n1*n2 \n{n1*n2}')
print('----')
print(f'n2/n1 \n{n2/n1}')
print('----')
print(f'n1**n2 \n{n1**n2}')
输出
n1:
[1. 2.]
n2:
[3. 4.]
----
n1+n2
[4. 6.]
----
n2-n1
[2. 2.]
----
n1*n2
[3. 8.]
----
n2/n1
[3. 2.]
----
n1**n2
[ 1. 16.]
2、比较运算
import numpy as np
n1=np.array([1,2,3])
n2=np.array([4,5,6])
print(n1>=n2)
print(n1<=n2)
print(n1==n2)
print(n1!=n2)
输出
[False False False]
[ True True True]
[False False False]
[ True True True]
3、数组的复制
import numpy as np
n1=np.array([1,2,3])
n2=np.array(n1,copy=True)
print(n2==n1)
n2[1]=0
print(n1)
print(n2)
n2=n1.copy()#这种方法比较常用
print(n1==n2)
输出
[ True True True]
[1 2 3]
[1 0 3]
[ True True True]
数组的索引
1、一维数组索引
import numpy as np
n1=np.array([1,2,3])
n2=n1[0]
print(n2)
输出
1
2、一维数组切片索引
[起始索引,终止索引,步长]
起始索引 :不写任何值表示从0开始
终止索引 :不写任何值表示到末尾全部索引
[起始索引,终止索引),注意是左闭右开
示例
import numpy as np
n1=np.array([0,1,2,3,4,5,6,7,8,9])
print(n1)
print(n1[:3])
print(n1[3:6])
print(n1[5:])
print(n1[3:6:2])
print(n1[::])
print(n1[:])
print(n1[::2])
print(n1[2::2])
print(n1[::-1])
print(n1[-1:-4:-1])#n1[-1:-4]这种写法是错误的,步长默认是1不是-1
print(n1[-3::-1])
输出
[0 1 2 3 4 5 6 7 8 9]
[0 1 2]
[3 4 5]
[5 6 7 8 9]
[3 5]
[0 1 2 3 4 5 6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]
[0 2 4 6 8]
[2 4 6 8]
[9 8 7 6 5 4 3 2 1 0]
[9 8 7]
[7 6 5 4 3 2 1 0]
3、二维数组索引
arry[n,m]
n:行
m:列
示例
import numpy as np
n1=np.array([[0,1,2,3],[4,5,6,7],[8,9,10,11]])
print(n1)
print('-------')
print(n1[1])
print(n1[1,2])
print(n1[-1])
print(n1[-1,-1])
print('-------')
print(n1[:2,1:])
print('-------')
print(n1[1,:2])
print('-------')
print(n1[:2,2])
print('-------')
print(n1[:,:1])
输出
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
-------
[4 5 6 7]
6
[ 8 9 10 11]
11
-------
[[1 2 3]
[5 6 7]]
-------
[4 5]
-------
[2 6]
-------
[[0]
[4]
[8]]
创建图片
创建纯色图片,黑色
import cv2
import numpy as np
width=200
high=150
n1=np.ones((width,high),dtype=np.uint8)
cv2.imshow("text",n1)
cv2.waitKey()
cv2.destroyAllWindows()
输出
白色
import cv2
import numpy as np
width=200
high=150
n1=np.zeros((width,high),dtype=np.uint8)
print(n1)
n1[:,:]=255
cv2.imshow("text",n1)
cv2.waitKey()
cv2.destroyAllWindows()
创建黑白相间图像
import cv2
import numpy as np
high=500
width=500
n1=np.zeros((width,high),dtype=np.uint8)
print(n1)
for i in range(0,high,40):
n1[0:,i:i+20]=255
print(n1)
cv2.imshow("text",n1)
cv2.waitKey()
cv2.destroyAllWindows()
运行
创建彩色图片、
以上例子我们可以发现,黑白图像都是二维数组:
如下图:
在对应的点位设置对应的色彩值(0~255)即是黑白图像,也可以说灰度。毕竟只有一个通道。
那么彩色来说一个像素点包含三个通道,那么二维数组就无法满足要求。毕竟二维数组里面(x,y)确定的位置只有一个色彩值,那么我们就需要三维数组来表示彩色图片中的像素。
记住图像中像素的位置是二维坐标,(X,Y)。但是加上图片通道就是三维了。举个例子:
一个图片像素点坐标是(X,Y),那么他在三维坐标轴中表示的点有(X,Y,0)、(X,Y,1)、(X,Y,2)三个点
分别是0,1,2分别对应BGR三通道。
示例:随机彩色图片
import cv2
import numpy as np
high = 255
width = 255
n1 = np.random.randint(0,256,size=(width,high,3),dtype=np.uint8)
cv2.imshow("text", n1)
cv2.waitKey()
cv2.destroyAllWindows()
输出:
图片的拼接
1、水平拼接图像
array=numpy.hstack(tup)
参数:
tup:图片元组
返回值:拼接后新的图片数组
示例:
将两个图片水平拼接在一起
import cv2
import numpy as np
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
image2=image.copy()
image3=np.hstack((image,image2))
cv2.imshow("text",image3)
cv2.waitKey()
cv2.destroyAllWindows()
print("text")
输出:
2、垂直拼接
array=numpy.vstack(tup)
参数:
tup:图片元组
返回值:拼接后新的图片数组
示例:
两张图片垂直拼接
import cv2
import numpy as np
image = cv2.imread("D:/python_learn/opencv_learn/2.png",1)
image2=image.copy()
image3=np.vstack((image,image2))
cv2.imshow("text",image3)
cv2.waitKey()
cv2.destroyAllWindows()
print("text")
输出: