本文结构
- 图像处理的基本操作
- 读取图像
- imread()
- 显示图像
- imshow()
- waitKey()
- destroyAllWindows()
- 保存图像
- imwrite()
- 复制图像
- copy()
- 获取图像属性
- 像素
- 确定像素的位置
- 获取像素的BGR值
- 修改像素的BGR值
- 色彩空间
- GRAY色彩空间
- cvtColor()——从BGR色彩空间转换到GRAY色彩空间
- HSV色彩空间
- 从BGR色彩空间转换到HSV色彩空间
- 通道
- 拆分通道
- 拆分一幅BGR图像中的通道
- 拆分一幅HSV图像中的通道
- 合并通道
- 综合运用拆分通道和合并通道
- alpha通道
图像处理的基本操作
图像处理包括4个基本操作:读取图像、显示图像、保存图像和获取图像属性。
读取图像
imread()
image = cv2.imread(filename,flags)
- filename:目标图像的完整路径名。
- flags:图像的颜色类型的标记,有0和1两个值,其中1为默认值。当读取一幅彩色图像时,如果想要得到一幅彩色图像,那么flags的值为1(此时flags的值可以省略);想要得到一幅灰度图像则为0。
- image:是imread()方法的返回值,返回的是读取到的彩色图像或者灰度图像。
其实就是读取了一个存在filename路径的图片,然后用image去表示这个图片而已(image只是一个举例,你爱叫啥叫啥),flags是0还是1取决于你想要彩图还是灰白图。
实例1: 读取当前项目目录下的图像
在PyCharm中的Demos项目下,有一幅名为1.jpg的图像。
现在先使用imread()方法读取1.jpg,再使用print()方法打印1.jpg。代码如下所示:
import cv2 # 导入库
image = cv2.imread("1.jpg",1) # 读取1.jpg,等价于image = cv2.imread("1.jpg")
print(image) # 打印1.jpg
部分结果如下:
图中输出的数字是1.jpg的部分像素值。
如果图像存储在电脑C盘中,示例代码如下:
import cv2 #opencv读取的格式是BGR
img = cv2.imread('C:/Users/lenovo/Pictures/Saved Pictures/castle.jpg') # 路径中不能出现中文
print(image)
注意:“D:/1.jpg"等价于"D:\1.jpg”
显示图像
imshow()
imshow()方法用于显示图像:
cv2.imshow(winname,mat)
- winname: 显示图像的窗口名称。
- mat: 要显示的图像
waitKey()
waitKey()方法用于等待用户按下键盘上的某个按键时将执行waitKey()方法,并且获取与这个按键相对应的ASCII码:
retval = cv2.waitKey(delay)
- delay:等待用户按下键盘上按键的时间,单位为毫秒(ms)。当delay的值为负数,0或者空时,表示无限等待用户按下键盘上按键的时间。
- retval:与被按下的按键相对应的ASCII码。例如ESC键的ASCII码是27,当用户按下该键时,waitKey()方法的返回值为27.如果没有按键被按下,waitKey()方法的返回值是-1。
destroyAllWindows()
destroyAllWindows()方法用于销毁所有正在显示图像的窗口:
cv2.destroyAllWindows()
实例2: 窗口显示图像
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("image",image) # 在名为 image 的窗口中显示1.jpg
cv2.waitKey() # 按下任何键盘按键中
cv2.destroyAllWindows() # 销毁所有窗口
结果如下:
如果想设置窗口显示图像的时间为5s,示例代码如下:
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("image",image) # 在名为 image 的窗口中显示1.jpg
cv2.waitKey(5000) # 括号内单位为ms
cv2.destroyAllWindows() # 销毁所有窗口
注意:
- 显示图像的窗口名称不能是中文,否则会乱码。
- 为了能够正常显示图像,要在cv2.imshow()后紧跟着cv2.waitKey()。
保存图像
imwrite()
imwrite()可按照指定路径保存图像
cv2.imwrite(filename,img)
- filename: 保存图像时所用的完整路径
- img: 要保存的图像
实例3: 保存图像
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imwrite("D:/Pictures/1.jpg",image) # 把1.jpg保存为D盘根目录下,Pictures文件夹中的1.jpg
注意: 运行上述代码前,要在E盘根目录下新建一个空的Pictures文件夹
复制图像
copy()
在OpenCV中,图像是由二维数组或者三维数组表示的。因此,使用copy()方法除了能够复制数组外,还能够复制图像。
实例4:复制图像
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
copyImage = image.copy()
cv2.imshow("img",image)
cv2.imshow("copyImage",copyImage)
cv2.waitKey()
cv2.destroyAllWindows()
结果如下:
获取图像属性
处理图像的过程中,经常需要获取图像的大小、类型等图像属性。为此,OpenCV提供了shape、size和dtype这3个常用属性。
- shape: 如果是彩色图像,那么获取的是一个包含图像的像素行数、像素列数、通道数的数组,数组的格式为
(像素行数,像素列数,通道数)
;如果是灰度图像,那么获取的是一个包含图像的像素列数、像素行数的数组,数组的格式为(像素行数,像素列数)
。 - size: 获取的是图像包含的像素总数,其值为
像素行数×像素列数×通道数
(灰度图像的通道数为1) - dtype: 获取的是图像的数据类型
实例4: 打印彩色图像和灰度图像的属性
import cv2
image_Color = cv2.imread("1.jpg", 1) # 读取1.jpg
print("获取彩色图像的属性:")
print("shape =",image_Color.shape) #打印彩色图像的(像素行数,像素列数,通道数)
print("size =",image_Color.size) #打印彩色图像包含的像素总数
print("dtype =",image_Color.dtype) #打印彩色图像的数据类型
image_Gray = cv2.imread("1.jpg", 0) # 读取1.jpg的灰度图像
print("获取灰度图像的属性:")
print("shape =",image_Gray.shape) #打印灰度图像的(像素行数,像素列数)
print("size =",image_Gray.size) #打印灰度图像包含的像素总数
print("dtype =",image_Gray.dtype) #打印灰度图像的数据类型
结果如下:
像素
像素是构成数字图像的基本单位。将电脑上的一幅图片放大,会发现图像是由许多个小方块组成的,通常把一个小方块称作一个像素。因此,一个像素是具有一定面积的一个块,而不是一个点。需要注意的是,像素的形状是不固定的,大多数情况下,像素被认为是方形的,但有时也可能是圆形的或者是其他形状的。
确定像素的位置
在OpenCV中,正确表示图像中某个像素坐标的格式为 (y,x)
,方向示意图如下:
实例5: 表示图中的指定像素
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
px = image[50,30] # 坐标(50,30)上的像素
获取像素的BGR值
人眼能够感知红色、绿色和蓝色这3种不同的颜色,称为三基色。计算机利用色彩空间对颜色进行编码,把与“三基色”对应的色彩空间称作“RGB色彩空间”。
在RGB色彩空间种包含3个通道:R通道、G通道、B通道,分别代表红色通道、绿色通道、蓝色通道,每个通道都在区间[0,255]内进行取值。这样,计算机通过为这3个色彩通道取不同的值来表示不同的颜色。
OpenCV默认的通道顺序是B->G->R。也就是说,当OpenCV获取图像内某个像素的值时,这个值指的是这个像素的BGR值,OpenCV默认使用的色彩空间是BGR色彩空间。
在实例5中,凭借一个标签px就成功地表示了坐标(50,30)上的像素。如果使用print()方法打印这个像素,就会得到这个像素的BGR值。
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
px = image[50,30] # 坐标(50,30)上的像素,同时获取三个通道的值
blue = image[50, 30, 0] # 坐标(50,30)上的像素的B通道的值
green = image[50, 30, 1] # 坐标(50,30)上的像素的G通道的值
red = image[50, 30, 2] # 坐标(50,30)上的像素的R通道的值
print(px)
print(blue,green,red)
结果如下:
修改像素的BGR值
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
px = image[50, 30] # 坐标(50,30)上的像素
print("像素的初试BGR值是:",px)
px = [255,255,255] # 把坐标上的像素的值修改为[255,255,255]
print("像素修改后的BGR值是:",px)
结果如下:
当图像中的每个像素的B、G、R这3个数值相等时,就可以得到灰度图像。其中,当B = G = R = 0时,像素呈现纯黑色;当B = G = R = 255时,像素呈现纯白色。
实例6: 修改图像中的指定区域内的所有像素
在图像上设定4个点,将4个点围成的区域内的所有像素都修改为白色。
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
for i in range(241, 292): # i表示横坐标,在区间[241,291]内取值
for j in range(168, 219): # j表示纵坐标,在区间[168,218]内取值
image[i, j] = [255, 255, 255] # 把区域内的所有像素都修改为白色
cv2.imshow("img_02", image) # 显示像素被修改后的图像
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下:
色彩空间
上文中简单介绍了RGB色彩空间和BGR色彩空间。接下来将介绍在OpenCV中另外两个比较常见的色彩空间:GRAY色彩空间和HSV色彩空间。
GRAY色彩空间
GRAY色彩空间通常指的是灰度图像。灰度图像是一种每个像素都是从黑到白,被处理为256个灰度级别的单色图像。这256个灰度级别分别用区间[0,255]中的数值表示。“0”表示黑色,“255”表示白色,0~255之间的数值表示不同亮度(即色彩的深浅程度)的深灰色和浅灰色。
cvtColor()——从BGR色彩空间转换到GRAY色彩空间
OpenCV可以使用imread()方法把图片读取为灰度图像。除此之外,OpenCV还提供了cvtColor()方法用于转换图像的色彩空间。
dst = cv2.cvtColor(src,code)
- src: 转换色彩空间前的初始图象
- code: 色彩空间转换码
- dst: 转换色彩空间后的图像
当一幅彩色图像从BGR色彩空间转换到GRAY色彩空间时,需要使用的色彩空间转换码时cv2.COLOR_BGR2GRAY。
实例7: 从BGR色彩空间转换到GRAY色彩空间
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
# 将1.jpg从BGR色彩空间转换到GRAY色彩空间
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
cv2.imshow("GRAY", gray_image) # 显示灰度图像
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下;
虽然色彩空间类型转换是双向的,而且OpenCV也提供了cv2.COLOR_GRAY2BGR这个色彩空间转换码,但是灰度图像是无法转换成彩色图像的。这是因为在彩色图像转换成灰度图像的过程中,已经丢失了颜色比例。
HSV色彩空间
RGB色彩空间是基于三基色而言的,即红色、绿色和蓝色。而HSV色彩空间则是基于色调、饱和度和亮度而言的。
- 色调(H)是指光的颜色。OpenCV中,色调在区间[0,180]内取值。例如代表红色、黄色、绿色和蓝色的色调值分别为0、30、60和120。
- 饱和度(S)是指色彩的深浅。在OpenCV中,饱和度在[0,255]内取值。当饱和度为0时,图像将变为灰度图像。
- 亮度(V)是指光的明暗。与饱和度相同,在OpenCV中,亮度在区间[0,255]内取值。亮度值越大,图像越亮;当亮度值为0时,图像呈纯黑色。
从BGR色彩空间转换到HSV色彩空间
当一幅彩色图像从BGR色彩空间转换到HSV色彩空间时,需要使用的色彩空间转换码是cv2.COLOR_BGR2HSV
实例8:从BGR色彩空间转换到HSV色彩空间
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
# 将1.jpg从BGR色彩空间转换到HSV色彩空间
hsv_image = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
cv2.imshow("HSV", hsv_image) # 显示灰度图像
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下:
通道
在BGR色彩空间中,包含3个通道:B通道、G通道和R通道。
拆分通道
为了拆分一幅图像中的通道,OpenCV提供了split()方法。
拆分一幅BGR图像中的通道
b, g, r = cv2.split(bgr_image)
- bgr_image: 一幅BGR图像
- b: B通道图像
- g: G通道图像
- r: R通道图像
实例9: 拆分一幅BGR图像中的通道
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
b,g,r=cv2.split(image)
cv2.imshow("B",b)
cv2.imshow("G",g)
cv2.imshow("R",r)
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下:
可以看到结果是0三个不同亮度的灰度图像。这是因为当程序执行到cv2.imshow(“B”,b)时原图像B、G、R这3个通道的值都会被修改为B通道的值,即(B,B,B),其余同理。对于BGR图像,只要B=G=R(即数值相等),就可以得到灰度图像。
拆分一幅HSV图像中的通道
h, s, v = cv2.split(hsv_image)
- hsv_image: 一幅HSV图像。
- h: H通道图像
- s: S通道图像
- v: V通道图像
实例10: 拆分一幅HSV图像中的通道
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
hsv_image = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
h,s,v=cv2.split(hsv_image)
cv2.imshow("H",h)
cv2.imshow("S",s)
cv2.imshow("V",v)
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下:
合并通道
使用merge()方法合并H、S、V通道图像。
hsv = cv2.merge([h, s, v])
- h: H通道图像
- s: S通道图像
- v: V通道图像
- hsv:合并H通道图像、S通道图像和V通道图像后得到的图像
实例11: 合并H、S、V通道图像
首先将图像从BGR色彩空间转换到HSV色彩空间,然后拆分得到HSV图像中的通道,接着合并拆分后的通道图像,最后显示合并通道的HSV图像。
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
hsv_image = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
h,s,v=cv2.split(hsv_image)
hsv = cv2.merge([h,s,v])
cv2.imshow("HSV",hsv)
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下:
综合运用拆分通道和合并通道
在HSV色彩空间中,如果保持其中两个通道的值不变,调整第3个通道的值,会得到响应的艺术效果。
实例12: 只把H通道的值调整为180
首先将图像从BGR色彩空间转换到HSV色彩空间;然后拆分得到HSV图像中的通道;接着让S通道和V通道的值表示不变,把H通道的值调整为180;再接着合并拆分后的通道图像,把这个图像从HSV色彩空间转换到BGR色彩空间;最后显示得到的BGR图像。
import cv2
image = cv2.imread("1.jpg", 1) # 读取1.jpg
cv2.imshow("img_01", image) # 显示图像
hsv_image = cv2.cvtColor(image,cv2.COLOR_BGR2HSV) # 将图像从BGR色彩空间转换到HSV色彩空间
h,s,v=cv2.split(hsv_image) # 拆分得到HSV图像中的通道
h[:,:] = 180 # 让S通道和V通道的值表示不变,把H通道的值调整为180
hsv = cv2.merge([h,s,v]) # 合并拆分后的通道图像
new_Image = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR) # 把这个图像从HSV色彩空间转换到BGR色彩空间
cv2.imshow("NEW",new_Image)
cv2.waitKey()
cv2.destroyAllWindows() # 关闭所有的窗口时,销毁所有窗口
结果如下:
alpha通道
OpenCV在B、G、R三个通道的基础上,又增加了一个A通道,即alpha通道,用于设置图像的透明度。在BGRA色彩空间中,alpha通道在区间[0,255]内取值,其中0表示透明,255表示不透明。
实例13: 调整A通道的值
import cv2
bgr_image = cv2.imread("1.jpg", 1) # 读取1.jpg
bgra_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2BGRA) # 把图片从BGR色彩空间转换到BGRA色彩空间
b, g, r, a = cv2.split(bgra_image) # 拆分BGRA图像中的通道
a[:, :] = 172 # 将BGRA图像的透明度调整为172(半透明)
bgra_172 = cv2.merge([b, g, r, a]) # 合并拆分后并将透明度调整为172的通道图像
a[:, :] = 0 # 将BGRA图像的透明度调整为0(透明)
bgra_0 = cv2.merge([b, g, r, a]) # 合并拆分后并将透明度调整为0的通道图像
cv2.imwrite("D:/bgra_image.png", bgra_image) # 在D盘根目录下,保存BGRA图像
cv2.imwrite("D:/bgra_172.png", bgra_172) # 在D盘根目录下,保存透明度为172的BGRA图像
cv2.imwrite("D:/bgra_0.png", bgra_0) # 在D盘根目录下,保存透明度为0的BGRA图像
如果使用imshow()方法的话,窗口里显示的图像是相同的。为了显示这3幅图像的不同效果,需要使用imwrite()方法来保存。