一、图像处理基本 *** 作 1.读取图像
使用的方法:imread()
cv.imread(filename[,flags])
参数说明:
📊filename:要读取文件的名称
📊flages:
- cv.IMREAD_COLOR: 加载彩色图像。
任何图像的透明度都会被忽视。
它是默认标志。
- cv.IMREAD_GRAYSCALE:以灰度模式加载图像
- cv.IMREAD_UNCHANGED:加载图像,包括alpha通道
注意 除了这三个标志,你可以分别简单地传递整数1、0或-1。
import cv2 as cv
image_1 = cv.imread('1.png', 1)
image_2 = cv.imread("D:\learn\1.png", 1)
3、4行代码效果相同,只不过第四行代码可以读取别的路径下的图片。
使用的方法:imshow()
、waitkey()
、destroyAllWindows()
-
imshow():显示图像
cv.imshow(winname,mat)
参数说明:
📊 winname:显示图像窗口的名称
📊 mat:要显示的图像
-
waitKey():等待用户按下键盘按键的时间。
当用户按下键盘的任意按键时,将执行waitKey() 方法,并且获取此方法的返回值。
retval = cv.waitKey(delay)
参数说明:
📊 retval:与被按下键相对应的ASCII码。
例如ESC键的ACSII码为27,当用户按下ESC键时,waitKey()方法返回值时27,如果不是就返回-1。
📊 delay:等待用户按下键盘上按键的时间。
单位为ms,如果值为负数,0或者为空时表示无限等待。
-
destroyAllWindows():销毁正在显示图像的窗口
cv.destroyAllWindows()
实例:
import cv2 as cv
image = cv.imread('1.png', 1)
cv.imshow("taylor", image)
retval = cv.waitKey()
cv.destroyAllWindows()
print(retval)
运行结果:按下ESC
27
注意:
1️⃣窗口的名称不能为中文,否则会出现乱码。
2️⃣为了能够正常显示图像,
cv.waitKey()
不能省略,否则图像会一闪而过。
补充:
1️⃣cv.destroyWindow()
:销毁指定名称的窗口。
import cv2 as cv
image = cv.imread('1.png', 1)
cv.imshow("taylor", image)
retval = cv.waitKey()
cv.destroyWindow("taylor")
print(retval)
2️⃣在特殊情况下,用户可以先创建一个空窗口,然后再将图像传入窗口。
这种情况下可以指定窗口的大小。
这是通过cv.nameWindow()
完成的。
默认情况下,该标志为cv.WINDOW_AUTOSIZE
,但是如果将标志指定为cv.WINDOW_NORMAL
就可以调整窗口的大小。
实例:
import cv2 as cv
image = cv.imread("1.png")
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.imshow("taylor", image)
cv.waitKey()
cv.destroyAllWindows()
运行结果:窗口是可以用鼠标调整大小的
3.保存图像注意:
代码的第3,4行要显示的窗口名称必须保持一致,否则会出现两个窗口。
使用方法:imwrite()
:可用于按照指定路径保存图像。
cv.imwrite(filename,img)
参数说明:
📊filename:保存图像的完整路径。
📊img:要保存的图像。
实例:
import cv2 as cv
image = cv.imread("1.png", 0)
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.imshow("taylor", image)
cv.imwrite("D:\learn\2.png", image)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
使用方法:shape、size、dtype
1️⃣shape:如果图像是彩色图像,那么获取的是一个由图像的像素列数,行数和通道数组成的数组;
如果图像是灰度图像,那么获取的是一个由图像的像素列数,行数组成的数组。
2️⃣size:获取的是一个包含图像的像素个数,值大小等于像素列数×像素行数×通道数(如果是灰度图像,通道数就是1)。
3️⃣dtype:获取的是图像的数据类型。
import cv2 as cv
image = cv.imread("1.png")
print("图像的色彩属性:")
print("shape = ", image.shape)
print("size = ", image.size)
print("dtype = ", image.dtype)
运行结果:
图像的色彩属性:
shape = (1080, 1920, 3)
size = 6220800
dtype = uint8
二、图像数字化基础
图像数字化指的是用数字表示图像。
计算机通常会把像素值处理为处理为256个灰度级别,这256个灰度级别分别用区间[0,255]中的数值表示。
其中0表示纯黑色,255表示纯白色。
像素是构成数字图像的基本单位。
-
确定像素的位置
首先要确定此图像水平方向和垂直方向上的像素个数。
在OpenCV中正确表示某个像素坐标的表示方法是(y,x)。
实例:
import cv2 as cv
image = cv.imread("1.png")
px = image[1079, 1919]
-
获取像素的BGR值
上一小节已经获取了坐标为[1079,1919]上的像素px,那么使用
print()
方法打印这个像素得到的就是这个像素BGR值。import cv2 as cv image = cv.imread("1.png") px = image[1079, 1919] print("这个像素的BGR值为", px)
运行 结果为:
这个像素的BGR值为 [179 177 177]
在了解这三组数字代表的含义之前,先了解一下何为三基色。
人眼能感受到红色、绿色和蓝色三种颜色,把这三种颜色称为三基色,同时将三基色以不同比例混合就可以得到不同的颜色。
那么在计算机中要对颜色进行编码,就要使用到色彩空间。
其中较为常用的就是RGB色彩空间。
以此为例,在RGB色彩空间中,有三个颜色通道,分别是:红色R、绿色G和蓝色B。
并且每个颜色都在[0,255]之间取值。
不过需要注意的是,OpenCV在输出通道顺序的时候是相反的,是按照BGR输出。
在OpenCV中获取像素的BGR值方法有两种:
import cv2 as cv image = cv.imread("1.png") px = image[1079, 1919] print("这个像素的BGR值为", px)
import cv2 as cv image = cv.imread("1.png") print("这个像素的B值为", image[1079, 1919, 0]) print("这个像素的G值为", image[1079, 1919, 1]) print("这个像素的R值为", image[1079, 1919, 2])
运行结果:
参考前文程序输出。 -
修改像素的BGR值
前一节获得了坐标为[1079,1919]的像素的BGR值,如果要修改BGR值,代码为:
import cv2 as cv image = cv.imread("1.png") px = image[1079, 1919] print("这个像素修改前的BGR值为", px) px = [255, 255, 255] print("这个像素修改后的BGR值为", px)
运行结果:
这个像素修改前的BGR值为 [179 177 177] 这个像素修改后的BGR值为 [255, 255, 255]
注意:
如果将每个像素的R、G、B值改为相等大小时,就可以得到灰度图像。
全为0时就是纯黑色,全为255时就是纯白色。
如果要修改指定区域中的所有像素就可以使用2层for循环嵌套:
import cv2 as cv image = cv.imread("1.png", 1) cv.namedWindow("taylor", cv.WINDOW_NORMAL) for i in range(0, 79): for j in range(0, 19): image[i, j] = [0, 0, 0] cv.imshow("taylor", image) cv.waitKey() cv.destroyAllWindows()
运行结果:
⚠️ 警告
文章刚开头介绍了imread()
方法,前一节介绍了如何修改指定区域的元素。
比较下面图片中代码的区别:
如果图片是以彩色图像 加载的时候,那么修改指定区域像素的颜色,可以直接使用列表[0,0,0]
如果图像不是以彩色图像加载的时候,那么修改指定区域像素的颜色,不能直接使用列表[0,0,0],否则会报错:ValueError: setting an array element with a sequence.
必须要使用数组。
Numpy是用于快速数组计算的优化库。
因此,简单地访问每个像素值并对其进行修改将非常缓慢,因此不建议使用。
注意 上面的方法通常用于选择数组的区域,例如前5行和后3列。
对于单个像素访问,Numpy数组方法array.item()和array.itemset())被认为更好,但是它们始终返回标量。
如果要访问所有B,G,R值,则需要分别调用所有的array.item()。
更好的像素访问和编辑方法:
# 访问 RED 值 >>> img.item(10,10,2) 59 # 修改 RED 值 >>> img.itemset((10,10,2),100) >>> img.item(10,10,2) 100
2.色彩空间
除了前文介绍的RGB和BGR色彩空间,还有两个比较常见的色彩空间:GRAY和HSV色彩空间。
1.GRAY色彩空间
GRAY色彩空间通常指的是灰度图像,每个像素都是从黑到白([0,255]).0表示纯黑色,255表示纯白色。
2.从RGB/BGR色彩空间到GRAY色彩空间
使用方法:dst = cv.cvtColor(src,code)
参数说明:
📊dst:转换后的图像;
📊src:转换前的初始图像
📊code:色彩空间转换码
色彩空间转换码 | 含义 |
---|---|
cv.COLOR_BGR2GRAY | 从BGR色彩空间转换到GRAY色彩空间 |
cv.COLOR_RGB2GRAY | 从RGB色彩空间转换到GRAY色彩空间 |
实例:
import cv2 as cv
image = cv.imread("1.png", 1)
image_GRAY = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow("taylor", image_GRAY)
cv.waitKey()
cv.destroyAllWindows()
1️⃣色彩空间转换码还有很多,读者请自行查阅。
2️⃣虽然色彩空间转换是双向的,但是灰度图像是无法转换成彩色图像的。
因为彩色图像在转换成灰度图像的时候丢失了颜色比例,并且无法找回。
3.HSV色彩空间
HSV色彩空间是基于色调、饱和度、亮度而言的。
色调 H 指的是光的颜色。
在OpenCV中,色调在[0,180]内取值。
红、黄、绿和蓝分别是:0、30、60、120。
饱和度 S 指的是色彩的深浅。
在OpenCV中,饱和度在[0,255]内取值。
饱和度为0时,图像将变为灰度图像。
亮度 V 指的是光的明暗。
在OpenCV中,亮度在[0,255]内取值。
实例:
import cv2 as cv
image = cv.imread("1.png", 1)
image_GRAY = cv.cvtColor(image, cv.COLOR_BGR2HSV)
cv.imshow("taylor", image_GRAY)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWW2H1Si-1649246389207)(D:\learn\opencv入门.assets\image-20220406101443885.png)]
3.通道1.拆分通道
使用方法:split()
b,g,r = cv.split(bgr_image)
参数说明:
📊b:B通道图像
📊g:G通道图像
📊R:R通道图像
📊bgr_image:一幅RGB图像
拆分一幅BGR图像通道的顺序是B→G→R,因此等号左边必须是“b, g, r”。
实例:
import cv2 as cv
image = cv.imread("1.png", 1)
b, g, r = cv.split(image)
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_B", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_G", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_R", cv.WINDOW_NORMAL)
cv.imshow("taylor", image)
cv.imshow("taylor_B", b)
cv.imshow("taylor_G", g)
cv.imshow("taylor_R", r)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
有的读者会发现得到的B、G、R通道图像是3幅不同灰度的图像。
这是因为在cv.imshow("taylor_B",b)
时候,BGR这三通道的值都为B通道的值。
其余两个同理。
所以只要 B=G=R 就可以得到灰度图像。
实例:
import cv2 as cv
image = cv.imread("1.png", 1)
b, g, r = cv.split(image)
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_B", cv.WINDOW_NORMAL)
for i in range(0, 1079):
for j in range(0, 1919):
a = image[i, j]
image[i, j] = a[0]
cv.imshow("taylor", image)
cv.imshow("taylor_B", b)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
拆分一幅图像的HSV通道。
只需先将图像先转换为HSV图像即可,后面步骤一致。
实例:
import cv2 as cv
image = cv.imread("1.png", 1)
image_HSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)
h, s, v = cv.split(image_HSV)
cv.namedWindow("taylor", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_H", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_S", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_V", cv.WINDOW_NORMAL)
cv.imshow("taylor", image_HSV)
cv.imshow("taylor_H", h)
cv.imshow("taylor_S", s)
cv.imshow("taylor_V", v)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-v7fPJp6E-1649246389208)(D:\learn\opencv入门.assets\image-20220406183300394.png)]
2.合并通道
合并通道是拆分通道的逆过程。
使用方法:bgr = cv.merge([b,g,r])
参数说明:
📊bgr:按照B→G→R的顺序合并后得到的图像。
📊b:B通道图像
📊g:G通道图像
📊r:R通道图像
如果用户要按照R→G→B顺序合并,调换顺序即可。
实例:
import cv2 as cv
image = cv.imread("1.png", 1)
b, g, r = cv.split(image)
cv.namedWindow("taylor_original", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_merge_BGR", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_merge_RGB", cv.WINDOW_NORMAL)
cv.imshow("taylor_original", image)
image_merge_BGR = cv.merge([b, g, r])
image_merge_RGB = cv.merge([r, g, b])
cv.imshow("taylor_merge_BGR", image_merge_BGR)
cv.imshow("taylor_merge_RGB", image_merge_RGB)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
相信读者已经发现,按照不同的合并顺序得到的图像也是不一样的。
HSV通道合并同理。
不多赘述。
3.合理运用拆分通道和合并通道
在HSV色彩空间内,如果保持其中两个通道的值不变,调整第三个通道,会得到相应的艺术效果。
**实例:**只把H通道的值改为180
import cv2 as cv
cv.namedWindow("taylor_H180", cv.WINDOW_NORMAL)
image = cv.imread("1.png", 1)
image_HSV = cv.cvtColor(image, cv.COLOR_BGR2HSV)
h, s, v = cv.split(image_HSV)
h[:] = 180
image_HSV_merge = cv.merge([h, s, v])
image_HSV2BGR = cv.cvtColor(image_HSV_merge, cv.COLOR_HSV2BGR)
cv.imshow("taylor_H180", image_HSV2BGR)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
⁉️疑问:
前一段程序中的第十行做出以下变动:
代码变换前后,输出图片的效果是一样的???
使用
type()
查看 h 数据类型的时候发现其类型是,不是list。
4.alpha通道
前文说明了BGR色彩空间包含了3个通道,在此基础上再加上一个A通道就构成了alpha色彩空间(BRGA色彩空间)。
A用于设置图像的透明度。
A在区间[0,255]内取值。
0表示纯透明。
实例:
import cv2 as cv
cv.namedWindow("taylor_BGRA_A200", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_BGRA", cv.WINDOW_NORMAL)
image = cv.imread("1.png", 1)
image_BRGA = cv.cvtColor(image, cv.COLOR_BGR2BGRA)
b, g, r, a = cv.split(image_BRGA)
a[:] = 200
image_BRGA_A200 = cv.merge([b, g, r, a])
cv.imshow("taylor_BGRA_A200", image_BRGA_A200)
cv.imshow("taylor_BGRA", image_BRGA)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
虽然从输出的图片看不出区别,但是将这两幅图使用imwrite()
就可以看出区别:
实例:
import cv2 as cv
cv.namedWindow("taylor_BGRA_A200", cv.WINDOW_NORMAL)
cv.namedWindow("taylor_BGRA", cv.WINDOW_NORMAL)
image = cv.imread("1.png", 1)
image_BGRA = cv.cvtColor(image, cv.COLOR_BGR2BGRA)
b, g, r, a = cv.split(image_BGRA)
a[:] = 200
image_BGRA_A200 = cv.merge([b, g, r, a])
cv.imshow("taylor_BGRA_A200", image_BGRA_A200)
cv.imshow("taylor_BGRA", image_BGRA)
cv.imwrite("D:/learn/taylor_BGRA_A200.png", image_BGRA_A200)
cv.imwrite("D:/learn/taylor_BGRA.png", image_BGRA)
cv.waitKey()
cv.destroyAllWindows()
运行结果:
由于后面的相关学习需要用到Numpy,作者先去更新Numpy相关学习内容了。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)