
唤醒手腕 - 人工智能 - 计算机视觉、Opencv 图像处理技术(更新中···)
什么是计算机视觉?计算机视觉(Computer Vision)是指用计算机实现人的视觉功能——对客观世界的三维场景的感知、识别和理解。这意味着计算机视觉技术的研究目标是使计算机具有通过二维图像认知三维环境信息的能力。因此不仅需要使机器能感知三维环境中物体的几何信息(形状、位置、姿态、运动等)而且能对它们进行描述、存储、识别与理解。可以认为,计算机视觉与研究人类或动物的视觉是不同的:它借助于几何、物
计算机视觉基本概述
什么是计算机视觉?
计算机视觉(Computer Vision)是指用计算机实现人的视觉功能——对客观世界的三维场景的感知、识别和理解。
这意味着计算机视觉技术的研究目标是使计算机具有通过二维图像认知三维环境信息的能力。因此不仅需要使机器能感知三维环境中物体的几何信息(形状、位置、姿态、运动等)而且能对它们进行描述、存储、识别与理解。可以认为,计算机视觉与研究人类或动物的视觉是不同的:它借助于几何、物理和学习技术来构筑模型,用统计的方法来处理数据。
人工智能的完整闭环包括感知、认知、推理再反馈到感知的过程,其中视觉在我们的感知系统中占据大部分的感知过程。所以研究视觉是研究计算机的感知重要的一步。
计算机视觉应用
计算机视觉技术已经在许多领域得到了广泛的应用,以下是一些典型的例子:
- 公安安防:人脸识别,指纹识别,场景监控,环境建模。
- 生物医学:染色体分析,X光、CT图像分析,显微医学操作。
- 文字处理:文字识别,文档修复,办公自动化,垃圾邮件分类。
- 国防军事:资源探测,军事侦察,导弹路径规划。
- 智能交通:公路交通管理,电子警察执法抓拍系统,自动驾驶车辆。
- 休闲娱乐:电影特效,视频编辑,人像美颜,体感游戏,VR。
数字图像处理基础
数字图像的采集过程类似人眼,使用大量的光敏传感器构成阵列以获取图像。成像的质量由传感器的单元数,尺寸和传感性能决定。
常见的图像文件格式
- PNG格式:使用无损压缩,画质好,背景或任何一种颜色可以透明化。不支持动画应用效果。
- GIF格式:适合色彩简单的图片,背景或任何一种颜色可以透明化,可以做成逐帧动画。
- JPEG格式:画面色彩比较丰富时,文件体积较小。不支持透明图像、不支持动画应用效果。
- BMP格式:BMP是英文Bitmap(位图)的简写,它是Windows操作系统中的标准图像文件格式,能够被多种WindowS应用程序所支持。
- TIFF格式:是一种比较灵活的图像格式,支持256色、24位真彩色、32位色、48位色等多种色彩位,文件体积较大。
- PDF格式:支持矢量图形,可无损放大打印,Adobe Acrobat Professional和常用的作图软体如Photoshop 、Illustrator都可编辑PDF格式。纽约摄影教材01.pdf
- WMF格式:它们是属于矢量类图形,是由简单的线条和封闭线条(图形)组成的矢量图,其主要特点是文件非常小,可以任意缩放而不影响图像质量。
图像像素基本属性
像素深度
在计算机的世界里,所有的位图均是由许多的像素所构成。这些像素以矩阵的方式排列,矩阵中的每一个元素都对应图像中的一个像素,存储这个像素的颜色信息。
像素深度是指存储每个像素所用的位数。像素深度决定彩色图像的每个像素可能有的颜色数,或者确定灰度图像的每个像素可能有的灰度级数。
分辨率
分辨率由宽(width)和高(height)两个参数构成。宽表示水平方向的细节数,高表示垂直方向的细节数。
分辨率是指每一英寸所包含的像素值,用 dpi 表示。分辨率越高,图像越清晰。分辨率一般分为输入分辨率、屏幕分辨率、图像分辨率和输出分辨率四种。
计算机视觉如何运作?
机器非常简单地解释图像:作为一系列像素,每个像素都有自己的一组颜色值。考虑下面的简化图像,以及如何将灰度值转换为简单的数字数组:
像素关系(邻域、连通域)
邻域在一定意义下,与某一像素相邻的像素的集合。反映像素间的空间关系。图像中的各个像素都是相关的,每个像素和邻域具有相同或者相似的一些特性,对此,可以进行图像的分割处理。图像像素常见的邻域有: N 8 § 、 N 4 § 、 N D § N8§、N4§、ND§ N8§、N4§、ND§
-
常用 4 邻域,记作: N 4 § N4§ N4§
-
对角邻域: p ( x , y ) : ( x + 1 , y ) ; ( x − 1 , y ) ; ( x , y + 1 ) ; ( x , y − 1 ) p(x,y):(x+1,y);(x−1,y);(x,y+1);(x,y−1) p(x,y):(x+1,y);(x−1,y);(x,y+1);(x,y−1) 每个像素与 p ( x , y ) p(x,y) p(x,y) 距离为 1 对角邻域,记作: N D § ND§ ND§
-
8 邻域: N 8 § = N 4 § + N D § N8§=N4§+ND§ N8§=N4§+ND§(即是3×3邻域)
N 8 § 、 N 4 § 、 N D § 邻 域 展 示 : N8§、N4§、ND§ 邻域展示: N8§、N4§、ND§邻域展示:
连通性:描述区域和边界的重要概念,有:4连通、8连通、m连通
两像素连通的必要条件:1)两像素位置是否相邻。2)两像素灰度值是否满足特定的相似性准则。
(1)4 连通:两个像素 p 和 q,如果 p 在 q 的 4 邻域中,称这两个像素是 4 连通。
(2)8 连通:两个像素 p 和 q,如果p在 q 的 8 邻域中,称这两个像素是 8 连通。
(3)m 连通:
- 1)两个像素p和q,p在q的4邻域内,或者p在q的D邻域内。
- 2)且p和q的4邻域的交集为空,即m连通是4连通和D连通的混合(mixture)连通。
图像像素 连通域
二值图像的图像的亮度值只有两个状态:黑(0)和白(255)。二值图像在图像分析与识别中有着举足轻重的地位,因为其模式简单,对像素在空间上的关系有着极强的表现力。在实际应用中,很多图像的分析最终都转换为二值图像的分析,比如:医学图像分析、前景检测、字符识别,形状识别。二值化+数学形态学能解决很多计算机识别工程中目标提取的问题。
二值图像分析最重要的方法就是连通区域标记,它是所有二值图像分析的基础,它通过对二值图像中白色像素(目标)的标记,让每个单独的连通区域形成一个被标识的块,进一步的我们就可以获取这些块的轮廓、外接矩形、质心、不变矩等几何参数。
下面是一个二值图像被标记后,比较形象的显示效果。
在我们讨论连通区域标记的算法之前,我们先要明确什么是连通区域,怎样的像素邻接关系构成连通。在图像中,最小的单位是像素,每个像素周围有8个邻接像素,常见的邻接关系有2种:4邻接与8邻接。4邻接一共4个点,即上下左右,如下左图所示。8邻接的点一共有8个,包括了对角线位置的点,如下右图所示。
如果像素点 A 与 B 邻接,我们称 A 与 B 连通,于是我们不加证明的有如下的结论:
结论:如果A 与 B 连通,B 与 C 连通,则 A 与 C 连通。
在视觉上看来,彼此连通的点形成了一个区域,而不连通的点形成了不同的区域。这样的一个所有的点彼此连通点构成的集合,我们称为一个连通区域。
下面这符图中,如果考虑4邻接,则有3个连通区域;如果考虑8邻接,则有2个连通区域。(注:图像是被放大的效果,图像正方形实际只有4个像素)
连通区域(Connected Component)一般是指图像中具有相同像素值且位置相邻的前景像素点组成的图像区域(Region,Blob)。连通区域分析(Connected Component Analysis,Connected Component Labeling)是指将图像中的各个连通区域找出并标记。
连通区域分析是一种在CVPR和图像分析处理的众多应用领域中较为常用和基本的方法。例如:OCR识别中字符分割提取(车牌识别、文本识别、字幕识别等)、视觉跟踪中的运动前景目标分割与提取(行人入侵检测、遗留物体检测、基于视觉的车辆检测与跟踪等)、医学图像处理(感兴趣目标区域提取)、等等。也就是说,在需要将前景目标提取出来以便后续进行处理的应用场景中都能够用到连通区域分析方法,通常连通区域分析处理的对象是一张二值化后的图像。
Opencv 基本操作
NumPy 是一个Python包(Numeric Python)它是一个由多维数组对象和用于处理数组的例程集合组成的库,其支持大量高维度数组与矩阵运算。NumPy 也针对数组运算提供大量的数学函数,机器学习涉及到大量对数组的变换和运算。
导入Numpy库,并命名为 np,起别名简化代码书写
import numpy as np
NumPy 中定义的最重要的对象是称为 ndarray 的 N 维数组类型。 它描述相同类型的元素集合。可以使用基于零的索引访问集合中的项目。
ndarray 中的每个元素在内存中使用相同大小的块, ndarray 中的每个元素是数据类型对象的对象(称为 dtype)
基本的ndarray是使用NumPy中的数组函数创建的,如下所示:
ndarray_obj = numpy.array(*args, **kwargs)
NumPy 的主要对象是多维数组 Ndarray。在 NumPy 中维度 Dimensions 叫做轴 Axes,轴的个数叫做秩 Rank。
注意,numpy.array 和 Python 标准库 array.array 并不相同,前者更为强大,这也就是我们学习 NumPy 的重要原因。
Opencv 图片缩放操作
import cv2
image = cv2.imread('02test.jpg')
res = cv2.resize(image, (300, 300), interpolation=cv2.INTER_CUBIC)
cv2.imshow('result_img', res)
cv2.imwrite('02test_mini.jpg', res)
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destoryAllWindows()
imread 函数
imread函数的作用非常简单,从函数的名称也可以看出来,imread为image read的缩写,即图像读取的意思。那么imread函数的作用就很明显了,负责读取图像。其实学过 matlab 的同学就会知道,matlab 中也有一个读取图像的函数也命名为 imread,这是 opencv 借鉴了 matlab 而命名的,因为在 opencv1.x时代,加载图像的函数并不叫 imread,二是由 cvLoadImage 函数负责。
Python:
retval = cv.imread(filename[, flags])
cv.imread:传入 1 是读取彩色图,传入 0 是读取灰度图
灰度图 Gray Scale Image
什么叫灰度图?
图像灰度值的概念是什么?灰度也可以认为是亮度,简单说就是色彩的深浅程度。
实际上在我们的日常生活中,通过三原色色彩深浅的组合,可以组成各种不同的颜色。产品能够展现的灰度数量越多,也就意味着色彩表现力更加丰富,能够实现更强的色彩层次。例如三原色 16 级灰度,能显示的颜色就是 16 ∗ 16 ∗ 16 = 4096 16 * 16 * 16 = 4096 16∗16∗16=4096 色。不过目前产品256级灰度已经非常地普遍了。
任何颜色都有红、绿、蓝三原色组成,假如原来某点的颜色为RGB(R,G,B),那么,我们可以通过下面几种方法,将其转换为灰度:
方法 | 具体操作 |
---|---|
1.浮点算法 | Gray = R * 0.3+G * 0.59 + B * 0.11 |
2.整数方法 | Gray = ( R * 30 + G * 59 + B * 11 ) / 100 |
3.移位方法 | Gray = ( R * 76 + G * 151 + B * 28 ) >> 8 |
4.平均值法 | Gray= ( R + G + B ) / 3 |
5.仅取绿色 | Gray = G |
通过上述任一种方法求得 G r a y Gray Gray 后,将原来的 R G B ( R , G , B ) RGB(R,G,B) RGB(R,G,B) 中的 R , G , B R,G,B R,G,B 统一用 G r a y Gray Gray 替换,形成新的颜色 R G B ( G r a y , G r a y , G r a y ) RGB(Gray,Gray,Gray) RGB(Gray,Gray,Gray),用它替换原来的 R G B ( R , G , B ) RGB(R,G,B) RGB(R,G,B) 就是灰度图了。
import numpy as np
import cv2
def transform_gray(image):
h, w = image.shape[:2]
# 获取图片的high和wide
img = np.zeros([h, w], image.dtype)
# 创建一张和当前图片大小一样的图片
# print(img)
for i in range(h):
for j in range(w):
m = image[i, j]
# 取出当前high和wide中的BGR坐标
img[i, j] = int(m[0] * 0.11 + m[1] * 0.59 + m[2] * 0.3)
# 将BGR坐标转化为gray坐标并赋值给新图像
print("image show: %s" % img)
cv2.imshow("transform_gray image show", img)
src = cv2.imread("02test_mini.jpg")
cv2.imshow("source image", src)
dst = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
# opencv自带RGB转灰度图api
print("gray: %s" % dst)
# 查看自带api转灰度图结果的数组
cv2.imshow("gray image", dst)
transform_gray(src)
cv2.waitKey(0)
cv2.destroyAllWindows("image")
分别是源图片、自定义灰度图算法、Opencv 自带 api 转换灰度图:
图像量化 Quantization
前言:对模拟图像进行采样之后所得到的小图像块的像素值仍然是连续的,所以要对其像素值进行离散化处理,即量化。
量化(Quantization)旨在将图像像素点对应亮度的连续变化区间转换为单个特定值的过程,即将原始灰度图像的空间坐标幅度值离散化。量化等级越多,图像层次越丰富,灰度分辨率越高,图像的质量也越好;量化等级越少,图像层次欠丰富,灰度分辨率越低,会出现图像轮廓分层的现象,降低了图像的质量。下图是将图像的连续灰度值转换为0至255的灰度级的过程[1-3]。
图像量化是对哪个对象进行什么样的操作?
对图像块的幅值进行量化,原来在一个图像块中,幅值是连续变化的,我们现在将这些幅值量化成有限个离散。比如,将所有的幅值量化成 0 / 1,即每个像素所对应的幅值要么是 1,要么是 0。
如果量化等级为 2,则将使用两种灰度级表示原始图片的像素(0-255),灰度值小于 128 的取 0,大于等于 128 的取 128;如果量化等级为 4,则将使用四种灰度级表示原始图片的像素,新图像将分层为四种颜色,0 - 64 区间取 0,64 - 128 区间取 64,128 - 192区间取 128,192 - 255区间取192,依次类推。
下图是对比不同量化等级的“Lena”图。其中(a)的量化等级为256,(b)的量化等级为64,(c)的量化等级为16,(d)的量化等级为8,(e)的量化等级为4,(f)的量化等级为2。
图像量化实现
图像量化的实现过程是建立一张临时图片,接着循环遍历原始图像中所有像素点,判断每个像素点应该属于的量化等级,最后将临时图像显示。下面的代码将灰度图像转换为两种量化等级。
import cv2
import numpy as np
# 读取原始图像
img = cv2.imread('02test.jpg')
# 获取图像高度和宽度
height = img.shape[0]
width = img.shape[1]
# 创建一幅图像
new_img = np.zeros((height, width, 3), np.uint8)
# 图像量化操作 量化等级为2
for i in range(height):
for j in range(width):
for k in range(3): # 对应BGR三分量
if img[i, j][k] < 128:
gray = 0
else:
gray = 128
new_img[i, j][k] = np.uint8(gray)
# 显示图像
cv2.imshow("src", img)
cv2.imshow("", new_img)
# 等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
其输出结果如图所示,它将灰度图像划分为两种量化等级:
怎么设置量化比率?
有两种方法:均匀量化 和 非均匀量化。
-
均匀量化:将图像的幅值从最大值到最小值进行均匀划分成若干个层级,量化级数一般是 2 的 n 次方,最小的就是 2,即 2 值图像。
-
非均匀量化:就是对图像灰度级变化剧烈的部分划分的更细。
均匀量化算法实现:
from matplotlib import pyplot as plt
from skimage import data
# 载入图像
image = data.coffee()
# 设置量化比率
ratio = 128
# 量化
for i in range(image.shape[0]):
for j in range(image.shape[1]):
for k in range(image.shape[2]):
# 只有两个灰度级,一个是0,一个是128
image[i, j, k] = int(image[i, j, k] / ratio) * ratio
plt.imshow(image)
plt.show()
更多推荐
所有评论(0)