「地表最全」零基础!计算机视觉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的支持

1.1 OpenCV发展历史

OpenCV于1999年由Intel建立,如今由Willow Garage公司提供支持。

OpenCV 0.X

  1999年1月,CVL项目启动。主要目标是人机界面,能被UI调用的实时计算机视觉库,为Intel处理器做了特定优化。
  2000年6月,第一个开源版本OpenCV alpha 3发布。
  2000年12月,针对linux平台的OpenCV beta 1发布。

OpenCV 1.X

  OpenCV 最初基于C语言开发,API也都是基于C的,面临内存管理、指针等C语言固有的麻烦。
  2006年10月, 正式发布OpenCV 1.0版本,同时支持mac os系统和一些基础的机器学习方法,如神经网络、随机森林等,来完善对图像处理的支持。
  2009年9月,OpenCV 1.2(beta2.0)发布。

OpenCV 2.X

  当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.

OpenCV 3.X

  随着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处理图像的性能。

1.2 OpenCV应用领域

1、人机互动

2、物体识别

3、 图像分割

4、人脸识别

5、动作识别

6、 运动跟踪

7、机器人

8、运动分析

9、机器视觉

10、结构分析

11、汽车安全驾驶

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 Image
import numpy as np
import matplotlib.pylab as pylab

lena=cv2.cvtColor(lena,cv2.COLOR_BGR2RGB) #将BGR转换成RGB
pylab.imshow(lena)

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=
",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]]

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

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]=255
print("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]]]

这时候就有小伙伴发现,展示出来的图片是红色而不是蓝色!!!

这是因为pylab的imshow是以RGB的方式展示出来的,而不是cv2的BGR
由于notebook无法使用cv2的imshow还请各位小伙伴在自己的本地编译器运行这段代码
我放一张这段代码在我的pycharm的运行截图

所以我们需要将BGR转换成RGB格式进行展示

In [ ]

blue=np.zeros((300,300,3),dtype=np.uint8)
blue[:,:,0]=255
blue=cv2.cvtColor(blue,cv2.COLOR_BGR2RGB) #将BGR转换成RGB
pylab.imshow(blue)

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转换成RGB
pylab.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转换成RGB
pylab.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]=face
pylab.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)

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)

In [ ]

lena=cv2.imread("./例.jpg",-1)
lena=cv2.cvtColor(lena,cv2.COLOR_BGR2RGB)
pylab.imshow(lena)
lena[:,:,0]=0
pylab.subplot(1,3,1)
pylab.imshow(lena)
lena[:,:,1]=0
pylab.subplot(1,3,2)
pylab.imshow(lena)
lena[:,:,2]=0
pylab.subplot(1,3,3)
pylab.imshow(lena)

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)

2.6 获取图像属性

In [ ]

#获取图像
gray_lena=cv2.imread("例.jpg",0) #获取灰色lena
color_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=862560
gray_lena.dtype=uint8

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=2587680
color_lena.dtype=uint8

展开阅读全文

页面更新:2024-03-09

标签:视觉   计算机   灰度   地表   车牌   数值   函数   像素   入门   图像   通道   彩色   基础

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top