图像处理 混合连接

2014-02-23 11:05:04 u012627502 阅读数 3473

像素的领域:



连接性

连接(两个像素之间的关系):

空间关系:在某种意义上确定他们是否接触(领域关系)。

灰度关系:他们灰度值是否满足某个特定的相似准则(如灰度值是否相等)。V表示。

4-连接:2个像素p和r在V中取值且r在p的4邻域中。

8-连接:2个像素p和r在V中取值且r在p的8邻域中。

m-连接(混合连接):满足条件之一即可。

   1、r在p的4领域中。

   2、r在p的对角领域中且p的4角领域和r的4角邻域是空集。



关于连通:

毗邻:

图像子集毗邻:

通路:

连通:

连通组员:

连接是连通一种特例。













2018-06-21 15:11:26 QiangLi_strong 阅读数 19645

传统图像处理部分

图像处理基础知识

彩色图像、灰度图像、二值图像和索引图像区别?

彩色图像:RGB图像。灰度图像:0-255像素值。二值图像:0和1,用于掩膜图像。

索引图像:在灰度图像中,自定义调色板,自定义输出256种颜色值。

常用的图像空间

HSI、HSV、RGB、CMY、CMYK、HSL、HSB、Ycc、XYZ、Lab、YUV色彩空间(颜色模型)

RGB颜色空间是算法处理中应用最多的颜色空间。

HSI颜色空间,色调(Hue)、色饱和度(Saturation或Chroma)和亮度(Intensity或Brightness)

YUV,分为三个分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。YUV 4:4:4采样,每一个Y对应一组UV分量。YUV 4:2:2采样,每两个Y共用一组UV分量。 YUV 4:2:0采样,每四个Y共用一组UV分量。 紧缩格式(packed formats)平面格式(planar formats)。YYYYYYYYUVUV YYYYYYYYUUVV

图像的像素数与分辨率有什么区别?

像素数为图像实际组成的像素的个数,像素是没有固定宽度和高度的,是一个感光单元。

分辨率的单位为 像素/英寸(1英寸(inch)=2.54厘米(cm)),这里指的不是面积,而是对角线的长度,即dpi、ppi。分辨率也称之为点密度,分辨率越高,看的越细腻。

视频帧播放速度的单位

PAL制式是——25fps,NTSC是——30fps。

图像预处理

叙述GABOR滤波器原理?

使用一个三角函数(如正弦函数)与一个高斯函数叠加我们就得到了一个Gabor滤波器。Gabor滤波器可以抽取空间局部频度特征,是一种有效的纹理检测工具。

附:图像的空域是指二维坐标系上的操作,频域指的是图像经过傅里叶变换后的频谱。在频率域中,高频分量表示图像中灰度变换比较快的那些地方,比如物体的边缘就是灰度的突然变化,所以物体边缘就是高频分量。而物体内部比较平坦的区域,灰度基本没有变化,对应的就是低频分量。比如低通滤波只让低频分量通过,往往就是使图像模糊,因为边缘信息被去除了。高频对应图像细节,低频对应图像大致轮廓。

椒盐噪声用什么滤波处理比较有效?

参考:中值滤波与椒盐噪声

椒盐噪声:也称为脉冲噪声:

在图像中,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。

滤除椒盐噪声比较有效的方法是对信号进行中值滤波处理。

插值

最近邻插值

双线性插值

立方卷积插值

二值图像连通域搜索

matlab中连通区域标记函数bwlabel中的算法,一次遍历图像,并记下每一行(或列)中连续的团(run)和标记的等价对,然后通过等价对对原来的图像进行重新标记。

  1. 创建RUN(团)结构体,包含(纵坐标、横坐标开始、横坐标结束、标记号)
  2. 开始逐行扫描图像,寻找所有的团,将他们放到一个二维数组vector< vector<Stuct> >中,以下为每一行的操作。
    1. 当遇到一个255时,创建一个团的对象,标记纵坐标和横坐标的开始。
    2. 从开始点向右寻找,直到遇到0或者这行结束,则标记为这个团的横坐标结束。
    3. 将该行的RUN push到对应的位置。回到步骤2.1.
  3. 对众多的团进行分析,对团进行标记且得到等价对,创建一个vector< pair<int, int> >用于存放所有的等价对。
    1. 遍历所有相邻行。
    2. 若该行为第一行,则直接进行标记。
    3. 对于相邻行,遍历该行的所有RUN,对于每一个RUN,遍历上一行的所有RUN(超出范围即停止循环)。
      1. 若上一行中没有与该行RUN邻接,则创建新的标记。
      2. 若上一行只有一个与该RUN邻接,则沿用相邻RUN的标记。
      3. 若上一行有多个与该RUN邻接,则使用这多个RUN中最小的标记,并创建多个等价对。
  4. 消除等价对,可使用并查集,使得所有的团都拥有自己的祖先。
    1. 假设标记从0开始,到1000结束。标记对为类似的(0,10).(10,39)。
    2. 创建一个prev[1000]数组,初始化值为-1,记录该标记的上一级领导。初始prev[10]=0,prev[39]=10。初始化所有的等价对。
    3. 遍历所有的等价对,修改每一级的上一级领导为最上层领导。
  5. 修改每个团中的标记为最上层领导的标记。

代码见github

开源库cvBlob中使用的标记算法,它通过定位连通区域的内外轮廓来标记整个图像,这个算法的核心是轮廓的搜索算法

TODO:轮廓跟踪算法

并行计算

Intel指令集中MMX,SSE,SSE2,SSE3和SSE4指的是什么?

MMX(Multi Media eXtension,多媒体扩展指令集)是一些整数并行运算指令。

SSE(Streaming SIMD Extensions,单指令多数据流扩展)是一系列浮点并行运算指令。

SIMD,单指令多数据流,是指用一条指令执行多个计算,比如图像像素一般是BYTE占8位,而计算机中总线是64位,所以理论上可以同时进行8个像素的运算。

并行计算有哪些实现方式?

单指令多数据流SIMD、对称多处理机SMP、大规模并行处理机MPP、工作站机群COW、分布共享存储DSM多处理机。

机器学习面试题链接

机器学习部分

特征算子

常用边缘检测有哪些算子,各有什么特性和优缺点?

  1. Prewitt算子
    优点:一阶微分算子,平均滤波,对低噪声的图像有较好的检测效果。缺点:抗噪性差。
  2. Sobel算子Sobel算子
    优点:一阶微分算子,加权平均滤波,对低噪声的图像有较好的检测效果。缺点:抗噪性差。
  3. Roberts算子Roberts
    优点:一种利用局部差分算子寻找边缘的算子,定位比较精确。缺点:对噪声敏感,无法抑制噪声的影响。
  4. Laplacian算子
    优点:各向同性,二阶微分,精确定位边缘位置所在。缺点:无法感知边缘强度。只适用于无噪声图象。存在噪声情况下,使用Laplacian算子检测边缘之前需要先进行低通滤波。
  5. Laplacian of Gaussian(LoG)算子:先对图像做高斯滤波,再做Laplacian算子检测。
  6. Canny算子:一个具有滤波,增强,检测的多阶段的优化算子。先利用高斯平滑滤波器来平滑图像以除去噪声,采用一阶偏导的有限差分来计算梯度幅值和方向,然后再进行非极大值抑制。

请描述以下任一概念:SIFT/SURF LDA/PCA

SIFT/SURF为了实现不同图像中相同场景的匹配,主要包括三个步骤:
1. 尺度空间的建立;
2. 特征点的提取;
3. 利用特征点周围邻域的信息生成特征描述子;
4. 特征点匹配。

之所以采用尺度空间,是为了应对尺度不变性。

SIFT

  1. 生成高斯差分金字塔(DOG金字塔),尺度空间构建
    • 通过对原始图像进行尺度变换,获得图像多尺度下的尺度空间表示序列
    • 对这些序列进行尺度空间主轮廓的提取,并以该主轮廓作为一种特征向量,实现边缘、角点检测不同分辨率上的关键点提取等
    • 尺度空间构建的基础是DOG金字塔,DOG金字塔构建的基础是高斯金字塔
  2. 空间极值点检测(关键点的初步查探)
    • 为了寻找DOG函数的极值点,每一个像素点要和它所有的相邻点比较,看其是否比它的图像域和尺度空间域的相邻点大或者小
    • 在二维图像空间,中心点与它3*3邻域内的8个点做比较,在同一组内的尺度空间上,中心点和上下相邻的两层图像的2*9个点作比较,如此可以保证检测到的关键点在尺度空间和二维图像空间上都是局部极值点
  3. 稳定关键点的精确定位
    • DOG值对噪声和边缘比较敏感,所以在第2步的尺度空间中检测到的局部极值点还要经过进一步的筛选,去除不稳定和错误检测出的极值点,另一点就是在构建高斯金字塔过程中采用了下采样的图像,在下采样图像中提取的极值点对应在原始图像中的确切位置,也是要在本步骤中解决的问题。
  4. 稳定关键点方向信息分配
    • 稳定的极值点是在不同尺度空间下提取的,这保证了关键点的尺度不变性。为关键点分配方向信息所要解决的问题是使得关键点对图像角度和旋转具有不变性。方向的分配是通过求每个极值点的梯度来实现的。
    • 分配给关键点的方向并不直接是关键点的梯度方向,而是按照一种梯度方向直方图的方式给出的。
    • 具体的方法是:计算以关键点为中心的邻域内所有点的梯度方向,当然梯度方向一定是在0~360°范围内,对这些梯度方向归一化到36个方向内,每个方向代表了10°的范围。然后累计落到每个方向内的关键点个数,以此生成梯度方向直方图。
  5. 关键点描述
    • 对关键点的描述是后续实现匹配的关键步骤,描述其实就是一种以数学方式定义关键的过程。描述子不但包含关键点,也包括关键点周围对其有贡献的邻域点。
    • 描述的思路是:对关键点周围像素区域分块,计算快内梯度直方图,生成具有独特性的向量,这个向量是该区域图像信息的一种抽象表述。
    • 如下图,对于2*2块,每块的所有像素点的荼毒做高斯加权,每块最终取8个方向,即可以生成2*2*8维度的向量,以这2*2*8维向量作为中心关键点的数学描述。
    • David G.Lowed的实验结果表明:对每个关键点,采用4*4*8共128维向量的描述子进项关键点表征,综合效果最佳:
  6. 特征点匹配
    • 特征点的匹配是通过计算两组特征点的128维的关键点的欧式距离实现的。欧式距离越小,则相似度越高,当欧式距离小于设定的阈值时,可以判定为匹配成功。

线性判别分析(LDA), 主成分分析(PCA)

参考参考

LDA和PCA最终的表现都是解一个矩阵特征值的问题,分类的目标是,使得类别内的点距离越近越好(集中),类别间的点越远越好。

LDA的全称是Linear Discriminant Analysis(线性判别分析),是一种supervised learning。

LDA的原理是,将带上标签的数据(点),通过投影的方法,投影到维度更低的空间中,使得投影后的点,会形成按类别区分,一簇一簇的情况,相同类别的点,将会在投影后的空间中更接近。要说明白LDA,首先得弄明白线性分类器(Linear Classifier):因为LDA是一种线性分类器。对于K-分类的一个分类问题,会有K个线性函数 y = wx+b.

当满足条件:对于所有的j,都有Yk > Yj,的时候,我们就说x属于类别k。对于每一个分类,都有一个公式去算一个分值,在所有的公式得到的分值中,找一个最大的,就是所属的分类了。

y = wx+b实际上就是一种投影,是将一个高维的点投影到一条高维的直线上,LDA最求的目标是,给出一个标注了类别的数据集,投影到了一条直线之后,能够使得点尽量的按类别区分开

主成分分析(PCA)与LDA有着非常近似的意思,LDA的输入数据是带标签的,而PCA的输入数据是不带标签的,所以PCA是一种unsupervised learning。

PCA更像是一个预处理的方法,它可以将原本的数据降低维度,而使得降低了维度的数据之间的方差最大

它的目标是通过某种线性投影,将高维的数据映射到低维的空间中表示,并期望在所投影的维度上数据的方差最大,以此使用较少的数据维度,同时保留住较多的原数据点的特性。

通俗的理解,如果把所有的点都映射到一起,那么几乎所有的信息(如点和点之间的距离关系)都丢失了,而如果映射后方差尽可能的大,那么数据点则会分散开来,以此来保留更多的信息。可以证明,PCA是丢失原始数据信息最少的一种线性降维方式。(实际上就是最接近原始数据,但是PCA并不试图去探索数据内在结构)

Linear Discriminant Analysis (也有叫做Fisher Linear Discriminant)是一种有监督的(supervised)线性降维算法。与PCA保持数据信息不同,LDA是为了使得降维后的数据点尽可能地容易被区分!

特征点匹配

如下图所示,请以准确快速实现配准为目标,设计算法,让两图中对应的特征点(至少一部分特征点)配准(即精准地地找出对应点之间对应的坐标关系值)。

参考

之前是用角点检测,后来采用SIFT算子,Sift算法的实质是在不同的尺度空间上查找关键点(特征点),计算关键点的大小、方向、尺度信息,利用这些信息组成关键点对特征点进行描述的问题。

  1. 生成高斯差分金字塔(DOG金字塔),尺度空间构建
  2. 空间极值点检测(关键点的初步查探)
  3. 稳定关键点的精确定位
  4. 稳定关键点方向信息分配
  5. 关键点描述(128维向量算子)
  6. 特征点匹配(欧氏距离)

极值点邻域筛选

对于一般应用图像中,景物可能存在任意特征(如折线,弧形、亮度极值、色调等),请设计合适的算法,找到图像中可以作为明显特征点的灰度的极值点所在的邻域。以准确快速实现极值点邻域筛选为目标,设计算法。用流程图表达)。

也使用SIFT特征

特征离散化的好处

  1. 增减特征较为方便,易于迭代。
  2. 离散化后运算速度快,存储方便。
  3. 对脏数据的鲁棒性较强。
  4. 离散化一定程度简化了模型,可以防止过拟合。

分类算法

常用的分类器有哪些,并简述其原理?

线性分类器:Logistic回归 y=sigmoid(wx+b)

传统方式:特征描述和检测

KNN,K最近邻,判断图像与各个类别的距离

SVM,选定特征, SVM算法输出一个最优化的分隔超平面(分类面)。本科课题:SIFT、k-means、Bag of Words、SVM。映射函数可能为多项式。

BPNN,全连接网络,计算量巨大

CNN,卷积神经网络

迁移学习,利用别人训练好的参数,自定义网络

LR与线性回归的对比

LR的优化函数为似然函数,经典线性回归的优化函数为最小二乘。

LR将预测范围缩小到了[0,1],而经典线性回归的预测范围为整个实数。

LR与SVM的对比

相同:都是分类模型。都处理二分类。都可以添加正则项。

区别:LR是参数模型,SVM是非参数模型;LR采用logistical loss,SVM采用hinge loss;SVM之所以称之为支持向量,是因为SVM只考虑了与分类最相关的少数点来学习分类器。

KNN的K是如何选取的

K值较小意味着模型会越复杂,容易发生过拟合。K值过大会使模型过于简单,使得预测发生错误。实际使用中K一般取较小的数字。

什么是SVM?

参考http://blog.csdn.net/v_july_v/ … 24837

是一个二分分类器,找寻数据之间间隔最大的线性分类器。其学习策略是使分隔间隔最大化。对于线性可分的数据,SVM构造一个分隔面。对于线性不可分的数据,SVM采用核函数将低维空间的问题映射到了高维空间,从而线性可分。常用核函数有多项式核函数、高斯核函数、线性核函数。为了应对维度爆炸的情形,核函数事先在低维空间上进行计算,再将分类的实际效果展现在高维上。

SVM的损失函数叫做Hinge(hɪndʒ) Loss,形式为max(0,1-y*a),y为真实值+-1,a为预测值,介于-1到1之间。

简述BP神经网络

BP(back propagation)神经网络,输入X,通过隐藏节点的非线性变换后,输出信号Y,通过误差分析,来调整隐藏节点的W和b。

AdaBoost的基本原理?

AdaBoost是一个广泛使用的BOOSTING算法,其中训练集上依次训练弱分类器,每次下一个弱分类器是在训练样本的不同权重集合上训练。权重是由每个样本分类的难度确定的。分类的难度是通过分类器的输出估计的。

参考资料

//TODO 详细学习

聚类算法

简述你熟悉的聚类算法并说明其优缺点

K均值聚类(K-meansClustering)

将输入数据分到K个类中。K均值是通过循环更新类中心的初始估计值来实现的。优势是实现起来很简单,是并行化的。主要缺陷是,类的数目需要提前确定。

主要分三步:
1. 随机选取k个聚类质心点(cluster centroids)
2. 对于每一个样例i,计算其应该属于的类
3. 对于每一个类j,重新计算该类的质心
1. 重复下面过程直到收敛

层次聚类

层次聚类(或者叫做凝聚聚类)是另一个简单但是强大的聚类算法。其思想是基于成对距离建立一棵相似度树。该算法首先分组成为两个最近的对象(基于特征向量之间的距离),并且在一棵有着两个对象作为孩子的树中创建一个平均结点。然后在余下的结点中找到一个最近的pair,并且也包含任何平均节点,等等。在每一个结点,两个孩子之间的距离也会被存储。簇然后可以通过遍历这棵树并在距离比某个阈值小以至于决定聚类的大小的结点处停止来被提取出来。

层次聚类有几个优势。比如,树结构可以被用来可视化关系,并且显示簇是如何关联起来的。一个好的特征向量将得到树中好的分离。另一个优势是树可以在不同的簇阈值中被重用,而不需要重新计算树。缺点是需要选择一个阈值如果实际的簇需要的话

谱聚类

对于n个元素的相似度矩阵(或者叫affinity matrix, 有时也叫距离矩阵)是一个有着成对相似度分数的n*n矩阵。谱聚类的这个名称是从相似度矩阵构造的矩阵的谱的使用得来。这个矩阵的特征向量被用来降维,然后再聚类。

谱聚类方法的其中一个优势是唯一的输入就是这个矩阵,并且可以被你可以想到的任何相似度度量构造出来。像K均值和层次聚类这样的方法计算特征向量的平均值,这个限制了特征(或者是描述符)对向量(为了能够计算平均值)。有了谱方法,不再需要任何类型的特征向量,只有“距离”或者“相似度”。

Mean Shift 聚类算法

  1. 在未被标记的数据点中随机选择一个点作为中心center;
  2. 找出离center距离在bandwidth之内的所有点,记做集合M,认为这些点属于簇c。同时,把这些求内点属于这个类的概率加1,这个参数将用于最后步骤的分类
  3. 以center为中心点,计算从center开始到集合M中每个元素的向量,将这些向量相加,得到向量shift。
  4. center = center+shift。即center沿着shift的方向移动,移动距离是||shift||。
  5. 重复步骤2、3、4,直到shift的大小很小(就是迭代到收敛),记住此时的center。注意,这个迭代过程中遇到的点都应该归类到簇c。
  6. 如果收敛时当前簇c的center与其它已经存在的簇c2中心的距离小于阈值,那么把c2和c合并。否则,把c作为新的聚类,增加1类。
  7. 重复1、2、3、4、5直到所有的点都被标记访问。
  8. 分类:根据每个类,对每个点的访问频率,取访问频率最大的那个类,作为当前点集的所属类。

简单的说,mean shift就是沿着密度上升的方向寻找同属一个簇的数据点。

欧式距离和曼哈顿距离的区别

欧式距离为最常见的2点之间的距离,为2点之间的直线距离。

曼哈顿距离又称为L1距离或者城市区块距离,是两个点的1范数距离。

图像分割

Graph-cut的基本原理和应用?

Graph cuts是一种十分有用和流行的能量优化算法,在计算机视觉领域普遍应用于前背景分割(Image segmentation)、立体视觉(stereo vision)、抠图(Image matting)等。

利用图,将目标和背景进行分割。

图像融合,镶嵌

已知两幅拼接好的图像,两幅图像在几何关系配准之后,但两图之间存在明显灰度差别跳变,请设计一个算法对图像进行处理,让两幅图之间的灰度看不出跳变,形成自然过渡。(可以不考虑两图之间的黑图部分)。

影像融合是指高分辨率灰度图像和低分辨率彩色图像融合得到具有高分辨率的彩色图像。该算法称之为图像镶嵌。简单的做法可以是寻找两幅影像的镶嵌线,镶嵌线是指两幅影像公共区域区别最小的一条线,可以利用相关系数法判断得到,然后根据镶嵌线上两幅影像的灰度差异对右影像进行反差调整,最后拼接。

其他模型

Random Forest的随机性表现在哪里。

Bagging方法是ensemble methods中获得用于训练base estimator的数据的重要一环。 正如其名,Bagging方法就是将所有training data放进一个黑色的bag中,黑色意味着我们看不到里面的数据的详细情况,只知道里面有我们的数据集。然后从这个bag中随机抽一部分数据出来用于训练一个base estimator。抽到的数据用完之后我们有两种选择,放回或不放回。

我们可以看到从根节点开始往下会有分支,最终会走向叶子节点,得到分类结果。每一个非叶子节点都是一个特征,上图中共有三维特征。但是决策树的一个劣势就是容易过拟合,下面我们要结合上文提到的bagging技术来中和一下。

img

bagging + decision trees,我们得到了随机森林。将决策树作为base estimator,然后采用bagging技术训练一大堆小决策树,最后将这些小决策树组合起来,这样就得到了一片森林(随机森林)。

(X[1],Y[1])….(X[n],Y[n])是数据集,我们要训练T棵决策树g[1]….g[t]…g[T]。 每次从数据中有放回地随机抽取size-N’的子数据集D[t]用于训练第t棵决策树g[t]。

随机森林的随机性体现在每颗树的训练样本是随机的,树中每个节点的分裂属性集合也是随机选择确定的。有了这2个随机的保证,随机森林就不会产生过拟合的现象了。

GMM的基本原理和应用

高斯混合模型(Gaussian Mixture Model, GMM)将一个事物分解为若干的基于高斯概率密度函数(正态分布曲线)形成的模型。

高斯混合模型(GMM,Gaussian mixture model)是建模最为成功的方法之一,同时GMM可以用在监控视频索引与检索。

用于动目标检测中的背景建模。

  • 混合高斯模型使用K(++基本为3到5个++) 个高斯模型来表征图像中各个像素点的特征。
  • 在新一帧图像获得后更新混合高斯模型,用当前图像中的每个像素点与混合高斯模型匹配,如果成功则判定该点为背景点, 否则为前景点。
  • 通观整个高斯模型,他主要是有++方差++和++均值++两个参数决定,,对均值和方差的学习,采取不同的学习机制,将直接影响到模型的稳定性、精确性和收敛性。
  • 由于我们是对运动目标的背景提取建模,因此需要对高斯模型中方差和均值两个参数实时更新。
  • 为提高模型的学习能力,改进方法对均值和方差的更新采用不同的学习率
  • 为提高在繁忙的场景下,大而慢的运动目标的检测效果,引入权值均值的概念,建立背景图像并实时更新,然后结合权值、权值均值和背景图像对像素点进行前景和背景的分类。

其他理论

监督学习和非监督学习。

  • 监督学习:通过已有的一部分输入数据与输出数据之间的对应关系,生成一个函数,将输入映射到合适的输出,例如分类。
  • 非监督学习:直接对输入数据集进行建模,例如聚类。
  • 半监督学习:综合利用有类标的数据和没有类标的数据,来生成合适的分类函数。

目前最广泛被使用的分类器有人工神经网络、支持向量机、最近邻居法、高斯混合模型、朴素贝叶斯方法、决策树和径向基函数分类。

无监督学习里典型的例子就是聚类了。聚类的目的在于把相似的东西聚在一起,而我们并不关心这一类是什么。因此,一个聚类算法通常只需要知道如何计算相似度就可以开始工作了。

过拟合的解决方法

减小模型复杂度、加大数据、batch normalization、dropout、正则化、early stopping。

谈谈判别式模型和生成式模型?

常见的判别模型有:K近邻、SVM、决策树、感知机、线性判别分析(LDA)、线性回归、传统的神经网络、逻辑斯蒂回归、boosting、条件随机场。通过决策函数来进行判别。

常见的生成模型有:朴素贝叶斯、隐马尔可夫模型、高斯混合模型、文档主题生成模型(LDA)、限制玻尔兹曼机。通过联合概率密度分布函数来进行预测。

L1和L2的区别

  • L1范数为向量中各个元素的绝对值之和,符合拉普拉斯分布,可以使权值稀疏。
  • L2范数为向量中各个元素的平方和的1/2次方,符合高斯分布,可以防止过拟合。
  • Lp范数为向量中各个元素的p次方和的1/p次方。

归一化的好处

归一化加快了梯度下降求解最优解的速度;归一化还可能会提高精度。

归一化的种类

  • 线性归一化。利用max和min进行归一化,如果max和min不稳定,则常用经验值来替代max和min。
  • 标准差归一化。利用所有样本的均值和方差将样本归一化为正态分布。
  • 非线性归一化。比如指数、对数、三角函数等。

归一化和标准化的区别

标准化是依照特征矩阵的列处理数据,其通过求z-score的方法,将样本的特征值转换到同一量纲下。归一化是依照特征矩阵的行处理数据,其目的在于样本向量在点乘运算或其他核函数计算相似性时,拥有统一的标准,也就是说都转化为“单位向量”。

对于深度网络而言,归一化的目的是方便比较,可以加快网络的收敛速度;标准化是将数据利用z-score(均值、方差)的方法转化为符合特定分布的数据,方便进行下一步处理,不为比较。

熵是指样本的随机程度。样本越无序,熵越大, 信息越多。

完成机器学习项目流程

  1. 抽象成数学问题。明确我们可以获得什么样的数据,这个问题是回归还是分类。
  2. 获取数据。增加数据的代表性,防止因数据引起的过拟合。
  3. 特征预处理和特征选择。进行数据清洗,包括归一化、离散化等操作。结合数据和业务的特点来确定需要选取的特征算子。
  4. 训练模型和调优。选择一个模型进行训练,并对超参数进行调节。
  5. 模型诊断。分析模型是否过拟合或者欠拟合,然后进行相应的操作。同时可以进行误差分析,针对不同的问题来优化模型。
  6. 模型融合。将预处理和预测进行统一。
  7. 上线运行。

深度学习部分

潮流

图像检测和分割,增强学习,生成对抗网络,预测学习

基础理论

SGD 中 S(stochastic)代表什么

Stochastic Gradient Descent 随机梯度下降。GD即Full-Batch,SGD即为Mini-Batch。随机性表现在训练数据的shuffle。

Softmax Loss推一下

Sigmoid、Tanh、ReLU比较

Rectified Linear Unit, ReLU

ReLU比Sigmoid、Tanh好的原因

  1. 指数函数运算量大。ReLU节省运算量。
  2. Sigmoid容易引发梯度消失问题,因为Sigmoid函数在两端的导数趋近于0.
  3. ReLU使得一部分神经元死亡,这样可以使得网络变得比较稀疏,缓解了过拟合的发生。

引入非线性激活函数的原因?

若使用线性激活函数,则无论神经网络有多少层,输出都是输入的线性组合。

好的激活函数有以下特点:

  1. 非线性:即导数不是常数。
  2. 几乎处处可微:可微性保证了在优化中梯度的可计算性。
  3. 计算简单。
  4. 非饱和性(saturation):饱和指的是在某些区间梯度接近于零(即梯度消失),使得参数无法继续更新的问题。
  5. 单调性(monotonic):即导数符号不变。
  6. 输出范围有限:有限的输出范围使得网络对于一些比较大的输入也会比较稳定
  7. 接近恒等变换(identity):即约等于x。这样的好处是使得输出的幅值不会随着深度的增加而发生显著的增加
  8. 参数少:大部分激活函数都是没有参数的。
  9. 归一化(normalization):这个是最近才出来的概念,对应的激活函数是SELU。类似于Batch Normalization。

什么造成了梯度消失和梯度膨胀?

深度网络的链式连乘法则,使得反向传播时到达前几层时,权值更新值非常小或非常大。

可以通过ReLU解决一部分。

各大指标

先是混淆矩阵,这是基础。

混淆矩阵

包含四部分的信息:
1. True negative(TN),称为真阴率,表明实际是负样本预测成负样本的样本数
2. False positive(FP),称为假阳率,表明实际是负样本预测成正样本的样本数
3. False negative(FN),称为假阴率,表明实际是正样本预测成负样本的样本数
4. True positive(TP),称为真阳率,表明实际是正样本预测成正样本的样本数

前面有的表示预测正确。

ROC曲线

二分类标签的输出概率需要定义一个阈值p,p值的选取反映了分类器的分类性能。ROC曲线的横轴为FP(将真实负样本预测为了正样本,越低越好),纵轴为TP(将真实正样本预测为正样本,越高越好)

ROC

  • (0,0):假阳率和真阳率都为0,即分类器全部预测成负样本
  • (0,1):假阳率为0,真阳率为1,全部完美预测正确,happy
  • (1,0):假阳率为1,真阳率为0,全部完美预测错误,悲剧
  • (1,1):假阳率和真阳率都为1,即分类器全部预测成正样本
  • TPR=FPR,斜对角线,预测为正样本的结果一半是对的,一半是错的,随机分类

则,若ROC曲线处于对角线之下,则分类性能差于随机分类器。希望该曲线向左上角凸。

AUC指标

AUC(Area under the ROC curve),适用于二元分类问题,AUC实际上就是ROC曲线下的面积。AUC直观地反映了ROC曲线表达的分类能力。

  • AUC = 1,代表完美分类器
  • 0.5 < AUC < 1,优于随机分类器
  • 0 < AUC < 0.5,差于随机分类器

求解步骤:

  1. 获得样本的输出概率和标签值。
  2. 对于不同的从高到低的阈值,计算不同的TP和FP。
  3. 绘制ROC曲线,计算面积。

AUC含义:从所有真实的正样本中取一个数据,判断这个样本是正样本的概率是p1,从所有真实的负样本中取一个数据,判断这个样本是正样本的概率是p2。对于分类器来说p1越大越好,p2越小越好。则p1大于p2的概率称之为AUC。

mAP

计算步骤,参考

  1. 得到所有测试样本的id、输出概率和真实标签值。
  2. 对输出概率进行排序。
  3. 假设有M个recall值,分别计算不同recall下的准确率。
  4. 取M个准确率的平均值。

AP(average precision),

卷积神经网络

图像预处理手段

卷积和相关

相关和卷积的机理相似,但卷积滤波器首先要旋转180度。

卷积算法的时间复杂度

因为在图像的每个位置都要计算一遍卷积核,所以图像像素数为M,卷积核大小为N,则卷积的时间复杂度为O(M*N)。

池化层的作用

  • 保留主要特征的同时进行降维和减少计算量,防止过拟合,提高模型泛化能力。
  • 增加一定的不变性,在池化窗口内。包括平移、旋转、尺度不变性。

CNN特性

CNN的四个特点:局部连接、权值共享、池化操作、多层次结构。

局部连接使网络可以提取数据的局部特征;权值共享降低了网络的训练难度,一个Filter只提取一个特征;池化操作与多层次结构一起,实现了数据的降维,将低层次的局部特征组合成为较高层次的特征,从而对整个图片进行表示。

为什么很多做人脸的Paper会最后加入一个Local Connected Conv?

人脸在不同的区域存在不同的特征(眼睛/鼻子/嘴的分布位置相对固定),当不存在全局的局部特征分布时,Local-Conv更适合特征的提取。

循环神经网络

LSTM为何比RNN好

LSTM可以防止梯度消失或者爆炸

其他网络

生成对抗网络

简称GAN。该网络包含2个部分,一个称之为生成器generator,主要作用是生成图片,并且尽量使得其看上去是来自于训练样本的。另一方是discriminator,其目标是判断输入图片是否属于真实训练样本。

TensorFlow

如何理解TensorFlow的计算图?

TensorFlow分为二部分,一部分是构造部分,用来构造网络;一部分是执行部分,用来执行网络中的计算。

图像相关开放性知识

怎样在一张街拍图像中识别明星的衣着服饰信息?

我们需要把服装与背景、人物、建筑等等元素区别开来,确定是否有衣服以及衣服在什么位置。接下来需要对衣服进行分析,提取出服装的属性、特征等等。最后再根据这些特征,在庞大的数据库里搜索同款或者类似的服装图片。

上衣纯色,裙子花色,怎样做区分?

方差判断,梯度变化。

怎样判断一张广告图片中是否有文字信息?是否用到OCR技术?怎样应用?

场景文字检测与识别,先用CNN等对文字进行定位,然后再使用LSTM、OCR进行文字识别。

给一张二值化图片(包含一个正方形),怎样识别图片中的正方形?如果图片污损严重,怎样识别并恢复?

首先检测轮廓,然后对轮廓进行分析(角点)。

如果图像污损严重,如何识别?

简述图像识别在移动互联网中的应用

人脸识别、识别各类东西、检索各类图像。

图像处理领域相关顶级论文

  • Image and Vision Computing (IVC)
  • Pattern Recognition (PR)
  • ICCV: IEEE International Conference on Computer Vision
  • CVPR: IEEE Conf on Comp Vision and Pattern Recognition
  • NIPS: Neural Information Processing Systems

数学部分

公式

贝叶斯全概率公式题

全概率公式

对任一事件A,若有互不相容的事件Bi(i=1,2,...,n),满足P(Bi)>0,i=1nP(Bi)=1(i=1,2,...,n)i=1nBiA,则事件A的概率可用下式计算:

P(A)=i=1nP(Bi)P(A|Bi)

img

此概率称之为全概率公式。

Bayes公式

利用乘法公式与全概率公式可导出Bayes公式

对任一事件A,若有互不相容的事件Bi(i=1,2,,n),满足P(Bi)>0,i=1nP(Bi)=1(i=1,2,...,n)i=1nBiA,(跟上个公式条件相同)则

P(Bi|A)=P(Bi)P(A|Bi)i=1nP(Bi)P(A|Bi)(i=1,2,,n)

最小二乘拟合的公式推导和代码实现。

最小二乘法通常用于 曲线拟合 (least squares fitting) 。

推导过程

核心思想是最小化损失函数:距离差值的平方((diR)2),若想公式可导,则可以计算平方差的平方(di2R2)2

C/C++部分

基本概念

关键字static的作用是什么?

  1. 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。
  2. 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数,它是一个本地的全局变量。
  3. 在模块内,一个被声明为静态的函数只可被这一模块的它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。

简述C,C++程序编译的内存分配情况?

C,C++中内存分配方式可以分为三种:

  1. 从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快,不容易出错,因有系统自行管理。它主要存放静态数据、全局数据和常量。会默认初始化,其他两个不会自动初始化。
  2. 在栈上分配:在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
  3. 从堆上分配:即运态内存分配。程序在运行时候用malloc或new申请任意大小的内存,程序员自己负责在何进用free 和delete释放内存。

一个C、C++程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区和程序代码区。

new 和 malloc的区别

  1. malloc/free是C的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。
  2. 当使用一些非内置数据类型的对象时,maloc/free不能自动执行构造函数和析构函数。这是因为malloc/free是库函数,不在编译器控制下。

图的遍历

深度搜索DFS

递归写法

  1. 定义一个visited数组。
  2. 访问当前节点,输出该节点。
  3. 循环遍历该节点的相邻的,未被访问过的节点。
    1. 递归第二步。

非递归写法

  1. 定义一个栈和一个visited数组。
  2. 将初始节点入栈。开始循环,直道栈空。循环如下:

广度搜索BFS

设置队列

  1. 定义一个队列Queue和visited数组。
  2. 将开头节点入队。
  3. 开始循环
    1. 出队,访问该节点
    2. 遍历该节点的相邻的未被访问过的节点,入队

hash 冲突及解决办法

键字值不同的元素可能会映象到哈希表的同一地址上就会发生哈希冲突。解决办法:

  1. 开放定址法。按照一定的方法进行顺延。
  2. 再哈希法。同时构造多个不同的哈希函数。
  3. 链地址法。数组后的每个元素后添加单链表。

红黑树的特征

具有二叉查找树的所有特征。二叉查找树查找的效率最坏为O(n),红黑树通过颜色着色的方法将最坏降低到平均水平。

  1. 每个结点要么是红的要么是黑的。
  2. 根节点是黑的。
  3. 每个叶结点(树尾端的NIL指针或者NULL结点)都是黑的。
  4. 如果一个节点是红色,他的两个孩子都是黑色。
  5. 对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。

是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度,从而也就解释了上面所说的“红黑树的查找、插入、删除的时间复杂度最坏为O(log n)”

其他编程

嵌入式系统总是用户对变量或寄存器进行位操作。给定一个整型变量a,写两段代码,第一个设置a的bit3,第二消除a的 bit 3。在以上两个操作中,要保持其它位不变.

#include <iostream>
#include <bitset>
using namespace std;

#define BIT3 (0x1<<3)
void set_bit3(unsigned &a)
{
    a |= BIT3;
}
void clear_bits(unsigned &a)
{
    a &= ~BIT3;
}

int main()
{
    unsigned a = UINT_MAX;
    clear_bits(a);
    cout << (bitset<32>)a << endl;
    set_bit3(a);
    cout << (bitset<32>)a << endl;
    return 0;
}

行列递增矩阵的查找

解法一、分治法

因为矩阵的行和列都是递增的,所以整个矩阵的对角线上的数字也是递增的,故我们可以在对角线上进行二分查找,如果要找的数是6介于对角线上相邻的两个数4、10,可以排除掉左上和右下的两个矩形,而在左下和右上的两个矩形继续递归查找

解法二、定位法

首先直接定位到最右上角的元素,比要找的数大就往左走,比要找数的小就往下走,直到找到要找的数字为止,走不动,说明这个数不存在。这个方法的时间复杂度O(m+n)。代码如下:

#include <iostream>
#include <vector>
using namespace std;

bool YoungMatrix(vector< vector<int> > mat, int target){
    int y = 0, x = mat[y].size() - 1;
    int var = mat[y][x];
    while (true) {
        if (var == target){
            printf("Mat[%d][%d]=%d\n", y, x, target);
            return true;
        }
        else if (var < target && y < mat.size() - 1){
            var = mat[++y][x];
        }
        else if (var > target && x > 0){
            var = mat[y][--x];
        }
        else{
            return false;
        }
    }
}

int main(){
    vector<vector<int> > matrix(20);
    for (int i = 0; i < 20; i++){
        for (int j = 0; j < 20; j++) {
            matrix[i].push_back(i+j);
            cout << matrix[i][j] << " ";
        }
        cout << endl;
    }
    cout << YoungMatrix(matrix, 38) << endl;
    return 0;
}

从1到500的500个数,第一次删除奇数位上的所有数,第二次删除剩下来的奇数位,以此类推,最后剩下的唯一一位数是什么?

就是当1~n,2^i

给出了一个n*n的矩形,编程求从左上角到右下角的路径数(n > =2),限制只能向右或向下移动,不能回退。例如当n=2时,有6条路径。

从左上角到右下角总共要走2n步,其中横向要走n步,所以总共就是C2nn次。

给出一棵二叉树的前序和中序遍历,输出后续遍历的结果。

已知一棵二叉树前序遍历和中序遍历分别为ABDEGCFH和DBGEACHF,则该二叉树的后序遍历为多少?

#include <iostream>
#include <string>
using namespace std;

string Subsequent(string pre, string mid) {
    if (pre.size() != mid.size() || pre.empty()) return "";
    char root = pre[0];
    int rootIndex = mid.find(root);
    string leftPre = pre.substr(1, rootIndex);
    string leftMid = mid.substr(0, rootIndex);
    string rightPre = pre.substr(rootIndex + 1);
    string rightMid = mid.substr(rootIndex + 1);

    string res;
    res += Subsequent(leftPre, leftMid);
    res += Subsequent(rightPre, rightMid);
    res += root;
    return res;
}

int main(){
    string pre = "ABDEGCFH";
    string mid = "DBGEACHF";
    cout << Subsequent(pre, mid) << endl;
    return 0;
}

自定义实现字符串转为整数的算法,例如把“123456”转成整数123456.(输入中可能存在符号,和数字)

代码见github

字符串最长公共子序列

动态规划推导式

img

代码见github

字符串最长公共子串

与上文区别是不等时的处理方式,和最后是整个矩阵中寻找最大值。

代码见github

请实现一个函数:最长顺子。输入很多个整数(1<=数值<=13),返回其中可能组成的最长的一个顺子(顺子中数的个数代表顺的长度); 其中数字1也可以代表14;

直方图

#include <iostream>
#include <vector>
#include <string>
using namespace std;

vector<int> LongestShunZi(vector<int> input) {
    // 统计直方图
    vector<int> hist;
    hist.resize(15);
    for (int i = 0; i < input.size(); i++)
        if (input[i] > 0 && input[i] < 15)
            hist[input[i]] ++;
    hist[14] = hist[1];
    //最大牌数
    int maxCount = 0;
    for (int i = 1; i < 15; i++)
        if (hist[i] > maxCount)
            maxCount = hist[i];
    //求结果
    int resLen = 0;
    int resCount = 0;
    int resEnd = 0;
    for (int i = 1; i <= maxCount; i++)
    {
        int len = 0;
        int longestLen = 0;
        int longestEnd = 1;
        for (int j = 1; j < 15; j++) {
            if (hist[j] >= i) {
                len++;
                if (len > longestLen) {
                    longestLen = len;
                    longestEnd = j;
                }
            }
            else {
                len = 0;
            }
        }
        if (longestLen == 14 && 2 * i > hist[1]) longestLen--;
        if (longestLen * i > resLen * resCount) {
            resLen = longestLen;
            resCount = i;
            resEnd = longestEnd;
        }
    }

    vector<int> res;
    for (int i = resEnd - resLen + 1; i <= resEnd; i++)
        for (int j = 0; j < resCount; j++)
            res.push_back(i);
    return res;
}

int main() {
    int arr[] = { 1, 5, 2, 3, 4, 4, 5, 9, 6, 7, 2, 3, 3, 4 };
    vector<int> v(arr, arr+sizeof(arr)/sizeof(int));
    vector<int> res = LongestShunZi(v);
    for (int i = 0; i < res.size(); i++) cout << res[i] << " ";
    cout << endl;
    return 0;
}

对一批编号为1-100,全部开关朝上(开)的亮灯进行如下操作

对一批编号为1-100,全部开关朝上(开)的亮灯进行如下操作:凡是编号为1的倍数的灯反方向拨一次开关;凡是编号为2的倍数的灯反方向又拨一次开关;编号为3的倍数的灯反方向又拨一次开关……凡是编号为100的倍数的灯反方向拨一次开关。编写程序,模拟此过程,最后打印出所熄灭灯的编号。

#include <iostream>
using namespace std;

int main() {
    bool arr[101];
    memset(arr, 0, 101);

    for (int i = 2; i <= 100; i++) {
        for (int j = 1; j <= 100; j++) {
            if (j % i == 0) {
                arr[j] = !arr[j];
            }
        }
    }
    for (int i = 1; i <= 100; i++) {
        if (!arr[i])
            cout << i << endl;
    }
    return 0;
}
1
4
9
16
25
36
49
64
81
100

一个数的约数个数为奇数。所有的数都包含1和自己,平方数的约数肯定是奇数个。

实现个函数 unsigned int convect(char* pstr)

实现个函数 unsigned int convect(char* pstr)。其中pstr是十六进制数的字符串。函数convectpstr转换成数字返回(比如:字符串’1A’,将返回数值26.注意,pstr[0]是’1’)。pstr中只有数字字符0到9、A到F。不得借助其它的系统函数调用。

#include <iostream>
using namespace std;

unsigned int convect(char* pstr) {
    char *p = pstr;
    unsigned long long res = 1;
    unsigned long long maxInt = (res << 32) - 1;
    res = 0;
    while (*p != '\0') {
        if (*p >= '0' && *p <= '9') {
            res = res * 16 + *p - '0';
        }
        else if (*p >= 'A' && *p <= 'F') {
            res = res * 16 + *p - 'A' + 10;
        }
        else return 0;
        p++;
    }
    if (res > maxInt) return 0;
    return res;
}

int main() {
    cout << convect((char*)"1A") << endl;
    cout << convect((char*)"FFFFFFFF") << endl;
    cout << convect((char*)"FFFFFFFFF") << endl;
    return 0;
}

实现一个函数unsigned int counter(char* pstr)

实现一个函数unsigned int counter(char* pstr)。函数将打印出匹配的括号对。比如:字符串”a(bc(d)ef(12)g)”就存在3对匹配的括号对,分别是:
1. 位置4上的(与位置6上的)匹配。打印4 6即可。
1. 位置9上的(与位置12上的)匹配。打印9 12即可。
1. 位置1上的(与位置14上的)匹配。打印1 14即可。

软件编程部分

设计

给你一个模块要求,你要做出这个模块,那么你的做出该模块的思路和步骤是什么?

明确这个模块的功能,明确其输入以及输出。

尽量去除与其他模块的耦合关系,确保独立性。

我会首先编写输入和输出的接口函数,然后由粗到精,逐步实现细节算法。

同时还需要编写模块的测试代码,保证交付的可靠性。

Matlab编程

Matlab 中读、写及显示一幅图像的命令各是什么?

imread(), imwrite(), imshow()

Matlab 与VC++混合编程有哪几种方式?

Matlab引擎方式(Matlab后台程序为服务器,VC前端为客户端,C/S结构)、Matlab编译器(将Matlab源代码编译为C++可以调用的库文件)及COM组件(Matlab生成COM组件,VC调用)

Matlab运算中 .** 的区别?

.*表示矩阵元素分别相乘,要求两个矩阵具有相同的shape。*表示矩阵相乘。

逻辑推理部分

智力题

药丸问题

有四人装药丸的罐子,每个药丸都有一定的重量,被污染的药丸是没被污染的重量+1.只称量一次,如何判断哪个罐子的药被污染了?

答:在四个罐子里面分别取1、2、3、4颗药丸,然后进行称量。如果称量结果比实际(污染前)重了n,就是第n罐被污染了。 (因为每加一颗被污染的药丸就增加1所以增加n就是增加n颗就是在第n个罐子里拿的)

帽子黑白问题

一群人开舞会,每人头上都戴着一顶帽子。帽子只有黑白两种,黑的至少有一顶。每个人都能看到其他人帽子的颜色,却看不到自己的。主持人先让大家看看别人头上戴的是什么帽子,然后关灯,如果有人认为自己戴的是黑帽子,就打自己一个耳光。第一次关灯,没有声音。于是再开灯,大家再看一遍,关灯时仍然鸦雀无声。一直到第三次关灯,才有劈劈啪啪打耳光的声音响起。问有多少人戴着黑帽子?

解:假如只有一个人戴黑帽子,那他看到所有人都戴白帽,在第一次关灯时就应自打耳光,所以应该不止一个人戴黑帽子;如果有两顶黑帽子,第一次两人都只看到对方头上的黑帽子,不敢确定自己的颜色,但到第二次关灯,这两人应该明白,如果自己戴着白帽,那对方早在上一次就应打耳光了,因此自己戴的也是黑帽子,于是也会有耳光声响起;可事实是第三次才响起了耳光声,说明全场不止两顶黑帽,依此类推,应该是关了几次灯,有几顶黑帽。

金条问题

让工人为你工作7天,给工人的回报是一根金条。金条平分成相连的7段,你必须在每天结束时给他们一段金条,如果只许你两次把金条弄断,你如何给你的工人付费?

答:分成1、2、4段。利用1,2,4可以组合成1,2,3,4,5,6,7

拆字游戏

下面玩一个拆字游戏,所有字母的顺序都被打乱。你要判断这个字是什么。假设这个被拆开的字由5个字母组成:
1. 共有多少种可能的组合方式?
2. 如果我们知道是哪5个字母,那会怎么样?
3. 找出一种解决这个问题的方法。

个人解答:
1. A55=54321=120
1. 会依靠英文字母的规则等大致弄几种可能性出来。
1. 将弄出来的可能性的单词进行查找。

为什么下水道的盖子是圆的?

解:很大程度上取决于下水道的形状,一般为了使得各个方向的管子都可以接入到下水道中,所以下水道设计成了圆柱形,所以盖子相应的也是圆形。且圆形比较省材料,便于运输。

请估算一下CNTOWER电视塔的质量

首先在纸上画出了CNTOWER的草图,然后快速估算支架和各柱的高度,以及球的半径,算出各部分体积,然后和各部分密度运算,最后相加得出一个结果。

2019-04-23 22:24:29 Dujing2019 阅读数 2896

数字图像处理—彩色图像处理

(一) 在 MATLAB 中彩色图像的表示

1.1 RGB图像

一幅 RGB图像就是 M×N×3 大小的彩色像素的数组,其中的每个彩色像素点都是在特定空间位置的彩色图像所对应的红、绿、蓝三个分量。RGB 图像也可以看做由三个灰度图像形成的“堆栈”,当发送到彩色监视器的红、绿、蓝输入端时,就在屏幕上产生彩色图像。 按照惯例,形成一幅 RGB 彩色图像的三幅图像通常被称作红、绿、蓝分量图像

分量图像的数据类决定了它们的取值范围。如果一幅 RGB 图像的数据类是 double,那么取值范围就是 [0,1]。类似的,对于uint8类uint16类的 RGB图像,取值范围分别是[0,255]或[0,65535]。

用来表示这些分量图像像素值的比特数决定了一幅 RGB 图像的比特深度。例如,如果每个分量图像都是 8 比特的图像,那么对应的 RGB图像的深度就是 24 比特。通常,所有分量图像的比特数都是相同的。在这种情况下,一幅 RGB图像可能有的色彩数就是(2b2^b)的三次方,其中的 b 就是每个分量图像的比特数。对于 8 比特图像,颜色数为 16 777 216。

令 fR 、 fG 和 fB 分别表示三幅 RGB 分量图像。RGB 图像就是利用 cat(连接)操作将这些分量图像组合而成的彩色图像:

rab_image = cat(3, fR,  fG , fB) 

在运算中,图像按顺序放置。通常,cat(dim,A1,A2…)沿着由dim指定的方式连接数组 (它们必须是相同尺寸)。例如,如果dim=1,数组就垂直安排;如果dim=2,数组就水平安排; 如果dim=3,数组就按照三维方式堆叠

如果所有的分量图像都是一样的,那么结果是一幅灰度图像

令rgb_image表示一幅RGB图像,下面这些命令可以提取出三个分量图像:

fR = rgb_image(: , : , 1); 
fG = rgb_image(: , : , 2); 
FB = rgb_image(: , : , 3); 

在这里插入图片描述
编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\food2.jpg');
fR = rgb_image(:, :, 1);
fG = rgb_image(:, :, 2);
fB = rgb_image(:, :, 3);
subplot(2, 2, 1), imshow(rgb_image);title('(a)原图像');
subplot(2, 2, 2), imshow(fR);title('(b)红色分量图');
subplot(2, 2, 3), imshow(fG);title('(c)绿色分量图');
subplot(2, 2, 4), imshow(fB) ;title('(d)蓝色分量图');  

代码运行效果如下:

编写代码:


rgb_image=imread('D:\数字图像处理\第六章学习\food2.jpg');
fR = rgb_image(:, :, 1);
fG = rgb_image(:, :, 2);
fB = rgb_image(:, :, 3);
rgb_red=cat(3,fR,zeros(size(fR)),zeros(size(fR)));
rgb_green=cat(3,zeros(size(fR)),fG,zeros(size(fR)));
rgb_blue=cat(3,zeros(size(fR)),zeros(size(fR)),fB);
subplot(2, 2, 1), imshow(rgb_image);title('(a)原图像');
subplot(2, 2, 2), imshow(rgb_red);title('(b)红色分量');
subplot(2, 2, 3), imshow(rgb_green);title('(c)绿色分量');
subplot(2, 2, 4), imshow(rgb_blue) ;title('(d)蓝色分量'); 

代码运行效果如下:

三分量组合成RGB彩色图像

编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\food2.jpg');
fR = rgb_image(:, :, 1);
fG = rgb_image(:, :, 2);
fB = rgb_image(:, :, 3);
rgb_1=cat(3,fR,fB,fB);
rgb_2=cat(3,fR,fR,fG);
rgb_3=cat(3,fB,fG,fG);
subplot(2, 2, 1), imshow(rgb_image);title('(a)原图像');
subplot(2, 2, 2), imshow(rgb_1);title('(b)红绿绿分量组成的彩色图');
subplot(2, 2, 3), imshow(rgb_2);title('(c)红红绿分量组成的彩色图');
subplot(2, 2, 4), imshow(rgb_3);title('(d)绿蓝蓝分量组成的彩色图');  

代码运行效果如下:

RGB 彩色空间常常用 RGB 彩色立方体加以显示,这个立方体的顶点是光的原色(红、绿、蓝)和二次色(青色、紫红色、黄色)。

在这里插入图片描述
为了能从任何透视方向观测这个彩色立方体,可使用自定义函数rgbcube

rgbcube(vx,vy,vz) 

编写代码:

rgbcube(0,0,10);       %3个参数表示观看图像视角的点坐标
%rgbcube(10,10,10);    %3个参数表示观看图像视角的点坐标
axis on;grid on;
title('RGB立方体1');

代码运行效果如下:

实验总结

自然界中任何一种色光都可由R、G、B三基色按不同的比例相加混合而成,当三基色分量都为0(最弱)时混合为黑色光;当三基色分量都为k(最强)时混合为白色光。任一颜色F是这个立方体坐标中的一点,调整三色系数r、g、b中的任一系数都会改变F的坐标值,也即改变了F的色值。可以从RGB图像中提取出红、绿、蓝三个颜色的分量图像,也可由三个分量图像自由组合成彩色图,如果所有的分量图像都是一样的,那么组合结果是一幅灰度图像。从不同透视方向观测RGB彩色立方体,看到的图像是不一样的,RGB彩色空间采用物理三基色表示,因而物理意义很清楚,适合彩色显像管工作。然而这一体制并不适应人的视觉特点。因而,产生了其他不同的颜色空间表示法。

1.2 索引图像

索引图像有两个分量:整数数据矩阵 X 和彩色映射矩阵 map。矩阵 map 是 m×3 大小、由 double 类型且范围在[0,1]之间的浮点数构成的数组。map 的长度 m 等于定义的颜色数。map 的每一行都定义有单色的红、绿、蓝分量。索引图像将像素的亮度值“直接映射”到彩色值。 每个像素的颜色由对应的整数矩阵 X的值作为指向 map的索引决定。如果 X是double类型, 那么值 1 指向 map 的第一行,值 2 指向第二行,等等。如果 X是uint8或uint16类型,那么值 0 指向 map 的第一行。

有时候,用较少的颜色去近似表达索引图像是有必要的。为此,使用函数imapprox, 语法如下:

[Y, newmap] = imapprox (X, map,n) 

这个函数利用彩色映射newmap来返回数组Y,最多有n种颜色。输入数组X的类型可以 是uint8、uint16或double。如果n小于等于256,那么输出Y是uint8类;如果n大于 256,那么Y是double类。

编写代码:

RGB=imread('D:\数字图像处理\第六章学习\flower3.jpg');
[X map]=rgb2ind(RGB,256);
subplot(3, 3, 1),imshow(X,map);           %max(X(:))=255;
title('原始索引彩色图像(256色)');
[Y,newmap]=imapprox(X,map,128);%用较少的128颜色来近似一幅索引图像
subplot(3, 3, 2),imshow(Y,newmap);
title('索引图像(128色)');
[Y,newmap]=imapprox(X,map,64);%用较少的64颜色来近似一幅索引图像
subplot(3, 3, 3),imshow(Y,newmap);
title('索引图像(64色)');
[Y,newmap]=imapprox(X,map,32);%用较少的32颜色来近似一幅索引图像
subplot(3, 3, 4),imshow(Y,newmap);
title('索引图像(32色)');
[Y,newmap]=imapprox(X,map,16);%用较少的16颜色来近似一幅索引图像
subplot(3, 3, 5),imshow(Y,newmap);
title('索引图像(16色)');
[Y,newmap]=imapprox(X,map,8);%用较少的8颜色来近似一幅索引图像
subplot(3, 3, 6),imshow(Y,newmap);
title('索引图像(8色)');
[Y,newmap]=imapprox(X,map,4);%用较少的4颜色来近似一幅索引图像
subplot(3, 3, 7),imshow(Y,newmap);
title('索引图像(4色)');
[Y,newmap]=imapprox(X,map,2);%用较少的2颜色来近似一幅索引图像
subplot(3, 3, 8),imshow(Y,newmap);
title('索引图像(2色)');
[Y,newmap]=imapprox(X,map,0);%用较少的0颜色来近似一幅索引图像
subplot(3, 3, 9),imshow(Y,newmap);
title('索引图像(0色)');

代码运行效果如下:
在这里插入图片描述
在这里插入图片描述
指定彩色映射的办法有很多,一种方法就是利用如下语句:

map(k, :) = [r(k) g(k) b(k)];

其中,[r(k) g(k) b(k)]是RGB值,指定彩色映射的一行。变化的k值可将map填满。

用下面语句中的任何一条都可以把图像的背景色改成想要的颜色:

whitebg('c');   %蓝色
whitebg('y');   %黄色
whitebg('Cyan'); 
whitebg('yellow'); 
whitebg([0 1 1]);  %蓝色
whitebg([1 1 0]); %黄色

代码运行效果如下:


MATLAB提供了一些预定义的彩色映射,可用下面的指令来访问:

colormap(map_name)    %将彩色映射设定为矩阵map_name

编写代码:

colormap([spring;summer;autumn;winter])%相当于自定义了一个256*3维的colormap ,实际上spring,summer,autumn,winter,都是64*3维的colormap
x=[0 1 1 0];
y=[0 0 1 1];                           %定义四个点 [0 0] [1 0] [1 1] [0 1]
fill(x,y,[0 0.1 0.2 0.3]);             %定义四个点的C值 ,则Cmin=0,Cmax=0.3
colorbar;
map=colormap;                          %map为256*3矩阵

代码运行效果如下:

函数 描述
spring 由深红和黄色色调组成
summer 由绿色和黄色色调组成
autumn 从红色到橙色、再到黄色平缓变化
winter 由蓝色和绿色色调组成

实验总结

索引模式和灰度模式比较类似,它的每个像素点也可以有256种颜色容量,但它可以负载彩色。索引模式的图像就像是一块块由彩色的小瓷砖所拼成的,由于它最多只能有256种彩色,所以它所形成的文件相对其它彩色要小得多。索引模式的另一个好处是它所形成的每一个颜色都有其独立的索引标识。当这种图像在网上发布时,只要根据其索引标识将图像重新识别,它的颜色就完全还原了。索引模式主要用于网络上的图片传输和一些对图像像素、大小等有严格要求的地方。

1.3 处理 RGB图像和索引

下表列出了在 RGB图像、索引图像和灰度图像之间进行转换的工具箱函数。

函数 描述
Dither 采用“抖动”方法从 RGB 图像创建索引图像
grayslice 从灰度图像通过阈值处理创建索引图像
gray2ind 从灰度图像创建索引图像
ind2gray 从索引图像创建灰度图像
rgb2ind 从 RGB 图像创建索引图像
ind2rgb 从索引图像创建 RGB 图像
rgb2gray 从 RGB 图像创建灰度图像

1.函数 dither 可以用于灰度图像和彩色图像。将灰度图像转换为二值图像,将彩色图像抖动为索引图像。用于灰度图像的函数dither的语法是:

bw = dither(gray_image) 

rgb_image来表示 RGB图像,用gray_image来表示灰度图像, 用 bw 来表示黑白(二值)图像。

将灰度图像抖动为二值图像

编写代码:

f=rgb2gray(imread('D:\数字图像处理\第六章学习\cat2.jpg'));
subplot(1,2,1);
imshow(f);
title('原图');
bw=dither(f);
subplot(1,2,2);
imshow(bw);
title('将灰度图像抖动为二值图像');

代码运行效果如下:

将彩色图像抖动为索引图像

编写代码:

f=imread('D:\数字图像处理\第六章学习\sun.jpg');
subplot(1,2,1);
imshow(f);
title('原图');
x=dither(f,parula);     %colormap中自带的颜色映射-森莺
subplot(1,2,2);
imshow(x,parula);
title('将彩色图像抖动为索引图像');

代码运行效果:

2.函数grayslice使用阈值对灰度图像进行阈值处理以产生索引图像,有如下语法:

X = grayslice(gray_image, n) 

索引图像可以看做用指令 imshow(X,map)通过长度适当的映射得到的。另一种语法是:

X = grayslice(gray_image, v) 

其中,v 是矢量(值的范围为[0,1]),用来给gray_image 赋阈值。函数 grayslice 是伪彩色图像处理的基本工具,伪彩色为指定的灰度区域赋予不同的颜色。输入图像的类型可以是 uint8、uint16或double。即使输入图像的类型是uint8或uint16,v的阈值也必须在 [0,1]之间。函数执行了必要的缩放操作。

编写代码:

f=rgb2gray(imread('D:\数字图像处理\第五章学习\building.jpg'));
x=grayslice(f,16);
subplot(1,2,1);
imshow(f);
title('灰度图像'); 
subplot(1,2,2);
imshow(x,jet(16));
title('索引图像');

代码运行效果如下:

3.函数gray2ind将灰度图像I转换为索引图像,I 为原灰度图像,n 为灰度等级,默认为64,map中对应的颜色值为颜色图gray(n)中的颜色值。采用如下语法:

[X, map] = gray2ind(I ,n) 

该函数也可将二值图像BW转换为灰度图像,BW只二值图像,n 为灰度等级,默认值为2,二值图像实际上也是灰度图像,只不过灰度级为2。采用如下语法:

[X,map]=gray2ind(BW,n);

编写代码:

I=imread('D:\数字图像处理\第六章学习\face.jpg');
[Y1,map1]=rgb2ind(I,128);                  %提取原始图像的颜色映射表
X=rgb2gray(I);                              %灰度转换
[Y,map]=gray2ind(X,64);                     %灰度图像转化为索引图像
subplot(1,2,1);imshow(X);title('灰度图像');
subplot(1,2,2);imshow(Y,map);title('索引图像');

代码运行效果如下:

4.函数ind2rgb将矩阵 X 和对应的彩色映射map转换成 RGB 格式。X 可以是uint8、uint16 或double类。输出的 RGB图像是大小为 M×N×3 的double类的数组。语法为:

rgb_image = ind2rgb(X, map) 

编写代码:

I=imread('D:\数字图像处理\第六章学习\flower2.jpg');
[Y1,map1]=rgb2ind(I,128);             %提取原始图像的颜色映射表
X=rgb2gray(I);                        %灰度转换
[Y,map]=gray2ind(X,64);               %灰度图像转化为索引图像
subplot(2,2,1);imshow(I);title('原图像');
subplot(2,2,2);imshow(Y,map);title('灰度图像索引图像');
RGB=ind2rgb(Y,map1);                   %还原转化为索引图像以后的RGB
subplot(2,2,3);imshow(RGB);title('转换后的索引转RGB图像');
RGB1=ind2rgb(X,map1);                  %还原转化为索引图像以后的RGB
subplot(2,2,4);imshow(RGB1);title('原灰度矩阵索引转RGB图像');

代码运行效果如下:

(二)彩色空间之间的转换

在一幅 RGB图像中,工具箱直接把颜色描述成 RGB值,或者在索引图像中间接地用 RGB格式来存储彩色映射。 然而,还有其他的彩色空间(又被称作彩色模型),它们在应用中的使用可能比 RGB更方便或更恰当。这些模型是 RGB 模型的变换,包括 NTSC、YCbCr、HSV、CMY、CMYK 和 HSI 彩色空间。工具箱提供了从 RGB 向 NTSC、YCbCr、HSV、CMY 彩色空间转换或转换回来的函数。

2.1 NTSC彩色空间

NTSC 彩色空间用于模拟电视。这种格式的主要优势是灰度信息和彩色数据是分离开来的, 所以同一信号可以用于彩色电视机和黑白电视机。在 NTSC 格式中,图像数据由三部分组成: 亮度(Y)、色调(I)和饱和度(Q)。YIQ分量都是用线性变换从一幅图像的 RGB分量得到的:
在这里插入图片描述
注意: 第一行的各元素之和为 1,而下两行元素的和为 0。这和预想的一样,因为对于一 幅灰度图像,所有的 RGB分量都是相等的;所以对于这样的图像来说,I 和 Q分量应该是 0

获取图像的亮度,色度,饱和度

编写代码:

yiq_image=imread('D:\数字图像处理\第六章学习\flower3.jpg');
fY = yiq_image(:,:,1);
fI = yiq_image(:,:,2);
fQ = yiq_image(:,:,3);
subplot(2, 2, 1), imshow(yiq_image);title('(a)原图像');
subplot(2, 2, 2), imshow(fY);title('(b)亮度');
subplot(2, 2, 3), imshow(fI);title('(c)色度');
subplot(2, 2, 4), imshow(fQ) ;title('(d)饱和度'); 

代码运行效果如下:

函数rgb2ntsc可执行前边的变换:

yiq_image = rgb2ntsc(rgb_image) 

编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\baby.jpg');
yiq_image = rgb2ntsc(rgb_image);
imshow(yiq_image);
subplot(1, 2, 1), imshow(rgb_image);title('(a)原图像');
subplot(1, 2, 2), imshow(yiq_image);title('(b)输出图像');

代码运行效果如下:


其中,输入的 RGB图像可以是uint8、uint16或double类。输出图像是大小为 M×N×3 的 double 类数组。类似的,RGB分量可以利用下面的线性变换从 YIQ分量得到:
在这里插入图片描述
工具箱函数ntsc2rgb执行这个变换,语法是:

rgb_image = ntsc2rgb(yiq_image) 

编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\flower3.jpg');
rgb_image = rgb2ntsc(rgb_image);
f = ntsc2rgb(rgb_image);
imshow(yiq_image);
subplot(1, 2, 1), imshow(rgb_image);title('(a)NTSC空间图像');
subplot(1, 2, 2), imshow(f);title('(b)RGB空间图像');

代码运行情况如下:


输入和输出图像都是double类。

2.2 YCbCr 彩色空间

YCbCr 彩色空间广泛用于数字视频。在这种格式中,亮度信息用单独的分量 Y来表示,彩色信息是用两个色差分量 Cb 和 Cr来存储的。分量 Cb蓝色分量与参考值的差,分量 Cr红色分量与参考值的差。工具箱采用的从 RGB转换为 YcbCr 的变换是:

在这里插入图片描述
转换函数是:

ycbcr_image = rgb2ycbcr(rgb_image)

输入的 RGB 图像可以是 uint8、uint16 或 double类。输出图像和输入图像的类型相同。使用类似的变换可以从 YCbCr 转换回 RGB:

rgb_image = ycbcr2rgb(ycbcr_image) 

编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\Pig2.jpg');
ycbcr_image = rgb2ycbcr(rgb_image)
f = ycbcr2rgb(ycbcr_image) 
subplot(1, 3, 1), imshow(rgb_image);title('(a)输入的RGB图像');
subplot(1, 3, 2), imshow(ycbcr_image);title('(b)RGB空间图像转换为 YCbCr 图像');
subplot(1, 3, 3), imshow(f);title('(c)YCbCr 图像转换为RGB空间图像');

代码运行情况如下:
在这里插入图片描述
在这里插入图片描述
输入的 YCbCr 图像可以是 uint8、uint16 或 double 类。输出图像和输入图像的类型相同。

2.3 HSV彩色空间

HSV(色调、饱和度、值)是人们用来从颜色轮或调色板中挑选颜色(例如颜料或墨水)时使用的彩色系统之一,值得考虑的是,这个颜色系统比 RGB 系统更接近人们的经验和对彩色的感知。HSV颜色空间的模型对应于圆柱坐标系中的一个圆锥形子集,圆锥的顶面对应于V=1。它包含RGB模型中的R=1,G=1,B=1三个面,所代表的颜色较亮。色彩H由绕V轴的旋转角给定。红色对应于角度0°,绿色对应于角度120°,蓝色对应于角度240°。在HSV颜色模型中,每一种颜色和它的补色相差180°。饱和度S取值从0到1,所以圆锥顶面的半径为1。
在这里插入图片描述

从 RGB 到HSV 的转换

数学公式推算

设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数。设 max 等价于 r, g 和 b 中的最大者。设 min 等于这些值中的最小者。要找到在 HSV 空间中的 (h, s, v) 值,这里的 h ∈ [0, 360)是角度的色相角,而 s, v ∈ [0,1] 是饱和度和亮度,计算为:

max=max(R,G,B)
min=min(R,G,B)
if R = max, H = (G-B)/(max-min)
if G = max, H = 2 + (B-R)/(max-min)
if B = max, H = 4 + (R-G)/(max-min)

H = H * 60
if H < 0, H = H + 360

S=(max-min)/max
V=max(R,G,B)

注意:h 的值通常规范化到位于 0 到 360°之间。而 h = 0 用于 max = min 的(就是灰色)时候而不是留下 h 未定义。

从 HSV 到 RGB 的转换

数学公式推算

类似的,给定在 HSV 中 (h, s, v) 值定义的一个颜色,带有如上的 h,和分别表示饱和度和明度的 s 和 v 变化于 0 到 1 之间,在 RGB 空间中对应的 (r, g, b) 三原色可以计算为:
在这里插入图片描述在这里插入图片描述
将 RGB转换为 HSV的 MATLAB函数是rgb2hsv,语法如下:

hsv_image = rgb2hsv(rgb_image) 

输入的 RGB图像可以是uint8、uint16或double类,输出图像是double类。将 HSV 转换回 RGB的函数为hsv2rgb,语法如下:

rgb_image = hsv2rgb (hsv_image) 

编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\flower5.jpg');
hsv_image = rgb2hsv(rgb_image)
f = hsv2rgb(hsv_image) 
subplot(1, 3, 1), imshow(rgb_image);title('(a)输入的RGB图像');
subplot(1, 3, 2), imshow(hsv_image);title('(b)RGB空间图像转换为HSV图像');
subplot(1, 3, 3), imshow(f);title('(c)HSV图像转换为RGB空间图像');

代码运行效果如下:

在这里插入图片描述在这里插入图片描述
上面图片只是简单的转换,看不出来HSV图像的优势,下面进行图像颜色调整

编写代码

h = input('Adjust hue by: ');        % 输入色度调整参数h
s = input('Adjust saturation by: ');        % 输入饱和度调整参数s
v = input('Adjust intensity by: ');        % 输入明度调整参数v

I = imread('D:\数字图像处理\第六章学习\flower4.jpg');    % 读取源图像并显示
figure(1);
imshow(I);title('(a)原图像');
% HSV颜色空间处理
hsv_image = rgb2hsv(I);        % 将rgb颜色空间转换为hsv颜色空间
hue = hsv_image(:,:,1);        % 提取色度通道
sat = hsv_image(:,:,2);        % 提取饱和度通道
int = hsv_image(:,:,3);        % 提取明度通道

hue = hue + 1 / 360 * h;    % 对各通道进行处理
sat = sat + 0.01 * s;
int = int + 0.01 * v;

%hue(hue>1)=hue(hue>1) - 1; hue(hue<0)=1 - hue(hue<0);
hue(hue>1)=1; hue(hue<0)=0;
sat(sat>1)=1; sat(sat<0)=0;
int(int>1)=1; int(int<0)=0;

hsv_image(:,:,1) = hue;        % 运算后的各通道返回原图
hsv_image(:,:,2) = sat;
hsv_image(:,:,3) = int;

% matlab 无法直接显示hsv和hsi图像,还要先转换为rgb
rgb = hsv2rgb(hsv_image);    % 将hsv颜色空间转换为rgb颜色空间,并显示
figure(2);
imshow(rgb);title('(b)HSV颜色空间处理后的图像');

代码运行效果如下:

实验总结

HSV(Hue Saturation Value)颜色模型是面向用户的。在图像处理中,通常情况下不会直接对RGB图像做处理,这主要是因为RGB与人类的视觉感知相差较远,而HSV就是常用的色彩空间。比如,某些由于光照不同造成的视觉感知不同的场景下,通常用Value这个通道进行计算,通过计算梯度,可以较好的提取物体边缘。再比如某些场景下,前景饱和度较高,背景采用饱和度较低的颜色来衬托前景,这时Saturation这个通道的信息就非常有用了。再比如,在某些室内场景下,风格较为单一,一般一个物体只有一种颜色,这时候Hue这个通道就显得尤为重要了。总之,HSV色彩空间在图像处理领域应用非常广泛,一般通过采用合适的通道就能完成大多数图像预处理工作。从上图(西湖荷花)也可以看出进行了色度,明度,饱和度的调整,图像变得更加鲜艳,接近物体本来的色彩,更符合人的视觉。

2.4 CMY和 CMYK

CMY(青,深红,黄)通过颜色相减来产生其他颜色的。大多数将颜料堆积于纸上的设备,比如彩色打印机和复印机,都需要 CMY 数据输入,或在内部将 RGB转换为 CMY,近似的转换可用下面的公式实现:
在这里插入图片描述
其中,假想所有的颜色值都已经归一化在[0,1]之间。这个公式证明从涂满纯青色的表面反射的光不包含红色(公式中的 C = 1–R )。同样,纯净的紫红色不反射绿色纯净的黄色不反射蓝色。上述公式还证明,从 1 减去个别的 CMY 值,可以从一组 CMY 值很容易地获得 RGB值。

imcomplement函数可近似地把 RGB模型转换为 CMY模型:

cmy_image = imcompliment(rgb_image) 

也可以用这个函数将 CMY图像转换为 RGB图像:

rgb_image = imcompliment(cmy_image) 
rgb_image=imread('D:\数字图像处理\第六章学习\flower5.jpg');
hsi_image = imcomplement(rgb_image);
j=imcomplement(hsi_image);
subplot(1, 3, 1), imshow(rgb_image);title('(a)输入的RGB图像');
subplot(1, 3, 2), imshow(hsi_image);title('(b)RGB空间图像转换为CMY图像');
subplot(1, 3, 3), imshow(j);title('(c)CMY图像转换为RGB空间图像');

在这里插入图片描述
在理论上,等量的颜料原色,将青色、紫红色和黄色混合会产生黑色。在实践中,将这些颜色混合印刷会生成模糊不清的黑色。所以,为了生成纯正的黑色(打印中主要的颜色),第 4 种颜色——黑色便添加进来了,从而给出提升的 CMYK彩色模型。这种模式的文件大,占用的磁盘和内存大,一般在印刷时使用。

2.5 HSI彩色空间

HSI(色彩、饱和度、强度),该模型将强度分量与从一幅彩色图像中承载的彩色信息分开。正如结果那样,HSI 模型是开发基于彩色描述的图像处理算法的理想工具

1.将颜色从 RGB 转换为 HSI

每个 RGB像素的 H分量可用下面的公式得到:
在这里插入图片描述
其中:
在这里插入图片描述
饱和度由下面的式子给出:
在这里插入图片描述
最后,亮度由下面的式子给出:
在这里插入图片描述
将从 H 的公式中得出的所有结果除以 360°,即可将色调归一化在[0,1]之间。 如果给出的 RGB值在[0,1]之间,那么其他的两个 HSI 分量就已经在[0,1]之间了。

下面是惯用的函数:

hsi = rgb2hsi(rgb) 

编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\sun.jpg');
hsi_image = rgb2hsi(rgb_image)
subplot(1, 2, 1), imshow(rgb_image);title('(a)输入的RGB图像');
subplot(1, 2, 2), imshow(hsi_image);title('(b)RGB空间图像转换为HIS图像');

代码运行效果如下:

2.将颜色从HSI 转换为RGB

有三个感兴趣的部分,正如早些时候提到的那样,分别对应原色之间相隔 120° 的范围。用 360°乘以 H,这样就将色调的值还原成了原来的范围——[000^0,36000^0]。

RG区域(000^0≤H≤36000^0)如果 H在这个区域内,那么 RGB分量由下式给出:

在这里插入图片描述

在这里插入图片描述
GB区域 (12000^0≤H<24000^0)如果给出的H值在这个区域内,我们就先从中减去120°:
在这里插入图片描述
那么,这时 RGB分量是:
在这里插入图片描述
并且
在这里插入图片描述
BR 区域(240°≤H≤360°) 最后,如果 H在这个区域内,我们就从中减去 240°:
在这里插入图片描述
RGB分量分别是:
在这里插入图片描述
其中:
在这里插入图片描述

在这里插入图片描述
编写代码:

rgb_image=imread('D:\数字图像处理\第六章学习\building.jpg');
hsi_image = rgb2hsi(rgb_image);
j = hsi2rgb(hsi_image);
subplot(1, 3, 1), imshow(rgb_image);title('(a)输入的RGB图像');
subplot(1, 3, 2), imshow(hsi_image);title('(b)RGB空间图像转换为HIS图像');
subplot(1, 3, 3), imshow(j);title('(c)HIS图像转换为RGB空间图像');

代码运行效果如下:
在这里插入图片描述
在这里插入图片描述
上面图片只是简单转换,看不出来HSI图像的优势,下面进行图像颜色调整:

编写代码:

h = input('Adjust hue by: ');        % 输入色度调整参数h
s = input('Adjust saturation by: ');        % 输入饱和度调整参数s
i = input('Adjust intensity by: ');        % 输入强度调整参数i

I = imread('D:\数字图像处理\第六章学习\flower4.jpg');    % 读取源图像并显示
figure(1);
imshow(I);title('(a)原图像');
% HSI颜色空间处理
hsi_image = rgb2hsi(I);        % 将rgb颜色空间转换为hsi颜色空间
hue = hsi_image(:,:,1);        % 提取色度通道
sat = hsi_image(:,:,2);        % 提取饱和度通道
int = hsi_image(:,:,3);        % 提取明度通道

hue = hue + 1 / 360 * h;       % 对各通道进行处理
sat = sat + 0.01 * s;
int = int + 0.01 * i;

%hue(hue>1)=hue(hue>1) - 1; hue(hue<0)=1 - hue(hue<0);
hue(hue>1)=1; hue(hue<0)=0;
sat(sat>1)=1; sat(sat<0)=0;
int(int>1)=1; int(int<0)=0;

hsi_image(:,:,1) = hue;        % 运算后的各通道返回原图
hsi_image(:,:,2) = sat;
hsi_image(:,:,3) = int;

rgb = hsi2rgb(hsi_image);    % 将hsi颜色空间转换为rgb颜色空间,并显示
figure(3);
imshow(rgb);title('(b)hsi颜色空间转换后的图像');

代码运行效果如下:

实验总结

由图可以明显看出HSI模型相对于RGB模型更适宜用于彩色图像的增强,完全反映了人感知颜色的基本属性,与人感知颜色的结果一一对应,因此,HSI模型被广泛应用于人的视觉系统感知演的的图像表示和处理系统中。并且在处理彩色图像时,可仅对I分量进行处理,结果不改变原图像中的彩色种类,所以HSI 模型是开发基于彩色描述的图像处理算法的理想工具

2.6 独立于设备的彩色空间

彩色空间以使计算更方便的方法描述了彩色信息,或以对特殊应用更直观或更合适的方法描述彩色。迄今为止讨论的所有空间都与设备相关。下面集中讨论独立于设备的彩色空间。

2.6.1 背景

通常,在辨别不同颜色时使用的特征是亮度、色调和饱和度。亮度具体表达无色的强度的概念,色调是在光波混合中与主要波长相关的属性,色调描述了观察者感知的主要彩色,饱和度指的是相对纯度或与色调相混合的白光数量。

色调和饱和度合起来称为颜色,因此,彩色是由颜色和亮度表现的特性。为形成一种特殊颜色而需要的红、绿、蓝颜色叫做三色值,分别用 X、Y、Z 来表示。颜色是由颜色自身的三色系数来指定的,定义为:
在这里插入图片描述
并且:
在这里插入图片描述
其中,x、y 和 z 分别表示红、绿、蓝分量。在可见光谱中,光的任何波长均可产生与那个波长相对应的三色值。以 x 和 y 为参数的函数显示人能感觉到的颜色范围的图被称为色度图。在色度图中,连接任意两个点的直线段说明了所有不同的颜色变化,可以由相加的两种颜色混合得到。由任何三个固定颜色处的顶点形成的三角形不能包括图中的全部颜色区域,所以任何颜色都可从确定的三原色产生是误解

2.6.2 sRGB 彩色空间

RGB彩色模型依赖于设备。这意味着对于给定的一组 R、 G、B 值,不存在单一、明确的彩色解释。另外,图像文件常常不包含获取图像时所用设备的彩色特性信息。就像结果那样,相同的图像文件可能(经常就是)在不同的计算机系统中看上去明显不同。

解决这个问题,微软和惠普提出了新的默认彩色空间标准,称作 sRGB。sRGB 彩色空间被设计为与计算机的CRT监视器标准特性相一致,并且与PC机在家庭和办公室观察环境相一致。 sRGB彩色空间独立于设备。因此,sRGB颜色值很容易被改变为另一个独立于设备的彩色空间。

sRGB 标准已变成计算机界广泛接受的标准,特别是面向消费者的设备。数字摄像机、扫 描仪、计算机显示器和打印机等,都例行地被设计为假定图像的 RGB值与 sRGB的彩色空间是一致的,除非图像文件包含更多的指定设备的彩色信息。

2.6.3 CIE 和 sRGB 彩色空间之间的转换

工具箱函数 makecform 和 applycform 可用于独立于设备的彩色空间之间的转换。

以Lab彩色空间为基础创建在感觉上的一致彩色空间

构建一个彩色标尺,可用于彩色和黑色出版物,设计在40和80之间的间隔相等的估值为1024的斜坡;

编写代码:

L=linspace(40,80,1024);
radius=70;
theta=linspace(0,pi,1024);
a=radius*cos(theta);
b=radius*sin(theta);
%我们制作一幅 L*a*b* 彩色标尺的 100×104×3 大小的图像: 
L=repmat(L,100,1);  
a=repmat(a,100,1);
b=repmat(b,100,1);
lab_scale=cat(3,L,a,b);
cform =makecform('lab2srgb');
rgb_scale= applycform(lab_scale,cform);
imshow(rgb_scale);

代码运行效果如下:
在这里插入图片描述
图为 基于 Lab*彩色空间的在感觉上一致的标尺 。

2.6.4 ICC彩色剖面

每一个设备正好有两个与之关联的变换,而不管在系统中可能存在的其他设备的数量。其中的一个变换把设备彩色转换为标准,独立于设备的彩色空间叫做剖面连接空间(Profile Connection Space, PCS)。另一个变换是第一个变换的反变换,用来把 PCS彩色转换回设备彩色(PCS不是 XYZ, 就是 Lab*)。这两个变换合起来构成设备的 ICC 彩色剖面

ICC 的主要目的之一是创建标准化的、维护和提升 ICC彩色剖面的标准。图像处理工具箱 函数iccread读取剖面文件,语法是:

p = iccread(filename) 

输出p是包含文件头信息和数字参数,以及计算设备和PCS间彩色空间转换所必需的表格。 使用 ICC 剖面转换彩色是通过使用makecform和applycform实现的。 makecform的语法是:

cform = makecform('icc', src_profile, dest_profile) 

其中,src_profile是源设备剖面的文件名,dest_profile是目的设备剖面的文件名。

ICC 彩色剖面的软实验

编写代码:

f=imread('D:\数字图像处理\第六章学习\girl.png');
fp = padarray(f, [40 40], 255, 'both'); 
fp = padarray(fp, [4 4], 230, 'both'); 
p_srgb = iccread('E:\Code\sRGB.icm');           %描述sRGB彩色空间的剖面
p_snap = iccread('E:\Code\SNAP2007.icc');       %新闻纸剖面
cform1 = makecform('icc', p_srgb, p_snap); 
fp_newsprint = applycform(fp, cform1); 
cform2 = makecform('icc', p_snap, p_srgb,  'SourceRenderingIntent', 'AbsoluteColorimetric', 'DestRenderingIntent', 'AbsoluteColorimetric'); 
fp_proof = applycform(fp_newsprint, cform2);   %指定渲染意图
subplot(1, 2, 1), imshow(fp);title('(a)具有白边的原始图像');
subplot(1, 2, 2), imshow(fp_proof);title('(b)当在新闻纸上打印时对图像外观的模拟 ');

代码运行效果如下:

实验总结

实验中首先用环绕图像的拥有粗白边和细灰边的边界对图像做预处理。这些边界将使得更容易观察对新闻用纸“白”度的模拟,图(a)显示了填充的图像,然后读进两个剖面并用它们把虹膜图像从 sRGB转换为新闻纸颜色,最后用绝对色度的渲染意图创建cform结构,以便为了显示而将之转换回 sRGB,图 (b)显示了结果。这幅图像本身仅是在计算机监视器上看到的实际结果的近似,因为印刷书籍的彩色全域与监视器的彩色全域不同。

(三)彩色图像处理的基础知识

彩色图像处理细分成 3 个主要领域:

  1. 颜色变换(也叫彩色映射)
  2. 单独彩色平面的空间处理
  3. 颜色向量的处理

第 1 类处理每个彩色平面的像素,这类处理严格地以像素值为基础,而不是它们的空间坐标,类似于灰度变换处理。第 2 类处理涉及各个彩色平面的空间(邻域)滤波, 类似于空间滤波。第 3 类处理涉及以同时处理彩色图像的所有分量为基础的处理技术。因为全彩图像至少有三个分量,彩色像素可以用向量来处理。

令 c 代表 RGB彩色空间中的任意向量:
在这里插入图片描述
这个公式指出,c 分量是一副彩色图像在某个点上的 RGB分量。考虑彩色分量是坐标的函数这样的事实,用下边的符号表示:
在这里插入图片描述
对于一幅大小为 M×N 的图像,有 MN 个这样的向量 c(x,y),其中,x=0,1,2…,M–1 且 y=0,1,2…,N–1。

在某些情况下,无论彩色图像每次处理一个平面,还是作为向量处理,都会得到相等的结果。然而,不会总是这样的情况。为了使两种方法都相同, 两个条件必须满足:首先,处理必须对向量和标量都可用。其次,针对向量的每个分量的操作必须与其他分量无关

(四)彩色变换

这里描述的是单一彩色模型情况下的技术,以处理彩色图像的彩色分量或单色图像的亮度分量为基础。对于彩色图像,限定如下形式的变换:

si = Ti(ri) i = 1,2,…,n

这里,ri 和 si 是输入和输出图像的彩色分量,n 是 ri是彩色空间的维数(或是彩色分量的数量),并且 Ti 是全彩色变换(或叫映射)函数。如果输入图像是单色的,公式将如下所示:

si = Ti( r ) i = 1,2,…,n

r表示灰度级的值,n 是在 Si中彩色分量的数量。这个公式描述了灰度级对任意颜色的映射,这一处理在伪彩色变换或伪彩色映射中经常提到。 注意,如果我们让 r1=r2=r3=r,第一个公式可用来处理 RGB中的单色图像。

三次样条内插用spline函数来实现:

Z = spline(x,y,xi) 

编写代码:

x=0:10;
y=sin(x);
subplot(121),plot(x,y,'+',x,y,'r');%画xy图像,并标出x和y点
xx=0:.25:10;
yy=spline(x,y,xx);
subplot(122),plot(x,y,'o',xx,yy,'b');%也是画xy图像,标出x和y点,但是这中间插值了隔.25的数,只是没被标出来

代码运行效果如下:

变换函数的说明可以用图形法操作控制点的方式交互地产生,那些控制点输入到 interpiq和spline函数并实时地显示将被处理的图像的结果。语法是:

g = ice('property name', 'property value',…) 

最后的结果是带有句柄的图像g(通常是图形目标)。

编写代码:

f=imread('D:\数字图像处理\第六章学习\cat5.jpg');
g=ice('image',f);

代码运行效果如下:

编写代码:

f=imread('D:\数字图像处理\第六章学习\cat5.jpg');
g=ice('image',f,'space','CMY');%修改CMY彩色空间

代码运行效果如下:

编写代码:

f=imread('D:\数字图像处理\第六章学习\cat5.jpg');
g=ice('image',f,'space','hsi');

代码运行效果如下:

‘space’是被修改的分量彩色空间。可能的值是’rgb’、‘cmy’、‘hsi’、‘hsv’、‘ntsc’(或’yiq’)和’ycbcr’,默认值是’rgb’ 。

2014-02-22 20:24:59 yunken28 阅读数 14846
关于像素的邻接,连接和连通
 

以前总是觉得都明白,再系统看一下书,发现记忆还是不牢靠。

现在写下来,以后应该对基本概念掌握好!!

首先邻域的概念有4邻域,8邻域之分。其中8邻域=4邻域+对角邻域。

邻接:两个像素接触,则它们是邻接的。一个像素和它的邻域中的像素是接触的。邻接仅考虑像素的空间关系。

连接:(1)是邻接的。(2)灰度值(或其他属性)满足某个特定的相似准则(灰度相等或在某个集合中等条件)。

这样我们就有了4-连接,8-连接和m-连接的概念,这些概念我在上图像处理课的时候理解的不好,这里详细讲一下。

    (1)4-连接:2个像素p和r在灰度集合V中取值且r在N4(p)---p的4邻域中。

    (2)8-连接:概念类似(1)。

    (3)m-连接:也叫混合连接,2个像素p和r在灰度集合V中取值且满足<1>r在N4(p)中;<2>r在Nd(p)中且N4(p)与N4(r)的交集元素不在V中。

“混合连接实质上是在像素间同时存在4-连接和8-连接时,优先采用4-连接,并屏蔽两个和同一像素间存在4-连接的像素之间的8-连接。”这是《图像工程》中的原话,我觉得对m-连接的概念讲得比较好理解,而且印象深刻。

说来也好理解,这种m-连接的引入目的之一就是消除8-连接的多路问题。8-连接在像素距离的选择时有多种路径,引发歧义,而m-连接则没有。

连通:说白了和图里的节点连通性道理一样。就是两个像素之间,如果有一条通路能把它们连接起来,那么就是连通的了。当然,连接是连通的一种特例,就是在两个邻近的像素之间的连通。对应连接的概念,连通也分4-连通和8-连通。

在像素的邻接和连通定义我们都熟知后,其实还有比较复杂点的概念引入,那就是像素集合的邻接和连通。如果把一幅图像看做是所有像素的集合,那么根据像素间的关系则可把像素结合成图像的子集合。那么显然这些子集也满足像图像像素元素那样的连通和连接性质(这个应该可以归纳证明的~~这里偷个懒吧囧)。对图像子集S中的任何一个像素p,所有和p相连通又在S中的像素的集合合起来称为S中的一个连通组元。如果S只有一个连通组元,即S中所有像素都互相连通,那么S就是一个连通集。如果一幅图像的所有像素都分属于几个连通集,则可以说这几个连通集是整个图像的连通组元。图像里的每个连通集构成图像的一个区域,这样我们就引入了区域的概念。P.S.正好前段时间做了区域增长的图像分割,看到这里好亲切啊!~~一个区域的边界(区域轮廓)将区域之间分开。

2017-06-28 22:02:59 DdiIcey 阅读数 16629

图像的像素的意义

一幅图像,经过取样和量化之后就可以得到数字图像。数字图像在存储时,都是由单一的像素保存在存储设备中。像素保存顺序是与像素在数字图片中原本所处在的物理位置相关,那么就要了解像素之间的一些基本关系。

在数字图像处理领域,存在着空间域和变换域的概念。数字图像处理的基本操作,有些需要在空间域中进行,而另外的一些则需要在变换域中进行。
空间域:就是指图像的本身,由所采集到的一个个像素组成。对目标像素进行常用的处理方法,例如灰度变换和空间滤波两大类。
变换域:通过特定的变换函数,将图像的像素变化到目标域中,在变换域中完成相应的操作运算后,再利用反变换核返回到空间域。
由上可知,无论在空间域还是在变换域,像素都是根本。在大多数的数字图像处理中,像素之间在运算时都是要发生关系的,这是因为多个像素构成了图像中的一个对象。

图像是由像素的形式来保存的,所以我们以f(x,y)来表示图像,对于特定像素,分别用p和q来表示。

相邻像素

在这节中主要讨论一个像素p的所有的相邻像素,所有的相邻像素与像素p的距离均不超过√2。.
位于坐标(x,y)处的像素p,在水平和垂直方向分别有两个像素与其相邻,对应坐标为:
(x+1,y), (x-1,y), (x,y+1), (x,y-1)
这一组像素称为像素p的4邻域,用N_4 (p)来表示。
对于同样的像素p,在其对角方向有4个像素与其相邻,对应坐标为:
(x-1,y-1), (x-1,y+1), (x+1,y-1), (x+1,y+1)
这一组像素用N_D (p)来表示。
上面的8个坐标点,构成了像素p的8邻域,用N_8 (p)来表示。
在讨论像素点的时候,会遇到这样的情况:像素p位于图像的边界,这样无论是N_4 (p),N_D (p)都有一些点是不存在的,在目前,讨论这些像素点是没有任何意义。在做特定像素运算的时候,再根据运算的性质来确定如何来处理边界像素的相邻像素。

下图为相邻像素的示意图:


N_8 (p)= N_4 (p)+ N_D (p)

邻接性、连通性

在灰度图像中,假如灰度位数为8bit,那么所有的可能灰度取值范围为[0,255]。为了方便讨论和分析,现只考虑二值图像,即灰度值只有0和1两种情况。定义V为所要讨论的像素的邻接性灰度值集合。则在二值图像中V={1}。分析三种类型的邻接:
  • 4邻接。如果像素q在集合N_4 (p)中,则具有V中灰度值的两个像素q和p是4邻接的。
  • 8邻接。如果像素q在集合N_8 (p)中,则具有V中灰度值的两个像素q和p是8邻接的。
  • m邻接。如果(1)q在集合N_4 (p)中,或者(2) 像素q在集合N_D (p)中,且集合N_4 (p)∩N_4 (q)没有来自V中灰度值的像素,则具有V中数值的两个像素p和q是m邻接的。
对于邻接性,更鲜明扼要的解释如下:
  • 4邻接。像素p q的灰度值属于集合V,像素q在N_4 (p)中
  • 8邻接。像素p q的灰度值属于集合V,像素q在N_8 (p)中
  • m邻接。像素p q的灰度值属于集合V,像素q在N_4 (p)中或者像素q在N_D (p)中,且集合N_4 (p)∩N_4 (q)没有来自V中数值的像素。

下图分别给出了4邻接,8邻接,m邻接的示意图。




接下来需要考虑一个问题,在有8邻接后,为什么要引入m邻接的定义呢?在《数字信号处理》2.5.2节中,作者给出的原因是,ml邻接主要是为了消除8邻接的二义性。那么,二义性怎么体现呢?首先来解释什么是像素的通路。

像素的通路

从坐标(x,y)的像素p到坐标为(s,t)的像素q的通路,是由一系列的特定像素组成的序列,其坐标为:
(x0,y0), (x1,y1), …, (xn,yn)
其中(x0,y0) = (x,y), (xn,yn) = (s,t). 并且像素(xi,yi)和(xi-1,yi-1)对于1≤i≤n是邻接的(4邻接,8邻接,m邻接)。在这种情况下,n是通路的长度。从像素p到像素q就形成了一个像素通路。

当按照特定的邻接性来确认像素的通路时,必须保证通路的唯一性,在下图的例子中,如果选择8邻接,则通路并不是唯一的,所以具有二义性。当考虑m邻接的时候,则通路就是唯一的,这就是m邻接可以消除8邻接的二义性体现。



由上图可以看出,在从像素p到像素q的通路中,如果考虑8邻接,那么通路就不具有唯一性。


令S是图像中的一个像素子集,如果S的全部像素之间存在一个通路,则可以说两个像素p和q在S中是连通的。对于S中的任何像素p,S中连通到该像素的像素集成为S的连通分量。如果S仅有一个连通分量,则集合S成为连通集。概括来说,S中的所有的像素,每两个相邻的像素之间是相邻接的(4,8,m),并且只有一个通路,那么S为连通集。

令R是图像中的一个像素子集。如果R是连通集,则R被称作为一个区域。两个区域Ri和Rj如果能形成一个连通集,那么称这两个区域为邻接区域。不过在讨论是否为邻接区域的时候,只能考虑区域边界的像素是否构成4邻接和8邻接,而不考虑m邻接。在定义区域邻接的时候,必须指定邻接类型。

注意:在《数字图像处理第三版》的2.5.2节中,“不邻接的区域称为不连接区域”应该是错误,修改成“不邻接的区域称为不邻接区域”。

图像处理基本知识

阅读数 12796