Python OpenCV 入门篇

51 阅读11分钟

openCV包含的模块

  • 最上层——>最底层: OpenCV和操作系统的交互 OpenCV Contrib模块 语言绑定和示例应用程序 OpenCV的核心 用于解决计算机视觉面临的难题的方法 OpenCV HAL 基于硬件加速层的各种硬件优化
  • OpenCV常用的模块及其说明

image.png

OpenCV图像操作

import cv2

#读取图像
image = cv2.imread('elysia.png', 1)
'''
image = cv2.imread(filename,flags)
image:imread()方法的返回值,返回的是读取到的图像,是一个numpy数组。
filename:图像的路径文件名,路径不能有中文,"D:/3.1.jpg"等价于"D:\\3.1.jpg"。
。支持多种图片格式。
flags:指定图像的读取方式,有以下几种:
1 cv2.IMREAD_COLOR:读取彩色图像,包括BGR三通道。
0 cv2.IMREAD_GRAYSCALE:读取灰度图像。
-1 cv2.IMREAD_UNCHANGED:读取图像包括 alpha 通道。
默认情况下,imread()方法读取彩色图像.
'''
print(image)  #打印图像像素矩阵

#显示图像
cv2.imshow('elysia', image)  #在名为elysia的窗口中显示image图像
cv2.waitKey()  #按下任意按键后
# cv2.destroyAllWindows()  #销毁所有窗口
'''
cv2.imshow(winname, mat)
winname:窗口的名称。
mat:要显示的图像。
retval=cv2.waitKey(delay)
delay:等待时间,单位毫秒。
retval:按下按键的ASCII码值。
destroyAllWindows()
销毁所有窗口。
'''

#保存图像
cv2.imwrite('elysia_gray.png', image)  #保存灰度图像
'''
cv2.imwrite(filename, img)
filename:要保存的图像路径。
img:要保存的图像。
'''

#获取图像属性
print(image.shape)  #彩色图像返回一个数组(垂直像素,水平像素,通道数),灰度图像返回一个数组(垂直像素,水平像素)
print(image.size)  #图像像素个数,值为“水平像素*垂直像素*通道数”彩色图像返回3通道像素个数,灰度图像返回1通道像素个数
print(image.dtype)  #获取图像数据类型

#像素的操作
px = image[500,500]#坐标(500,500)处的像素值
print("坐标(1256,707)处的像素值:",px)#彩色输出BGR值,灰度输出灰度值
blue = image[500,500,0]#坐标(500,500)处的蓝色通道值
green = image[500,500,1]#坐标(500,500)处的绿色通道值
red = image[500,500,2]#坐标(500,500)处的红色通道值
print(blue,green,red)
'''
image[500,500,?]中0表示B通道,1表示G通道,2表示R通道。
'''

#修改像素的BGR值或灰度值
px = [255,255,255]
# px = 255
print("修改后image[500,500]处的像素值:",px)

#修改指定区域的像素值
for i in range(241,292):#i表示横坐标,在区间[241,292]内取值
    for j in range(168,219):#j表示纵坐标,在区间[168,219]内取值
        image[i,j] = [255,255,255]#把区域内的像素值改为白色
cv2.imshow('elysia', image)#显示修改后的图像
cv2.waitKey()
cv2.destroyAllWindows()

使用NumPy模块操作像素

  • 数组的类型

image.png

#使用NumPy模块操作像素
import numpy as np
'''
numpy.array(object,dtype,copy,order,subok,ndmin)
object:数组或嵌套的数列。
dtype:数组元素的数据类型,可选。
copy:布尔值,默认是True,表示是否复制对象。
order:创建数组的样式,C为行方向,F为列方向,A为任意方向(默认)K(元素在内存中的出现顺序)。
subok:布尔值,默认是False,表示返回一个与基类类型一致的数组。
ndmin:指定生成数组的最小维度,默认是0。
'''
n1 = np.array([1,2,3])#创建1维数组
n2 = np.array([0.1,0.2,0.3])#创建包含小数的一维数组
n3 = np.array([[1,2],[3,4]])#创建二维数组

list = [1,2,3]
#创建浮点型数组
n4 = np.array(list,dtype=np.float_)
#或者
n5 = np.array(list,dtype=float)
print(n4,n5)
print(n4.dtype,n5.dtype)
print(type(n4[0]),type(n5[0]))#输出数组元素的数据类型和元素类型

#创建三维数组
nd1 = [1,2,3]
nd2 = np.array(nd1,ndmin=3)
print(nd2)

#创建指定维度和数据类型未初始化的数组
n6 = np.empty([2,3])
print(n6)

#创建纯0数组
n7 = np.zeros((3,3),np.uint8)
print(n7)

#创建纯1数组
n8 = np.ones((3,3),np.uint8)
print(n8)

#创建随机数组
'''
numpy.random.randint(low,high,size)
low:整数,数组元素的最小值。
high:整数,数组元素的最大值。
size:元组,数组的维度。
'''
n9 = np.random.randint(1,3,10)
print("随机生成10个1-3之间且不包括3的整数:",n9)
n10 = np.random.randint(5,10)
print("size数组大小为空随机返回一个整数:",n10)
n11 = np.random.randint(5,size=(2,5))
print("随机生成5以内二维数组:",n11)

#操作数组
n12 = np.array([1,2])
n13 = np.array([3,4])
print("数组相加:",n12+n13)
print("数组相减:",n12-n13)
print("数组相乘:",n12*n13)
print("数组相除:",n12/n13)
print("两个数组做幂运算",n12**n13)

#比较运算
print(n12>=n13)#大于等于
print(n12==n13)#等于
print(n12<=n13)#小于等于
print(n12!=n13)#不等于

#复制数组
# n13 = np.array(n12,copy=True)
n13 = n12.copy()
print(n12==n13)
n12[0] = 9
print(n12==n13)

#数组索引和切片
'''
[start:stop:step]
start:整数,切片起始位置,默认为0。
stop:整数,切片结束位置,默认为数组长度。
step:整数,切片步长,默认为1。
'''
#一阶数组索引
n14 = np.array([0,1,2,3,4,5,6,7,8,9])
print(n14[0])
print(n14[1])
print(n14[0:2])
print(n14[1:])
print(n14[:2])
print(n14[::2])#步长为2
print(n14[::-1])#逆序
print(n14[::])
print(n14[:])
print(n14[-5::-1])#从倒数第5个元素开始到第一个元素,步长为-1

#二阶数组索引
n15 = np.array([[0,1,2,3],[4,5,6,7],[8,9,10,11]])
print(n15)
print(n15[1])
print(n15[1,2])#第二行第三列元素
print(n15[-1])#最后一行
#二维数组切片
print(n15[:2,1:])#第一行到第二行,第二列到最后一列
print(n15[1,:2])#第二行,第一列到第二列
print(n15[:2,2])#第一行到第二行,第三列
print(n15[:,:1])#第一列
  • 在OpenCV中,黑白图像实际上就是一个二维数组,彩色图像是 一个三维数组。数组中每个元素就是图像对应位置的像素值。因此修 改图像像素的操作实际上就是修改数组的操作。

使用NumPy操作图像

import cv2
import numpy as np

width = 500  # 图像宽度
height = 200  # 图像高度
#创建一个指定宽高、单通道、像数值都为0的图像
img1 = np.zeros((height,width),np.uint8)
cv2.imshow("img1",img1)
cv2.waitKey()
#创建一个指定宽高、单通道、像数值都为1的图像
img2 = np.ones((height,width),np.uint8)*255#*255表示将图像像素值乘以255,使其变成纯白图像
cv2.imshow("img2",img2)
cv2.waitKey()
#在黑白图像里绘制白黑矩阵
img1[25:75,50:100]=255
cv2.imshow("img3",img1)
cv2.waitKey()
img2[25:75,50:100]=0
cv2.imshow("img4",img2)
cv2.waitKey()
#创建黑白相间的图像
img3 = np.zeros((height,width),np.uint8)
for i in range(0,width,40):#每隔40个像素绘制一个黑色像素
    img3[:,i:i+20]=255  #白色区域的宽度为20像素
cv2.imshow("img5",img3)
cv2.waitKey()
#创建彩色图像
img4 = np.zeros((height,width,3),np.uint8)
blue = img4.copy()
blue[:,:,0]=255  #将图像的蓝色通道设置为255,使其变成纯蓝图像
green = img4.copy()
green[:,:,1]=255  #将图像的绿色通道设置为255,使其变成纯绿图像
red = img4.copy()
red[:,:,2]=255  #将图像的红色通道设置为255,使其变成纯红图像
cv2.imshow("img6-blue",blue)
cv2.waitKey()
cv2.imshow("img6-green",green)
cv2.waitKey()
cv2.imshow("img6-red",red)
cv2.waitKey()
#创建随机图像
img5 = np.random.randint(256,size=(height,width,3),dtype=np.uint8)
cv2.imshow("img7",img5)
cv2.waitKey()

#拼接图像
'''
array = numpy.hstack(tup)
tup:要拼接的数组元组,每个数组的形状必须相同
array:将参数元组中的数组水平拼接成一个新数组
'''
a = np.array([1,2,3])
b = np.array([4,5,6])
c = np.array([7,8,9])
result1 = np.hstack((a,b,c))
print("水平拼接数组",result1)
'''
array = numpy.vstack(tup)
tup:要拼接的数组元组,每个数组的形状必须相同
array:将参数元组中的数组垂直拼接成一个新数组
'''
result2 = np.vstack((a,b,c))
print("垂直拼接数组",result2)
#拼接图像
img_h = np.hstack((blue,green,red))
img_v = np.vstack((blue,green,red))
cv2.imshow("img8-hstack",img_h)
cv2.waitKey()
cv2.imshow("img8-vstack",img_v)
cv2.waitKey()

cv2.destroyAllWindows()

色彩空间和通道

  • 虽然Photoshop把一幅彩色图像的色彩空间默认为RGB色彩空间, 但是OpenCV把一幅彩色图像的色彩空间默认为BGR色彩空间,这是 因 为 OpenCV 拆 分 一 幅 彩 色 图 像 的 通 道 后 , 默 认 的 通 道 顺 序 是 B→G→R。
  • GRAY色彩空间

GRAY色彩空间通常指的是灰度图像,灰度图像是一种每个像素 都是从黑到白,被处理为256个灰度级别的单色图像。这256个灰度级 别分别用区间[0, 255]中的数值表示。其中,“0”表示纯黑色,“255”表 示纯白色,0~255的数值表示不同亮度(即色彩的深浅程度)的深灰 色或者浅灰色。

  • HSV色彩空间

BGR色彩空间是基于三基色而言的,三基色指的是红色、绿色和 蓝色。而HSV色彩空间则是基于色调、饱和度和亮度而言的。 其中,色调(H)是指光的颜色,例如,彩虹中的赤、橙、黄、 绿、青、蓝、紫分别表示不同的色调,例如,代表红色、黄色、绿色和蓝色的色 调值分别为0、30、60和120。 饱和度(S)是指色彩的深浅。在OpenCV中,饱和度在区间[0, 255]内取值。当饱和度为0时,图像将变为灰度图像。亮度(V)是指光的明暗。与饱和度相同,在 OpenCV中,亮度在区间[0, 255]内取值。亮度值越大,图像越亮;当 亮度值为0时,图像呈纯黑色。

  • alpha通道

BGR色彩空间包含了3个通道,即B通道、G通道和R通道。 OpenCV在BGR色彩空间的基础上,又增加了一个用于设置图像透明 度的A通道,即alpha通道。这样,形成一个由B通道、G通道、R通道 和A通道4个通道构成的色彩空间,即BGRA色彩空间。在BGRA色彩 空间中,alpha通道在区间[0, 255]内取值;其中,0表示透明,255表示 不透明。

# 色彩空间和通道
import cv2
import numpy as np

#从BGR色彩空间转换到GRAY色彩空间
'''
dst = cv2.cvtColor(src,code)
dst:转换后的图像
src:初始图象
code:色彩空间转换码
'''
image = cv2.imread("elysia.png")
cv2.imshow("Original",image)
gary_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow("GRAY",gary_image)
cv2.waitKey()
#从BGR色彩空间转换到HSV色彩空间
hsv_image = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
cv2.imshow("HSV",hsv_image)
cv2.waitKey()

#通道
#拆分BGR通道
'''
b,g,r = cv2.split(bgr_image)
b:蓝色通道
g:绿色通道
r:红色通道
bgr_image:一幅BGR图像
'''
b,g,r = cv2.split(image)
cv2.imshow("Blue",b)
cv2.imshow("Green",g)
cv2.imshow("Red",r)
cv2.waitKey()
#拆分HSV通道
'''
h,s,v = cv2.split(hsv_image)
h:色调通道
s:饱和度通道
v:明度通道
hsv_image:一幅HSV图像
'''
h,s,v = cv2.split(hsv_image)
cv2.imshow("Hue",h)
cv2.imshow("Saturation",s)
cv2.imshow("Value",v)
cv2.waitKey()
#合并BGR通道
'''
bgr = cv2.merge([b,g,r])
bgr:按BGR顺序合并后的图像
b:蓝色通道
g:绿色通道
r:红色通道
'''
bgr = cv2.merge([b,g,r])
cv2.imshow("BGR",bgr)
cv2.waitKey()
#合并HSV通道
'''
hsv = cv2.merge([h,s,v])
hsv:按HSV顺序合并后的图像
h:色调通道
s:饱和度通道
v:明度通道
'''
hsv2 = cv2.merge([h,s,v])
cv2.imshow("HSV2",hsv2)
cv2.waitKey()
#综合运用拆分通道和合并通道
h[:,:]=180#将H通道设置为180
# v[:,:]=255#将V通道设置为255
# s[:,:]=255#将S通道设置为255
hsv3 = cv2.merge([h,s,v])
bgr2 = cv2.cvtColor(hsv3,cv2.COLOR_HSV2BGR)
cv2.imshow("BGR2",bgr2)
cv2.waitKey()

#alpha通道
bgra_image = cv2.cvtColor(image,cv2.COLOR_BGR2BGRA)
cv2.imshow("BGRA",bgra_image)
b,g,r,a = cv2.split(bgra_image)
a[:,:]=172#将A通道设置为172
bgra_172 = cv2.merge([b,g,r,a])
a[:,:]=0#将A通道设置为0
bgra_0 = cv2.merge([b,g,r,a])
cv2.imshow("BGRA_172",bgra_172)
cv2.imshow("BGRA_0",bgra_0)
cv2.waitKey()
cv2.imwrite("bgra_0_elysia.png",bgra_0)
cv2.imwrite("bgra_172_elysia.png",bgra_172)
#PNG图像是一种典型的4通道(即B通道、G通道、R通道和A通 道)图像,因此被保存的3幅图像的格式均为.png
cv2.destroyAllWindows()

虽然色彩空间类型转换是双向的,而且OpenCV也提供了 cv2.COLOR_GRAY2BGR(从GRAY色彩空间转换到BGR色彩空 间)和cv2.COLOR_ BGR2GRAY(从BGR色彩空间转换到GRAY色 彩空间)2个色彩空间转换码,但是灰度图像是无法转换成彩色图像 的。这是因为在彩色图像转换成灰度图像的过程中,丢失了颜色比 例(即红色、绿色和蓝色之间的混合比例)。这些比例一旦丢失, 就再也找不回来了。

  • 小结:

当使用cvtColor()方法转换色彩空间时,虽然彩色图像能够转换为 灰度图像,但是灰度图像不能转换为彩色图像。对于HSV色彩空间, 如果保持其中两个通道的值不变,调整第3个通道的值,会得到相应的 艺术效果。为了能够显示艺术效果,要把合并通道后的图像从HSV色 彩空间转换到BGR色彩空间。当使用alpha通道设置图像的透明度时, 为了能够直观地看到图像的透明效果,需先保存已经设置透明度的图像。

以上内容摘自明日科技《Python OpenCV从入门到精通》一书