【世界新要闻】「地表最全」零基础!计算机视觉OpenCV从入门到入土
项目介绍
前言:
(资料图片仅供参考)
OpenCV是计算机视觉领域一个图像和视频处理库,用于各种图像和视频分析,如面部识别和检测,车牌阅读,照片编辑,高级机器人视觉,光学字符识别等等。
最近一直在学习深度学习计算机视觉方面,但是在逐步深入的过程中,发现对图像的预处理相比起模型构建本身也同样重要,于是决定在学习完图像处理之后再去深入学习深度学习计算机视觉。为了同大家一起为飞桨社区添砖加瓦,特编辑出本文章方便大家踏寻着我的脚步,一起步入计算机视觉的大门~
近年来,计算机视觉(computer vision)已经越来越受到人们的重视。特别是在智能交通系统中,计算机视觉识别发挥了巨大的作用。
例如:汽车牌照的自动识别技术是把处理图像的方法与计算机的软件技术相连接在一起,以准确识别出车牌牌照的字符为目的,将识别出的数据传送至交通实时管理系统,以最终实现交通监管的功能。
在车牌自动识别系统中,从汽车图像的获取到车牌字符处理是一个复杂的过程,主要分为四个阶段:图像获取、车牌定位、字符分割以及字符识别。
再例如,随着深度学习技术的崛起、人工智能的备受关注,自动驾驶,作为AI中备受关注的重要落脚点,也被炒的火热,更让人充满了幻想。
摘要:
本文主要是使用python环境下的OpenCV来处理图像。OpenCV(Open Source Computer Vision Library)是开源的计算机视觉和机器学习库,提供了C++、C以及python等接口,并支持Windows、Linux、Android、MacOS平台。OpenCV自1999年问世以来,就已经成为计算机视觉领域学者和开发人员的首选工具。
注:
作者为了帮助各位小萌新尽快入门opencv的世界尽量将叙述语言构架地具有逻辑性和通俗性,希望大家在学习opencv的道路上可以一帆风顺~
本项目持续更新,欢迎评论催更,你的点赞and关注就是我的动力~
零. OpenCV简介
Opencv(Open Source Computer Vision Library)是一个基于开源发行的跨平台计算机视觉库,它实现了图像处理和计算机视觉方面的很多通用算法,已成为计算机视觉领域最有力的研究工具。在这里我们要区分两个概念:图像处理和计算机视觉的区别:图像处理侧重于“处理”图像–如增强,还原,去噪,分割等等;而计算机视觉重点在于使用计算机来模拟人的视觉,因此模拟才是计算机视觉领域的最终目标。 OpenCV用C++语言编写,它具有C ++,Python,Java和MATLAB接口,并支持Windows,Linux,Android和Mac OS, 如今也提供对于C#、Ch、Ruby,GO的支持
OpenCV于1999年由Intel建立,如今由Willow Garage公司提供支持。
1999年1月,CVL项目启动。主要目标是人机界面,能被UI调用的实时计算机视觉库,为Intel处理器做了特定优化。 2000年6月,第一个开源版本OpenCV alpha 3发布。 2000年12月,针对linux平台的OpenCV beta 1发布。
OpenCV 最初基于C语言开发,API也都是基于C的,面临内存管理、指针等C语言固有的麻烦。 2006年10月, 正式发布OpenCV 1.0版本,同时支持mac os系统和一些基础的机器学习方法,如神经网络、随机森林等,来完善对图像处理的支持。 2009年9月,OpenCV 1.2(beta2.0)发布。
当C++流行起来,OpenCV 2.x发布,其尽量使用C++而不是C,但是为了向前兼容,仍保留了对C API的支持。 2009年9月2.0 beta发布,主要使用CMake构建。 2010年3月:2.1发布 2010年12月6日,OpenCV 2.2发布 2011年8月,OpenCV 2.3发布。 2012年4月2日,发布OpenCV 2.4.
随着3.x的发布,1.x的C API将被淘汰不再被支持,以后C API可能通过C++源代码自动生成。3.x与2.x不完全兼容,与2.x相比,主要的不同之处在于OpenCV 3.x 的大部分方法都使用了OpenCL加速。 2014年8月, 3.0 alpha发布,除大部分方法都使用OpenCL加速外,3.x默认包含以及使用IPP(一套跨平台的软件函数库) 2017年8月,发布3.3版本,OpenCV开始支持C++ 11构建,同时加强对神经网络的支持。 OpenCV 4.X 2018年10月4.0.0发布,OpenCV开始需要支持C++11的编译器才能编译,同时对几百个基础函数使用"wide universal intrinsics"重写,极大改善了opencv处理图像的性能。
In [ ] import cv2 #引入第三方库
一.OpenCV入门
1.读取图像
函数原型
retval=cv2.imread(filename[,flags])
retval是返回值,其值是读到的图像。如果未读到图像,则返回“None”
filename是图像的完整的文件名
flag是读取标记
读取标记
In [ ]
lena=cv2.imread("./例.jpg",-1) #保持原格式不变的情况下按照文件路径读取文件print(lena) #打印图片数值
[[[ 86 73 183] [ 86 73 183] [ 86 73 181] ... [121 123 207] [123 123 207] [123 123 207]] [[ 86 73 183] [ 86 73 183] [ 86 73 181] ... [121 123 207] [124 124 208] [124 124 208]] [[ 84 71 181] [ 84 71 181] [ 84 71 179] ... [122 124 208] [124 126 210] [125 127 211]] ... [[ 47 5 70] [ 48 6 71] [ 48 6 71] ... [ 88 61 135] [ 88 61 134] [ 88 61 134]] [[ 47 5 70] [ 47 5 70] [ 48 6 71] ... [ 91 64 138] [ 90 63 136] [ 89 62 135]] [[ 45 6 68] [ 46 7 69] [ 48 7 69] ... [ 92 65 138] [ 90 63 136] [ 89 62 135]]]
2.显示图像
函数原型
1.namedWindow函数
None=cv2.namedWindow(winname)
2.imshow函数
None=cv2.imshow(winname,mat)
3.waitKey函数
retval=cv2.waitKey([delay])
winname是窗口名称,mat是显示图像*,delay是窗口展示的时间单位为ms
In [ ]
# cv2.namedWindow("winname")# cv2.imshow("winname", img) # cv2.waitKey(2000)# 由于notebook不兼容cv2的可视化,我们使用PIL的可视化工具代为进行#大家可以在本地ide尝试
In [ ]
from PIL import Imageimport numpy as npimport matplotlib.pylab as pylablena=cv2.cvtColor(lena,cv2.COLOR_BGR2RGB) #将BGR转换成RGBpylab.imshow(lena)
<matplotlib.image.AxesImage at 0x7f98bb286950>
3.保存图像
函数原型
1.cv2.imwrite函数
retval=cv2.imwrite(filename,img[,params])
retval返回值,保存成功返回True,否则返回False
filename是要保存的图像的完成路径名,包括扩展名
In [ ]
cv2.imwrite("./例2.jpg",lena)
True
二.图像处理基础
1.图像的基本表示方法
1.1 二值图像
二值图像是指仅包含黑色和白色两种颜色的图像
2.1 灰度图像
灰度图像有256个灰度级,用数值区间[0,255]来表示,其中255表示为纯白色,0表示为纯黑色
256个灰度级的数值恰好可以用一个字节(8位二进制值)来表示
3.1 彩色图像
在RGB色彩空间中,存在R,G,B三个通道,每个通道的数值范围在[0,255]之间,我们利用这三个色彩通道的组合表示颜色
三种颜色经过混合可以配出常见的256×256×256=16777216种颜色
在OpenCV中,通道的顺序是B→G→R
2.像素处理
2.1 二值图像及灰度图像
由于OpenCV没有二值图像这种数据类型,所以我们可以把二值图像理解为特殊的灰度图像
为了方便理解,我们首先使用Numpy库生成一个8×8大小的数组,来模拟黑色图像来进行处理
In [ ]
img=np.zeros((8,8),dtype=np.uint8) #创建一个8×8的全零数组print("img=\n",img) pylab.gray() #不使用颜色信息pylab.imshow(img) #可视化图像
img= [[0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0] [0 0 0 0 0 0 0 0]]
<matplotlib.image.AxesImage at 0x7f98c7df4590>
In [ ]
print("读取像素点 img[0,3]=",img[0,3]) img[0,3]=255 #255为白色,相当于在[0,3]的位置将黑色格修改成白色格print("修改后像素点 img[0,3]=",img[0,3])pylab.gray() #不使用颜色信息pylab.imshow(img) #可视化图像
读取像素点 img[0,3]= 0修改后像素点 img[0,3]= 255
<matplotlib.image.AxesImage at 0x7f98b8606890>
In [ ]
img=np.array(Image.open("./例.jpg").convert("L")) #为了方便接下来对灰度图的演示,我们使用灰度图的方式打开"./例.jpg"print(img)pylab.imshow(img)cv2.imwrite("./例—灰度图.jpg",img)
[[107 107 107 ... 148 148 148] [107 107 107 ... 148 149 149] [105 105 105 ... 149 151 152] ... [ 29 30 30 ... 86 86 86] [ 29 29 30 ... 89 88 87] [ 29 30 30 ... 90 88 87]]
True
In [ ]
for i in range(400,500): for j in range(80,500): img[i,j]=255 #将一部分区域内的数值修改为255,相当于将对应的图像的位置修改为白色pylab.imshow(img)cv2.imwrite("./例—灰度图修改后.jpg",img)
True
2.2 彩色图像
RGB模式的彩色图在读入OpenCV内进行处理时,会按照方向依次读取RGB的B,G,R通道的像素点,其在OpenCV内以BGR模式的三维数组形式存储
例如:
img[0,0]访问图像img第0行第0列像素点的BRG值 [B,G,R]
img[0,0,0]访问img第0行第0列第0通道的像素值,会得到B通道第0行第0列的值
img[0,0,2]访问img第0行第0列第2通道的像素值,会得到R通道第0行第0列的值
为了方便理解,我们首先使用Numpy生成一个2×4×3大小的数组,用它来模拟一幅彩色图像并对其进行简单处理
In [ ]
blue=np.zeros((300,300,3),dtype=np.uint8)blue[:,:,0]=255print("blue=",blue)pylab.imshow(blue)
blue= [[[255 0 0] [255 0 0] [255 0 0] ... [255 0 0] [255 0 0] [255 0 0]] [[255 0 0] [255 0 0] [255 0 0] ... [255 0 0] [255 0 0] [255 0 0]] [[255 0 0] [255 0 0] [255 0 0] ... [255 0 0] [255 0 0] [255 0 0]] ... [[255 0 0] [255 0 0] [255 0 0] ... [255 0 0] [255 0 0] [255 0 0]] [[255 0 0] [255 0 0] [255 0 0] ... [255 0 0] [255 0 0] [255 0 0]] [[255 0 0] [255 0 0] [255 0 0] ... [255 0 0] [255 0 0] [255 0 0]]]
<matplotlib.image.AxesImage at 0x7f98b8456490>
这时候就有小伙伴发现,展示出来的图片是红色而不是蓝色!!!
这是因为pylab的imshow是以RGB的方式展示出来的,而不是cv2的BGR
由于notebook无法使用cv2的imshow还请各位小伙伴在自己的本地编译器运行这段代码
我放一张这段代码在我的pycharm的运行截图
所以我们需要将BGR转换成RGB格式进行展示
In [ ]
blue=np.zeros((300,300,3),dtype=np.uint8)blue[:,:,0]=255blue=cv2.cvtColor(blue,cv2.COLOR_BGR2RGB) #将BGR转换成RGBpylab.imshow(blue)
<matplotlib.image.AxesImage at 0x7f98b83b5b90>
2.3 感兴趣区域(ROI)
在图像处理的中,我们可能会对图像的某一个特定区域感兴趣,该区域被称为感兴趣的区域(ROI)。在设定感兴趣的区域ROI后,就可以对该区域进行整体操作。
In [ ]
a=cv2.imread("./例.jpg") #提取lena的面部face=a[50:400,500:1000]face=cv2.cvtColor(face,cv2.COLOR_BGR2RGB) #将BGR转换成RGBpylab.imshow(face)cv2.imwrite("lena_face.jpg",face)
True
In [ ]
a=cv2.imread("./例.jpg") #给lena面部打码a[50:400,500:1000]=np.random.randint(0,256,(350,500,3))a=cv2.cvtColor(a,cv2.COLOR_BGR2RGB) #将BGR转换成RGBpylab.imshow(a)cv2.imwrite("lena_面部打码.jpg",a)
True
In [ ]
dollar=cv2.imread("./美元.jpg")dollar=cv2.cvtColor(dollar,cv2.COLOR_BGR2RGB)dollar[150:500,300:800]=facepylab.imshow(dollar)cv2.imwrite("dollar with dollar.jpg",dollar)
True
2.4 通道拆分
在RGB图像中,图像由R,G,B三个通道构成。需要注意的是,在OpenCV中,通道是按照B,G,R通道顺序存储的
In [ ]
# 1.按照索引拆分b=lena[:,:,0]g=lena[:,:,1]r=lena[:,:,2]pylab.subplot(1,3,1)pylab.imshow(b)pylab.subplot(1,3,2)pylab.imshow(g)pylab.subplot(1,3,3)pylab.imshow(r)
<matplotlib.image.AxesImage at 0x7f98b81be290>
<Figure size 432x288 with 3 Axes>
In [ ]
# 2.通过函数拆分b,g,r=cv2.split(lena)pylab.subplot(1,3,1)pylab.imshow(b)pylab.subplot(1,3,2)pylab.imshow(g)pylab.subplot(1,3,3)pylab.imshow(r)
<matplotlib.image.AxesImage at 0x7f98b810ff50>
<Figure size 432x288 with 3 Axes>
In [ ]
lena=cv2.imread("./例.jpg",-1)lena=cv2.cvtColor(lena,cv2.COLOR_BGR2RGB)pylab.imshow(lena)lena[:,:,0]=0pylab.subplot(1,3,1)pylab.imshow(lena)lena[:,:,1]=0pylab.subplot(1,3,2)pylab.imshow(lena)lena[:,:,2]=0pylab.subplot(1,3,3)pylab.imshow(lena)
<matplotlib.image.AxesImage at 0x7f98b0783710>
<Figure size 432x288 with 3 Axes>
2.5 通道合并
In [ ]
lena=cv2.imread("例.jpg")b,g,r=cv2.split(lena)# 将图像分为b,g,r三部分bgr=cv2.merge([b,g,r]) #按照bgr顺序合并图像rgb=cv2.merge([r,g,b]) #按照rgb顺序合并图像pylab.subplot(1,2,1)pylab.imshow(bgr)pylab.subplot(1,2,2)pylab.imshow(rgb)
<matplotlib.image.AxesImage at 0x7f98b06fcb50>
<Figure size 432x288 with 2 Axes>
2.6 获取图像属性
In [ ]
#获取图像gray_lena=cv2.imread("例.jpg",0) #获取灰色lenacolor_lena=cv2.imread("例.jpg",-1) #获取BGR彩色lena
In [ ]
print("灰度图像lena属性:")pylab.imshow(gray_lena)print("gray_lena.shape={}".format(gray_lena.shape))print("gray_lena.size={}".format(gray_lena.size))print("gray_lena.dtype={}".format(gray_lena.dtype))
灰度图像lena属性:gray_lena.shape=(599, 1440)gray_lena.size=862560gray_lena.dtype=uint8
<Figure size 432x288 with 1 Axes>
In [ ]
print("彩色图像lena属性:")color_lena=cv2.cvtColor(color_lena,cv2.COLOR_BGR2RGB)pylab.imshow(color_lena)print("color_lena.shape={}".format(color_lena.shape))print("color_lena.size={}".format(color_lena.size))print("color_lena.dtype={}".format(color_lena.dtype))
彩色图像lena属性:color_lena.shape=(599, 1440, 3)color_lena.size=2587680color_lena.dtype=uint8
<Figure size 432x288 with 1 Axes>
关键词:
推荐阅读
特斯拉的最低价是多少? 其他车型的最低价格是多少?
特斯拉作为一个豪华电动车品牌,你知道特斯拉价格多少钱一辆吗?目前特斯拉销售的主要Model S、Model X以及国产Model 3,那么,特拉斯最 【详细】
通用设备介绍 通用设备包括什么?
通用设备介绍一、通用设备。办公和商务通用设备,包括文化办公机械、消防设备、电机、变压器、锅炉、空调设备、清洁卫生设备、通讯设备、视 【详细】
美国UFO探索事件 全面解析美国UFO探索事件
一般在发生UFO探索事件之后,许多的研究人员都会认真的去分析此事件发生的前因后果,去搜集一些相关的证据,但是其实我们还能够从这些事件 【详细】
汽车吸尘器好用吗?汽车吸尘器真的有用么?
现在随着大家都逐渐拥有了自己的汽车,很多人对汽车的一些相关工具也还是逐步的关注了起来。其中车载吸尘器就是大家关注度最高的产品,那么 【详细】
航天员太空生活舱内景曝光 在太空中航天员之间是如何交流的呢?
航天员太空生活舱内景曝光,航天员在天上是如何生活的呢?中国载人航天工程空间站、神舟系列载人飞船、天舟系列货运飞船和长征系列运载火箭 【详细】
相关新闻
- 环球微头条丨iPhone推出全新配色却成小米13背景板,网友:库克审美呢?
- 【世界新要闻】「地表最全」零基础!计算机视觉OpenCV从入门到入土
- 哈啰顺风车车主在赣州接客被罚5000元!当地称平台未备案
- 腾讯“五虎”曾李青 ,现想成为沈南鹏一样的创投大王
- 预计售价不足千元 曝vivo Y11即将发布 采用LCD屏幕
- 3月7日基金净值:易方达创业板ETF最新净值2.3131,跌1.97%-环球简讯
- 天天通讯!计算机产业的生态化发展对商业模式和市场竞争的影响
- 初识CSS-CSS的三大特性|全球速看
- 大数据扫黄是怎么抓到你的?看完你怕了吗?快戒掉坏习惯 要闻
- 毛sir:接下来是跨境高速成长后的善后阶段,该拿什么来拯救?_天天热消息
- 微信这一波隐藏功能你用过吗!网友:好用_天天聚看点
- 系带是什么
- 巴特勒26+9+9阿德巴约16+7+5,热火力克老鹰 今日要闻
- 数据测试实践:从一个bug开始的大数据引擎兼容性探索|世界聚看点
- 派网云APP软件和AP固件升级公告 天天百事通
- 再见了夸克,找到比你更牛的浏览器了
- 张婷:沣西人才政策助力企业发展 世界时快讯
- 天天微动态丨香港大学火星实验室最新开源LiDAR-惯性SLAM可实时重建环境网格!
- 大火烧掉库克“后路”,印度厂商“玩火自焚”,苹果撤离中国没戏
- 应向小米11学习,售后保障切勿“拍拍屁股走人”