简介
对于主攻计算机视觉的我们来说,对图片处理几乎时时刻刻都在进行。但在复现了几个网络后,我开始对整个网络过程中,图片到底是怎么变换的产生好奇。因此,在实验室中借阅了本相关的书籍(《Opencv算法精解-基于Python与C++》),通过一段时间的学习,整理。总算大致了解了图片在计算机上的各种转换过程。尤其在学习完之后,原来如此之情油然而生。因此,在这里,希望研究本方向的其他同学(特指入门者,资深学者请忽略)能先了解图片的原理之后,再开始入门深度学习。为方便大家,我在此做了一些总结,可以省去大部分时间,以及有些书籍中的opencv版本过低,某些算法已经改变。希望本篇博客能给大家带来帮助,也欢迎大家指出问题。
目录
- Opencv简介
- 图像数值化
- 几何变化
- 对比度增强
- 图像平滑
- 阈值分割
- 形态学处理
Opencv简介
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
OpenCV用C++语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语言接口。该库也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。这些语言的API接口函数可以通过在线文档获得。如今也提供对于C#、Ch、Ruby,GO的支持。
Opencv的应用领域
OpenCV 的应用领域非常广泛,包括图像拼接、图像降噪、产品质检、人机交互、人脸识别、动作识别、动作跟踪、无人驾驶等。
图像数值化
(之后的所有图片处理,都将以上图为原图)
- Numpy中的ndarray
- Opencv中的Mat
- 灰度图像数字化
- 彩色图像数字化
1.Numpy中的ndarray
函数说明
- 转化为数组形式:
np.array(object,dtype=None,copy='K',subok=False,ndmin=0)
- 创建元素为0的数组:
np.zeros(shape,dtype=float)
- 创建shape同x的0数组:
np.zeros_like(x)
- 创建元素为1的数组:
np.ones(shape,dtype=float)
- 创建shape同x的1数组:
np.zeros_like(x)
2.Opencv中的Mat
- 基本构成:行数(高),列数(宽),通道数(高)以及数据类型
- Mat(int rows,int cols,int type)
type的基本类型:
CV_8UC(n),CV_8SC(n),CV_16SC(n),CV_16UC(n),CV_32SC(n),CV_32FC(n),CV_64FC(n)
构成说明:
前面的数字代表所占的bit数,
U:unsign char S:sign int F:float
C(n)则代表了n通道
例如:
CV_16SC3 代表着2个字节的sign int,通道数为3的类型(1byte = 8bit)
(注意:这里的构造函数,只给出了三个参数,并没有给出通道数的构建,其实这已经包括在type的定义中,这主要涉及到了opencv中的type设定)
3.灰度图像数字化
所谓的数字化,其实就是化成同行同列的二维数组,而每个坐标存的就是相关的灰度值(0-255)
(为什么是0-255?就像上面所说,一个字节存放8bit,而图的储存都是以uint8类型存放,同时计算机时按照二进制存放数值,也就是2的8次方,也就是256)
补充:色彩深度与灰阶
色彩深度 | 灰阶 |
---|---|
色彩深度(Depth of Color),色彩深度又叫色彩位数。视频画面中红、绿、蓝三个颜色通道中每种颜色为N位,总的色彩位数则为3N,色彩深度也就是视频设备所能辨析的色彩范围。目前有18bit、24bit、30bit、36bit、42bit和48bit位等多种。24位色被称为真彩色,R、G、B各8bit,常说的8bit,色彩总数为1670万,如手机参数,多少万色素就这个概念。 | 通常来说,液晶屏幕上人们肉眼所见的一个点,即一个像素,它是由红、绿、蓝(RGB)三原色组成的。每一个基色,其背后的光源都可以显现出不同的亮度级别。而灰阶代表了由最暗到最亮之间不同亮度的层次级别。把三基色每一个颜色从纯色(如纯红)不断变暗到黑的过程中的变化级别划分成为色彩的灰阶,并用数字表示,就是最常见的色彩存储原理。这中间层级越多,所能够呈现的画面效果也就越细腻。以8bit 为例,我们就称之为256灰阶。 |
调用函数: cv2.imread(filename,flag)
- filename:文件名
- flag:读入方法
- 常用:0相当于灰度读入,1相当于彩色读入
具体flag类型:
实例:
3.彩色图像数字化
原理同上,不多说,直接展示实例。
实例:
补充:通道的分离与组合
图片解析:
从图中可看出,每三个BGR就组成了一张图片的一列。因此,实际上可将图片看成一个长方体(如下图,自画图,可能不咋地)。而分离与结合也是基于这三个通道展开。
分离(split())
问题:
为什么得到的是三张不同的灰度图?不是已经分离出RGB通道了,应该是红色图,蓝色图,绿色图。
解答
当调用 imshow(R)时,是把图像的R,G,B三个通道的值都变为R的值,所以图像的颜色三通道值为(R,R,R)同理 imshow(G)和imshow(B)所显示d图像的颜色通道也依次为(G,G,G)和(B,B,B)。而 当三个通道d值相同时,则为灰度图。(注意:在opencv中是按照bgr,而不是rgb,因此在提取时需要特别注意)。
合并(merge())
几何变化
- 平移
- 放大,缩小
- 旋转
- 投影,极坐标
仿射变化
主要是指平移,缩放,旋转,反转,错切五种
原理解析
我们可以将一张图片看成是由无数个点组成的。因此,要实现以上变化,则可以看成对无数个点的操作。从而完成整张图的变换。
单点操作
推导(引用矩阵变换)
过程
其中A成为仿射变换矩阵。
参数解析
- a,d代表x,y的放大倍数,当m,n都为0时,代表以远点为中心缩放,否则代表(m,n)为中心缩放。(一般情况下,b,c为0)
- m,n代表平移距离
- 特别的,可进行符合运算,即先平移,再放大,再平移等(需特别注意矩阵的结合律等)
旋转
将B点从θ旋转阿尔法到B’
首先,由图可得:
之后,通过上式可知:
由此可知,放射变化矩阵A为
特别的,当绕(m,n)旋转时:
补充:插值算法
具体几个算法可在此博客中查看
在进行变化之后,会使某些坐标的值损失,因此需要进行插值。具体的算法原理在上面的链接中已经非常详细了。因此,在这里主要手写实现一下:最邻近插值以及双线性插值算法。
最邻近插值
双线性插值
应用
投影
原理相同,不过实在原来的仿射变换矩阵上添加了第三行z(在空间中进行仿射变换)。
步骤
- 通过四个点的投影前投影后的对比,求出变换矩阵
- 利用变换矩阵对全图进行计算
极坐标变换
该转化过程可回忆高中的极坐标转换(圆的方程),直角坐标系上的圆转化为极坐标上的直线,从而实现了图像的变换。
这是一个opencv4的例子
- 直角坐标系转换成极坐标cv2.cartTopolar(array,angleInDegress(角度或者弧度))
- 极坐标转换成直角坐标系 cv2.polarTocart(同上)
- 线性极坐标(cv2.linearPolar(img,center,maxRadius,flags))
- 对数极坐标(cv2.logPolar(img,cemter,M,flags))
原图
极坐标
线性极坐标
对数极坐标
至此,上半部分的内容结束了,下半部分则解释一下:对比度增强,图像平滑,阈值分割,形态学处理等剩下部分。