赞
踩
前两天将numpy库的基本知识做了一个简单的学习和回顾,主要是为了帮自己找回知识和忘记的函数,以及查看使得否需要进行新的应用。我们将两大成员数组与矩阵的知识点一一拉通学习之后,经过多多练习,便可逐渐掌握,numpy是一个计算的大库,在电脑计算有很大用处。
然而,这仅仅只是python中最常用的一个库而已,对于团队的学习,还需要重点掌握的一个库为:cv2,这个库将在车辆的驾驶,图像处理,动态渲染等方面与重大的贡献,在车路协同,交通大数据的背景下,我们将会做到很多动态变化的图像,由此来看交通试试变化,由此采取实时的措施管理与控制。
因此,作为模拟的库,自然与图像与计算紧密相连,也就是python中的numpy和matlab库的配合使用,在matlab库中我是用最多的一个模块为:matplotlib.pyplot,相信这也是大多数人接触最多的,用于绘制坐标图。
然而,对于cv2,我目前仅限于了解有这个东西,那么,既然了解了想变成自己的东西,那就慢慢一步一步来,接下来,就进入入门的学习。
首先是针对cv2库的安装,我们依旧在VS Code终端面板采用清华源:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
安装完毕之后方可采用import cv2 as cv2即可,也可as成一个可代表的字符。在这里,我们用来学习的照片如下:
cat.jpg
在cv2中,最基本的函数为读取和写入照片,和保存图片。cv2读取的格式有很多,基本上完全包括了目前素有照片的主流储存模式。读取照片采用的函数为:imread(),写入照片采用的函数为:imwrite。具体用法如下:
cv2.imread(filename,flags):filename写入想要展示的图片命名,字符串格式,flags表示该如何读取,对于其读取的方式,这里一般采用以下三种:
IMREAD_COLOR (1):加载彩色图像
IMREAD_GRAYSCALE (0):以灰度模式加载图像
IMREAD_UNCHANGED (-1):加载图像,包括 alpha 通道
通常采用1加载图片。
而对于图片的保存一般采用imwrite()函数,其用法为:
cv2.imwrite(filename,img):img为读取的照片的变量参数,照片被读取定义为MatLike,其本质格式为多维数组,将一个像素作为一个坐标点。展示照片的imshow()在目前阶段写法是相同的。
特别注意的一点为:imwrite() 只能保存 BGR 3通道图像,或 8 位单通道图像、或 PNG/JPEG/TIFF 16位无符号单通道图像
- img_test = cv2.imread('cat.jpg', flags=cv2.IMREAD_COLOR)
- cv2.imshow('cat_photo', img_test)
- # 保持照片窗口停留的时间
- cv2.waitKey(3000)
- # 销毁所有窗口
- cv2.destroyAllWindows()
输出的仍然是原来的图案,这里的waitKey表示图片展示框停留的时间(ms),destoryALLWindow表示销毁所有串口,保持好习惯,有打开就有关闭,在python中这一点要求并不严格,甚至几乎不检测,但在java中,对每个窗口的进入与关闭是严格的,甚至窗口个数也限制挺大的。
- img_test_2 = cv2.imread('cat.jpg', 0)
- print(type(img_test))
- cv2.imshow('cat_photo_2', img_test_2)
- cv2.imwrite("cat_grey.jpg", img_test_2)
- key = cv2.waitKey(3000)
- cv2.destroyAllWindows()
可以看到,通过0的方式打开的图片,将显示为灰白色,我们将其重新保存一份放入文件夹中。
matplotlib库是一个常用的绘图库,i面提供了各式各样的绘图参数,我们这里主要学习cv2,matplotlib库的内容直接用就可以了。该库的重点在于渲染,改善照片的展示质量,我们在这里做一个三秒的保存渲染并关闭。
- img_test_3 = cv2.imread('cat.jpg', 0)
- # 运用函数渲染图像
- plt.imshow(img_test_3)
- # 展示三秒并关闭,这里不采用show,而使用定时展示与关闭
- plt.ion()
- plt.pause(3)
- plt.close()
这里可以采用一个暂停函数的三组合来代替额传统的plt.show,是一个自动关闭打开的对话框。经过渲染,其图像为:
除了对图片进行传统的普通处理,在cv2中,还提供了rgb格式的图像修改方法,其具体的修改方案为将图像看作是一个ndarray多维数组,可以采用多维数组定位的方法。因此,我们需要先知道其图片的像素点大小和图片的尺寸,还有图像通过几RGB通道进行渲染的。
- img_test_rgb = cv2.imread('cat.jpg', 1)
- print(type(img_test_rgb))
- # 得到该ndarray的尺寸:(266,423,3)
- print(img_test_rgb.shape)
- # 得到该ndarray的像素大小:337554
- print(img_test_rgb.size)
其输出的结果分别为:<class 'numpy.ndarray'> (266, 423, 3) 337554。其中的3表示其采用的rgb渲染通道为3项,RGB就是通过三个数定义光的颜色,[0,0,0]表示黑色;[255.255,255]表示白色。
紧接着,在知道其为平面坐标的情况下,我们便可以进行索引与修改:
- # 试着访问某位置的元素的rgb值
- print(img_test_rgb[200, 200])
- # 改变某些位置元素的颜色
- # 将左上角100元素内的颜色为黑色
- for i in range(100):
- for j in range(100):
- img_test_rgb[i, j] = [0, 0, 0]
- cv2.imshow('cat_photo_modify', img_test_rgb)
- cv2.waitKey(3000)
- cv2.imwrite("cat_rgb.jpg", img_test_rgb)
- cv2.destroyAllWindows()
如此,我们边疆左上角100x100像素的图像全部改为了rgb显示为黑色的图案了。
通过split()函数可以将原始图像分割为三个通道,其中“0”表示蓝色,“1”表示绿色,“2”表示红色。而merge()函数则可以将通道合并起来。这里简单学习一下RGB,在RGB色彩的定义中,色彩由三个通道组成:蓝(B),绿(G),红(R)。
- # split可以将图像拆分为单独的通道
- img_test_rgb_2 = cv2.imread('cat.jpg', 1)
- b_img, g_img, r_img = cv2.split(img_test_rgb_2)
以下分别展示各种单通道的图片:
cv2.imshow("cat_rgb_b.jpg", b_img)
cv2.imshow("cat_rgb_g.jpg", g_img)
cv2.imwrite("cat_rgb_r.jpg", r_img)
对于图像,如果只有单通道,那么,他的值只能在0~255之间,也就是每个像素点之间只存在一层通道。纯粹的黑白对比图只存在0或者255的像素点。其他数字的出现会产生不同的灰度,但仍然是灰度图。以上便是三种通道分离开之后的各自通道组成的单通道灰度图。
- thoro_rbg = cv2.merge([b_img, b_img])
- cv2.imwrite('cat_two_rbg.jpg', thoro_rbg)
然而,当我们将同一个像素点,再次覆盖的时候便会发生色彩的变化,当我们第三次再覆盖一层同样范围的数的时候,便会出现更加丰富的色彩。我在合并通道的收,尝试过输出两通道合并的图,然而,最终报错,我的目前的学习理解状况来看,应当是cv2能识别的仅仅为单通道图和三通道图,不存在二通道图。
- Traceback (most recent call last):
- File "d:\PythonLearn\PythonWork\专题cv2入门(上)_初步认识.py", line 65, in <module>
- cv2.imwrite('cat_two_rbg', thoro_rbg)
- cv2.error: OpenCV(4.8.1) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:696: error: (-2:Unspecified error) could not find a writer for the specified extension in function 'cv::imwrite_'
因此,我们只能合成三通道,这就回到了imwrite只能读取单通道或者三通道进行文件图片写入。
- # 合并通道
- img_rgb_test = cv2.imread('cat.jpg', 1)
- b_img, g_img, r_img = cv2.split(img_rgb_test)
- thoro_three = cv2.merge([r_img, g_img, b_img])
- cv2.imwrite('thoro_3rgb.jpg', thoro_three)
而且还有一点,它分离的时候是按照B+G+R的顺序分离的,在这里我们合并的时候,是按照R+G+B的堆叠模式合成的,堆叠顺序影响图案的形成,最终输出的图案为:
接下来,虽然山面说不能通过合并两通道的RBG通道进行书写输出,却可以通过关闭某个或两个通道,这在程序看来,还是处于三通道,只是关闭的通道处于透明状态——存在但不可见,因此,就去掉某图层的颜色。示例如下:
- # 关闭rbg光学三原色的过程
- # 关闭蓝色通道
- img_test_rgb_2 = cv2.imread('cat.jpg', 1)
- # 此方案写法等同于将源图片分割为三通道,表达法不同
- img_test_rgb_2[:, :, 0] = False
- cv2.imwrite('cat_rbg_lost_b.jpg',img_test_rgb_2)
- img_test_rgb_2[:, :, 0] = True
其次,对于三通道图,若是三个通道的值是相同的,输出的也是灰度图。区分它们的重点辨识点为属性中查看位深度:当位深度为8的图为单通道灰度图,当深度为24则为三通道灰度图。一般来说,三通道还是彩色图的。
而三通道与单通道之间是存在转化关系的:
(1)单通道图转化为三通道图:
img = cv2.cvtColor(img , cv2.COLOR_GRAY2RGB)
(2)三通道图转化为单通道图,分为读取前转化与读取后转化:
- img = cv2.imread('test.jpg', 0)
- img = cv2.cvtColor(img , cv2.COLOR_RGB2GRAY)
至此,图像拆分与合并的难点编导此掌握了。
接下来的一大基础训练为在原始图像上绘制形状。此等操作在我们开发java的时候经常用到,用于开发软件与APP的时候由于手机型号不同,一般都采用相对位置进行开发。此方案同样如此,对每个相对位置的开发,是至关重要的环节。以下学习几个重点的函数:
函数 | 说明 | 命令 |
---|---|---|
cv2.line() | 绘制连接两点的线段 | cv2.line(img, pt1, pt2, color, thickness) |
cv2.circle() | 以给定点为中心绘制给定半径的圆 | cv2.circle(img, center, radius, color, thickness) |
cv2.rectangle | 绘制一个矩形,给定点为左上角和右角 | cv2.rectangle(img, pt1, pt2, color, thickness) |
cv2.ellipse() | 绘制简单的粗椭圆弧或填充椭圆扇区 | cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness) |
对于每个函数,其也有着对应的参数:
img:表示要绘制形状的图像。
color:形状的颜色,一般采用RGB方式传递。 对于 BGR,将其作为元组传递。 对于灰度,只需传递标量值。
thickness:线或圆的粗细。如果为圆或封闭图形,传递-1,它将填充形状。
lineType:线条的类型,是否8连线,抗锯齿线设置等。
以下展示一段团绘制的实例,用于自我的学习:
- img_draw = cv2.imread('cat.jpg', 1)
- # 在图片上添加一个矩形
- cv2.rectangle(img_draw, (15, 35), (235, 230), (45, 243, 26), 3)
- # 在图片上添加一条横线
- cv2.line(img_draw, (30, 50), (240, 50), (190, 92, 19), 5)
- # 添加一个填充圆形
- cv2.ellipse(img_draw, (280, 100), (70, 10), -20, 0, 360, (0, 0, 255), -1)
- # 储存图片
- cv2.imwrite('cat_draw.jpg', img_draw)
其代码绘制的图案如下:
如今这只是进行简单的线条绘制,等学习到一定程度,可以绘制更多的动态模型,我主要是为了在智慧驾驶,车路协同、信号控制等演示上重点运用此库。
到这里,cv2的入门课基本就结束了,我们已经学习了cv2的基本流程,现在,可以进行简单的图形处理了,因此,对于去除背景这件事,是不是就变得很简单了呢?纯色。万丈高楼平地起,每天学习一点点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。