图像处理中的灭点_matlab 灭点 - CSDN
  • 一点透视投影的X方向校正和Y方向校正

    图像预处理——透视变换(二):X,Y方向校正原理

    接着上一篇进行,上一篇为:

    Nani_xiao的图像处理学习笔记:透视变换(一)

    这里采用一点透视投影

    X 方向校正

    图2 是透视投影的灭点原理图。在不考虑其他畸变的情况下,边ab 和边cd 平行于X 轴, 而边ac 和边bd 则和X 轴成一定的夹角。根据a 、b 、c 、d 点的图像坐标,可以求出透视投影的灭点e 的坐标(mx , my)(在图像坐标系下)。 然后根据透视缩小效应, 对其进行反运算, 进行X 方向的校正。在X 方向的校正中, 可以选择图像高度(0~ H - 1)任意一条水平线的宽度作为标准宽度。为了计算方便, 选取图像的最上面的边(宽度W)作为标准宽度。在图2 中, 将边ac 校正为垂直于X 轴的a′c′, 可以通过求边ac 与过灭点e(mx ,my )垂直于X 轴的边e f 的夹角α, 根据三角形相似性, 求出边ac 在i 高度的X方向的偏移量Δxi , 那么原图像中的点(j , i)在校正后的图像的坐标为(j +Δxi , i), 其中Y 方向的坐标在X 方向上的校正是保持不变。

    X方向校正后是保证acbdX轴垂直

    在X 方向上的校正公式如下:   

       

     Y 方向校正

    根据小孔成像原理, 可得:


    由上式可知在Y 和X 方向上的缩放比例是相同的, 因此可以根据在X 方向变换时得到的比例关系对Y 方向进行同样比例的变换。知道了X 方向的校正比例关系, 可以建立Y 方向的校正公式:


    Y方向校正后是实现在Y方向上,各个实际距离之间实现等分,重构原图像。

    进行X 和Y 方向两次变换后, 计算出二维图像上对应点位置坐标之间的变换关系, 就可以重构出校正后的图像, 各点的灰度值采用双线性插值法计算出。


    展开全文
  • LZ最近在看EM算法在直线分类与灭点检测的应用;翻阅了不少文献,主要参考MIT的Automatic Recovery of Relative Camera Rotation for Urban Scenes,链接如下http://biorobotics.ri.cmu.edu/papers/sbp_pape

    EM算法在机器学习领域有着重要的应用,其根本上要解决的问题即为是先有鸡还是先有蛋的问题;LZ最近在看EM算法在直线分类与灭点检测中的应用;翻阅了不少文献,主要参考MIT的Automatic Recovery of Relative Camera Rotation for Urban Scenes,链接如下http://biorobotics.ri.cmu.edu/papers/sbp_papers/a/cvpr2000_arrcrus.pdf,翻阅了几篇关于EM在直线分类与灭点检测中的应用,也就数此篇讲述较为详细。以下为小白对于此篇文章中介绍到到的算法进行分析与理解。 顾名思义,算法分为3部分,第一步为E步骤,按照字面上理解E步骤应该是期望(Expection)的意思,然而在直线分类灭点检测中并不能够直接的看到E步骤中有期望的意思,若是要追溯到期望,参考以下两篇文章http://blog.csdn.net/zouxy09/article/details/8537620 http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006936.html 第二步即为M步骤,即为最大(Maximition),同样的可以在以上两篇文章中找到答案;初始化也十分的重要;以下给出具体的步骤。  

    1.E step E步骤假设已经灭点的向量(考虑到外点的存在,所以此处假设为多个灭点,一般应该为4个灭点)以及与之相联系的概率,另外还有

    高斯函数的方差。有了这些参量之后,对于所有的直线以及所有的灭点我们都可以进行下面的计算:,其中通过寻找下列矩阵的最大的特征值来得到,其中为边缘的协方差,表示协方差阵在上的投影。至此,得到了,此结果将在下述表达中用到。根据计算得到的,我们进行下列计算,这个表达式在数学上表示在发生的条件下,发生的概率,根据原文的叙述,这一步骤为对于直线进行classification的关键步骤,因为原文对于这一表达式给出的解释是每一个属于的概率,看起来事件的先后顺序有颠倒,这一点有待理解;那么分类的关键应该就是对于每一条直线,根据它的选择最大的那一个就可以对于这条直线属于哪一个灭点找到明确的答案。以上表示分类的步骤。
    2.M step
    对于直线分类完了之后,我们再次计算灭点的坐标,还记得在E step中我们已经假设了灭点的坐标,此步骤主要是对于灭点的坐标进行调整;要知道我们最终达到的目的是完成对于直线的分类,而这些直线已经全部检测到,并且位置不能够改变,而灭点的位置是不确定的,对于直线的属性的不确定性就是分类问题,对于灭点的不确定性就是位置问题。如果E步骤完成了对于直线的分类的话,那么M步骤可想而知将根据分类的直线对于灭点进行检测(此处分类的直线应该是所有的直线,只不过某条直线距离某个灭点比较大的话,该直线权重比较大,这一点在下面将会看到)。
    调整,以及重新求取灭点的坐标值,即通过对于的SVD分解,求取最小奇异值对应的特征向量。为包含权重为对角元素的对角矩阵,的行向量为直线的向量。注意到我们M步骤修改的参量即为E步骤需要的值,也即初始化的值,上述的应该求取至少4次,因为需要知道4个灭点,而要知道对于同一条直线,不同的灭点的权重是不一样的,所以应该至少得到4个不同的值。

    初始化
    初始化用到了一些霍夫变换之类的东西,中间看到这样一句话,讲的是直方图中的极值点对应EM算法中的灭点,大概是对于直线的方向进行统计,然后对于灭点初始化。同样可以参考另外一篇文章,但是没有上述推荐的两篇文章讲的详细:http://xueshu.baidu.com/s?wd=paperuri%3A%289a32a6802b4514e9b7a9344e8726ce7f%29&filter=sc_long_sign&tn=SE_xueshusource_2kduw22v&sc_vurl=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Bjsessionid%3DCB7E0066B92E5409AC08C8B64F0C5610%3Fdoi%3D10.1.1.91.5186%26rep%3Drep1%26type%3Dpdf&ie=utf-8
    展开全文
  • 《数字图像处理》复习提纲

    千次阅读 2019-06-11 09:44:34
    本文在撰写过程参考了由何东健教授主编、西安电子科技大学出版社出版的《数字图像处理》(第三版),一切著作权归原书作者和出版社所有。特别感谢长安大学软件系老师的认真负责的教导。 第1章 概论 1.1 数字...

    本文在撰写过程中参考了由何东健教授主编、西安电子科技大学出版社出版的《数字图像处理》(第三版),一切著作权归原书作者和出版社所有。特别感谢长安大学软件系老师的认真负责的教导。

    第1章 概论

    1.1 数字图像处理及其特点

    1、数字图像与图像处理
    区分模拟图像与数字图像。
    数字图像处理:利用计算机对图像进行去噪、增强、复原、分割、特征提取、识别等的理论、方法和技术。
    2、数字图像处理的特点:
    处理精度高、易于控制处理效果、处理的多样性、图像数据量大、处理费时、综合性强

    1.2 图像处理的目的及主要内容

    1、数字图像处理的目的
    提高图像的视感质量、特征信息的提取、图像数据变换、编码和压缩
    2、数字图像处理的主要内容
    图像获取、表示和表现,复原,增强,分割,分析,重建、压缩编码

    1.3 数字图像处理的应用(略)

    第2章 数字图像处理基础

    2.1 图像数字化技术

    数字图像处理的先决条件:连续图像离散化。
    图像的数字化包括采样和量化两个过程。
    连续图像数字化的结果是图像矩阵,每一个元素称为像素、像元或图像元素。
    采样方法:正方形采样、三角形采样、正六角形采样
    1、采样
    采样:图像在空间上的离散化,即用采样点的灰度值代替图像。
    采样方法:先垂直采样,在水平采样。对于视频,先对时间采样,再沿垂直方向采样,最后沿水平方向采样。
    一维采样定理:若一维信号的g(t)的最大频率为ω,则采样周期小于等于1/(2ω),则能够根据采样频结果完全恢复图像。
    2、量化
    量化:把采样得到的各像素点的灰度值从模拟量到离散量的转换称为图像灰度的量化,转换前的灰度值称为连续灰度值,转换后的灰度值称为量化灰度值,量化灰度值与连续灰度值的差的绝对值称为量化误差。
    量化方法:等间隔量化(均匀量化、线性量化)、非等间隔量化。
    非等间隔量化是根据图像灰度值分布的概率密度函数,按总量化误差最小的原则来进行量化的。具体做法是“高概率细分,低概率粗分”。
    3、采样与量化参数的选择
    图像存储大小=采样数×量化灰度值位数(bit)
    低采样数导致马赛克,低量化级数导致假轮廓。
    采样原则:
    缓变——细量化、粗采样
    细节丰富——粗量化、细采样
    4、图像数字化设备
    组成:采样孔、图像扫描机构、光传感器、量化器、输出储存装置
    性能指标:像素大小、量化位数(颜色元数)、图像尺寸、线性度、噪声

    2.2 色度学基础与颜色模型

    1、色度学基础
    视杆细胞辨亮度,视锥细胞辨颜色,RGB光的三原色
    颜色属性:色调、饱和度、亮度
    2、颜色模型
    计算颜色模型:RGB、CIE XYZ、Lab
    视觉颜色模型:HSI、HSV、HSL
    工业颜色模型:CMYK、YUV、YCbCr
    (1)RGB模型
    在这里插入图片描述
    (2)CIE XYZ模型
    F=x•X+y•Y+z•Z, x=X/(X+Y+Z), y=Y/(X+Y+Z), z=Z/(X+Y+Z)
    (3)Lab颜色模型
    具有设备无关性,L表示亮度分量,a、b为色度分量,其中a正向绝对值越大表示越红,负向绝对值越大表示越绿;b正向绝对值越大表示越黄,负向绝对值越大表示越蓝。
    (4)HSI颜色模型
    色调H:反应颜色的种类(波长)
    饱和度S:表示颜色的深浅
    强度I:亮度/灰度
    (5)CMY与CMYK颜色模型
    (C,M,Y)=(1,1,1)-(R,G,B)
    在这里插入图片描述
    (6)YUV电视信号彩色坐标系统
    Y表示亮度信号,U、V表示色差
    (7)YCbCr模型
    由亮度Y,色差Cb、Cr组成,但充分考虑RGB分量在视觉感受中的不同重要性。
    3、颜色变换
    颜色变换模型:g(x, y) = T[ f(x, y) ]
    颜色变换关系:si = Ti [r1, r2, r3, … ,rn], i = 1, 2, … , n
    彩色切片:识别目标颜色分离出来

    2.3 数字图像类型

    矢量图:数学公式描绘图像,存储量小,图像清晰度与分辨率无关,缺点是单调且不真实
    位图:像素点阵表示图像,每个像素点具有颜色和位置属性,分为线画稿、灰度图像、索引颜色图像、真彩色图像
    1、位图
    线画稿:二值图像
    灰度图像:介于黑色与白色之间的多级灰度
    索引颜色:选择一些颜色,然后编号,用编号作为颜色的索引
    真彩色图像:RGB颜色
    2、位图有关术语
    像素:显示器显示图像的基本单位
    样点:将原图像网格化,用样点代替网格中所有点
    分辨率:单位长度像素数,按照像素的来源分为图像分辨率屏幕分辨率、打印机分辨率、扫描仪分辨率

    2.4 图像文件格式

    BMP图像文件格式:
    (1)四部分组成:位图文件头、位图信息头、调色板、图像数据
    (2)字节对齐,4byte整数倍
    (3)上下倒置存放
    其他文件格式略

    2.5 OpenCV编程简介

    OpenCV = Open Source Computer Vision Library
    1、OpenCV简介 不考
    2、OpenCV的安装与配置 不考
    3、OpenCV的数据结构 不太可能考
    二维点、三维点、Size_、Rect_、RotatedRect、Matx、Vec、Scalar_、Range、Mat
    4、读入、显示和存储图像

    #include <iostream>
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    using namespace std;
    using namespace cv;
    int main(){
    	Mat image, result;
    	cout << "size: " << image.size().height() << " , " << image.size().width << endl;
    	image = imread("tiger.jpg");
    	if(!image.data){
    		cout << "read image file failed!" << endl;
    	}
    	namedWindow("Original Image");
    	imshow("Original Image", image);
    	flip(image, result,1);
    	namedWindow("Output Image");
    	imshow("Output Image", result);
    	imwrite("output.bmp", result);
    	waitKey(0);
    	return 0
    }
    

    5、操作图像像素
    (1)at方法

    void colorReduce(Mat& inputImage, Mat& outputImage, int div){
    	outputImage = inputImage.clone();
    	int rows = outputImage.rows;
    	int cols = outputImage.cols;
    	for(int i=0;i<rows;i++){
    		for(int j=0;j<cols;j++){
    			outputImage.at<Vec3b>(i,j)[0] = outputImage.at<Vec3b>(i,j)[0]/div*div+div/2;
    			outputImage.at<Vec3b>(i,j)[1] = outputImage.at<Vec3b>(i,j)[1]/div*div+div/2;
    			outputImage.at<Vec3b>(i,j)[2] = outputImage.at<Vec3b>(i,j)[2]/div*div+div/2;
    		}
    	}
    }
    

    (2)使用迭代器

    void colorReduce(Mat& inputImage, Mat& outputImage, int div){
    	outputImage = inputImage.clone();
    	Mat_<Vec3b>::iterator it = inputImage.begin<Vec3b>();
    	Mat_<Vec3b>::iterator it = inputImage.end<Vec3b>();
    	Mat_<Vec3b> cimage = outputImage;
    	Mat_<Vec3b>::iterator itout = cimage.begin();
    	Mat_<Vec3b>::iterator itoutend = cimage.end();
    	for(; it != itend; it++,itout++){
    		(*itout)[0]=(*it)[0]/div*div+div/2;
    		(*itout)[1]=(*it)[1]/div*div+div/2;
    		(*itout)[2]=(*it)[2]/div*div+div/2;
    	}
    }
    

    (3)使用指针

    void colorReduce(Mat& inputImage, Mat& outputImage, int div){
    	outputImage = inputImage.clone();
    	int rows = outputImage.rows;
    	int cols = outputImage.cols;
    	if(outputImage.isContinuous()){
    		cols = cols * rows;
    		rows = 1;
    	}
    	for(int i=0;i<rows;i++){
    		uchar * dataout = outputImage.ptr<uchar>(i);
    		for(int j=0;j<cols;j++){
    			dataout[j] = dataout[j]/div*div+div/2;
    		}
    	}
    }
    

    注意:OpenCV中的彩色图像不是以RGB顺序存放的,而是以BGR顺序存放的。
    4、整行整列像素值的赋值

    img.row(i).setTo(Scalar(255));
    img.col(i).setTo(Scalar(255));
    

    6、图形交互和媒体接口HighGui 不太可能考

    第3章 图像增强

    图像增强的目的:改善图像的视觉效果,或使图像更适合于人或机器的分析处理。减少图像噪声,提高目标与背景的对比度,强调或抑制图像中的某些细节。
    图像增强的方法:空域法、频域法,空域法又可以分为点处理和区处理,频域增强可以分为低通滤波、高通滤波、带通滤波、带阻滤波和同态滤波。

    3.1 灰度变换

    灰度变化模型:g(x, y) = T[ f(x, y) ]
    区处理:灰度变换操作在像素的邻域内进行,区处理一般基于模板卷积实现,因此又称为模板操作或空域滤波。
    常见的灰度变换方法:直接灰度变换法、直方图修正法。直接灰度变换法包括线性、分段线性以及非线性变换;直方图修正法可以分为直方图均衡化和直方图规定化。
    1、灰度线性变换
    在这里插入图片描述
    2、分段线性变换
    在这里插入图片描述
    3、非线性变换
    在这里插入图片描述
    在这里插入图片描述

    3.2 直方图修正

    1、直方图的基本概念
    灰度直方图是图像量化灰度值的频数分布直方图或频率分布直方图。
    2、直方图的性质
    (1)丢失位置信息,保留统计信息
    (2)图像与灰度直方图是一对多的关系
    (3)灰度直方图具有可加性
    3、直方图的计算
    (1)初始化:数组零值初始化
    (2)统计:将量化灰度值映射为数组下标,遍历图像将对应数组元素的值++
    (3)归一化:数组所有元素除以像素总数
    也可以像素值沿水平轴划分为若干子区间称为箱格,从而简化计算。
    4、直方图均衡化
    (1)基本思想:把原始图像的直方图变换为均匀分布的形式,从而增加图像灰度的动态范围,以达到增强图像对比度的效果。经过均衡化处理的图像,其灰度级出现的概率相同,此时图像的熵最大,图像包含的信息量最大。
    (2)推导
    s=T(r)s=T(r)
    s和r分别为灰度变换前后的灰度级,T(r)T(r)单调递增且有界[0,1]
    η=T(ξ)η=T(ξ),则有
    Fη(s)=P(η&lt;s)=P(ξ&lt;r)=rPr(x)dxF_{η}(s) = P(η&lt;s) = P(ξ&lt;r) = \int_{-\infty}^{r}P_{r}(x)dx
    对两边同时求导得
    ps(s)=[pr(r)drds]r=T1(s)p_{s}(s)=[p_{r}(r)•\frac{\mathrm{d} r}{\mathrm{d} s}]_{r=T^{-1}(s)}
    若要使变换后的图像灰度s为均匀分布,即有
    ps(s)=1p_s(s)=1
    代入上式有
    ds=pr(r)dr\mathrm{d} s=p_r(r)\mathrm{d}r
    两边同时积分有
    T(r)=s=0rpr(ω)dωT(r)=s=\int_0^rp_r(ω)\mathrm{d}ω
    其中0rpr(ω)dω\int_0^rp_r(ω)\mathrm{d}ω是r的累计分布函数。
    容易证明,以CDF为灰度变换函数,可得到灰度分布均匀的图像。
    (3)数字图像的直方图均衡化

    k rk nk pr=T(rk) sk=int[(L-1)sk+0.5] s rk->sk ps(sk)
    0 0 790 0.19 0.19 0.19→1 0→1 -
    1 1 1023 0.25 0.44 0.144→3 1→3 0.19
    2 2 850 0.21 0.65 0.65→5 2→5 -
    3 3 656 0.16 0.81 0.81→6 3→6 0.25
    4 4 329 0.08 0.89 0.89→6 4→6 -
    5 5 245 0.06 0.95 0.95→7 5→7 0.21
    6 6 122 0.03 0.98 0.98→7 6→7 0.24
    7 7 81 0.02 1 1→7 7→7 0.11

    简并:频数较低的灰度级被归并为一个新的灰度级上,使得变换过后的灰度级的数量减少了,这种现象称为简并。简并现象增大了灰度级的间隔,增加了图像对比度,可以看清更多的细节。
    理论上,直方图均衡化的结果应该是平坦的,但由于不能将同一灰度级的像素映射到不同的灰度级,因而实际结果只是近似均衡。
    5、直方图规定化
    直方图规定化:实际应用中希望将直方图变换为某个特定的形状,从而有选择地增强某个灰度范围内的对比度,这种方法就称为直方图规定化。
    直方图规定化的步骤:
    第一步,对原始直方图进行均衡化,得到映射关系1;
    第二步,对规定直方图进行均衡化,得到映射关系2;
    第三步,按照单映射规则或组映射规则,根据映射关系1和映射关系2得到最终的映射关系。

    rk,zl pr(rk) pz(zl) sk=T(rk) vl=G(zl) 单映射rk→zl 单映射ps(sk) 组映射rk→zl 组映射ps(sk)
    0 0.19 - 0.19 - r0→r3 0 r0→r3 0
    1 0.25 - 0.44 - r1→r3 0 r1→r5 0
    2 0.21 - 0.65 - r2→r5 0 r2→r5 0
    3 0.16 0.2 0.81 0.2 r3→r5 0.44 r3→r7 0.19
    4 0.08 - 0.89 - r4→r7 0 r4→r7 0
    5 0.06 0.5 0.95 0.7 r5→r7 0.37 r5→r7 0.46
    6 0.03 - 0.98 - r6→r7 0 r6→r7 0
    7 0.02 0.3 1 1 r7→r7 0.19 r7→r7 0.35

    单映射:对于每一个sk找距离它最近的vl
    组映射:对于每一个vl找距离它最近的sk,作为分组依据(分界值归到左侧区间),再进行组映射。

    3.3 图像平滑

    目的:消噪或模糊图像,去除小的细节或弥合目标间的缝隙。
    低频代表信号缓慢变化的部分,高频代表迅速变化的部分;图像边缘、跳跃以及噪声等灰度变化剧烈的部分代表图像的高频分量,灰度变化缓慢的部分代表图像的低频分量。
    1、图像噪声
    (1)噪声分类
    外部噪声和内部噪声
    平稳噪声和非平稳噪声
    高斯噪声和椒盐噪声
    白噪声和粉红噪声(1/f噪声)
    加性噪声和乘性噪声
    (2)特点
    随机性、图像相关性、叠加性
    2、模板卷积
    模板操作的种类:卷积、相关
    功能:图像平滑、锐化、边缘检测
    线性滤波,其输出像素是输入邻域像素的加权核。
    卷积和相关运算的主要区别在于卷积运算需要将模板绕模板中心旋转180°,因其余运算过程一致而统称为模板卷积。模板卷积中的模板称为卷积核,其元素称为卷积系数、模板系数或加权系数,其大小和排列顺序决定了对图像邻域处理的类型。
    模板卷积的运算过程:移动模板、对应相乘再相加、赋值
    3、邻域平均
    Box模板:
    19[111111111] \frac{1}{9}\begin{bmatrix} 1 &amp; 1 &amp; 1 \\ 1 &amp; 1* &amp; 1 \\ 1 &amp; 1 &amp; 1 \end{bmatrix}
    高斯模板:
    116[121242121] \frac{1}{16}\begin{bmatrix} 1 &amp; 2 &amp; 1 \\ 2 &amp; 4* &amp; 2 \\ 1 &amp; 2 &amp; 1 \end{bmatrix}
    领域平均法的主要优点是算法简单,缺点是降噪时会模糊图像,尤其是在边缘和细节处,尺寸越大模糊程度越大。适合处理高斯噪声,不适合处理椒盐噪声。
    4、中值滤波
    非线性滤波,滤除噪声的同时很好地保持图像边缘。
    基本原理:窗口内元素灰度值求中位数并赋给中心元素
    统计排序滤波器:模板内元素排序,选取某个值作为中心元素的值。中值滤波是统计排序滤波器的一种。最值滤波器用于检测亮点或暗点。
    中值滤波的性质:
    (1)不影响阶跃信号、斜坡信号、连续个数少于窗口长度一半的脉冲受到抑制,三角函数顶部变平。
    (2)中值滤波的输出与输入噪声的密度分布有关
    (3)中值滤波频谱特性起伏不大,可以认为中值滤波之后,信号频谱基本不变
    中值滤波窗口形状和尺寸决定了滤波效果,就一般经验而言,对于有缓变的较长轮廓线物体的图像,采用方形或圆形窗口为宜;对于包含有尖顶角物体的图像,用十字形窗口。窗口大小不宜超过图像中最小有效物体的尺寸。如果图像中包含的点、线、尖角较多,则不宜采用中值滤波。
    复合型中值滤波器:中值滤波的线性组合、高阶中值滤波组合、加权中值滤波、迭代中值滤波
    5、图像平均
    基本原理:同一景物的多幅图像取平均值来消噪。
    缺点:难以操作

    3.4 图像锐化

    目的:使模糊的图像变清晰,增强图像的边缘等细节,但同时也会增强噪声,一般先做消噪处理。
    图像锐化的方法:空域法、频域法
    1、微分法
    微分运算通常通过一阶向前差分运算或二阶中心差分来实现。
    (1)梯度算子
    梯度算子的定义
    f(x,y)=[fxfy]T \mathrm{▽}\mathbf{f}(x,y)=\begin{bmatrix}\frac{\partial f}{\partial x} &amp; \frac{\partial f}{\partial y}\end{bmatrix}^T
    梯度幅度
    f(x,y)=f(x,y)=(Gx2+Gy2)12 \mathrm{▽} f(x,y)=|\mathrm{▽}\mathbf{f}(x,y)|=(G_x^2+G_y^2)^{\frac 1 2}
    梯度方向角
    φ(x,y)=arctan(GyGx) φ(x,y)=arctan(\frac {G_y} {G_x})
    水平梯度差分法
    f(x,y)f(x+1,y)f(x,y)+f(x,y+1)f(x,y) \mathrm{▽} f(x,y) \approx |f(x+1,y)-f(x,y)|+|f(x,y+1)-f(x,y)|
    Robert交叉算子
    f(x,y)f(x+1,y+1)f(x,y)+f(x,y+1)f(x+1,y) \mathrm{▽} f(x,y) \approx |f(x+1,y+1)-f(x,y)|+|f(x,y+1)-f(x+1,y)|
    中心差分算子
    {Gx=f(x+1,y)f(x1,y)2Gy=f(x,y+1)f(x,y1)2 \left \{\begin{matrix} G_x=\frac{f(x+1,y)-f(x-1,y)}{2} \\ \\ G_y=\frac{f(x,y+1)-f(x,y-1)}{2} \end{matrix}\right.
    常见的梯度算子:

    算子名称 模板H1 模板H2 特点
    Roberts [0110]\begin{bmatrix}0* &amp; -1 \\ 1 &amp; 0\end{bmatrix} [1001]\begin{bmatrix}-1* &amp; 0 \\ 0 &amp; 1\end{bmatrix} 各向同性;对噪声敏感;模板尺寸为偶数,中心位置不明显
    Prewitt [101101101]\begin{bmatrix}-1 &amp; 0 &amp; 1 \\ -1 &amp; 0* &amp; 1 \\ -1 &amp; 0 &amp; 1 \end{bmatrix} [111000111]\begin{bmatrix}-1 &amp; -1 &amp; -1 \\ 0 &amp; 0* &amp; 0 \\ 1 &amp; 1 &amp; 1\end{bmatrix} 引入了平均因素,对噪声有抑制作用;操作简便
    Sobel [101202101]\begin{bmatrix}-1 &amp; 0 &amp; 1 \\ -2 &amp; 0* &amp; 2 \\ -1 &amp; 0 &amp; 1 \end{bmatrix} [121000121]\begin{bmatrix}-1 &amp; -2 &amp; -1 \\ 0 &amp; 0* &amp; 0 \\ 1 &amp; 2 &amp; 1\end{bmatrix} 引入了平均因素,增强了最近像素的影响,噪声抑制效果比Prewitt要好
    Krisch [335305335]\begin{bmatrix}-3 &amp; -3 &amp; 5 \\ -3 &amp; 0* &amp; 5 \\ -3 &amp; -3 &amp; 5 \end{bmatrix} [333303555]\begin{bmatrix}-3 &amp; -3 &amp; -3 \\ -3 &amp; 0* &amp; -3 \\ 5 &amp; 5 &amp; 5\end{bmatrix} 噪声抑制效果要好;需求出8个方向的响应(这里只给出两个方向的模板)
    Isotropic Sobel [101202101]\begin{bmatrix}-1 &amp; 0 &amp; 1 \\ -\sqrt 2 &amp; 0* &amp; \sqrt 2 \\ -1 &amp; 0 &amp; 1 \end{bmatrix} [121000121]\begin{bmatrix}-1 &amp; -\sqrt 2 &amp; -1 \\ 0 &amp; 0* &amp; 0 \\ 1 &amp; \sqrt 2 &amp; 1\end{bmatrix} 权值反比于邻点与中心点的距离,检沿不同方向边缘时梯度幅度一致,即具有各向同性

    (2)拉普拉斯算子
    拉普拉斯算子:
    Δf=2f=2f2x+2f2y \Delta f=\nabla ^2f=\frac{\partial ^2f}{\partial ^2x}+\frac{\partial ^2f}{\partial ^2y}
    差分表示:
    2ff(x+1,y)+f(x1,y)+f(x,y+1)+f(x,y1)4f(x,y) \nabla ^2f \approx f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y)
    常用拉普拉斯模板:
    [010141010][111181111][121242121] \begin{bmatrix} 0 &amp; -1 &amp; 0 \\ -1 &amp; 4* &amp; -1 \\ 0 &amp; -1 &amp; 0 \end{bmatrix} \begin{bmatrix} -1 &amp; -1 &amp; -1 \\ -1 &amp; 8* &amp; -1 \\ -1 &amp; -1 &amp; -1 \end{bmatrix} \begin{bmatrix} 1 &amp; -2 &amp; 1 \\ -2 &amp; 4* &amp; -2 \\ 1 &amp; -2 &amp; 1 \end{bmatrix}
    平滑模板和微分模板的对比:
    (1)微分模板的权系数之和为0,使得灰度平坦区的响应为0。平滑模板的权系数都为正,和为1,这使得灰度平坦区的输出与输入相同。
    (2)一阶微分模板在对比度较大的点产生较高的响应,二阶微分模板在对比度大的点产生零交叉。一阶微分一般产生更粗的边缘,二阶微分则产生更细的边缘。相对一阶微分而言,二阶微分对细线、孤立的点等小细节有更强的响应。
    (3)平滑模板的平滑或去噪程度与模板的大小成正比,跳变边缘的模糊程度与模板的大小成正比。
    2、非锐化滤波
    非锐化滤波:从原始图像中减去原始图像的一个非锐化的或者说是平滑的图像,从而达到增强边缘等细节的目的,用公式表示为:
    g(x,y)=f(x,y)fs(x,y) g(x,y)=f(x,y)-f_s(x,y)
    式中f表示输入图像,fs表示由输入图像得到的平滑图像,g为输出图像。
    图像平滑的实质是一种低通滤波,从原始图像中减去平滑图像就相当于除去低频成分保留了高频成分。
    3、高频增强滤波
    高频增强滤波:如果原始图像与高通图像相加,则可以在保持原始图像概貌的同时突出边缘等细节。将原始图像乘以一个比例系数A,高通图像也乘以一个比例系数K,两者相加得到一个增强图像,称该过程为高频增强滤波。
    fhb(x,y)=Af(x,y)+Kg(x,y) f_{hb}(x,y)=Af(x,y)+Kg(x,y)
    fhb(x,y)f_{hb}(x,y)表示输出图像,g(x,y)g(x,y)f(x,y)f(x,y)的一个高通图像,A>=0,0<=K<=1。K在0.2~0.7之间取值时,高频增强滤波的效果最好;A足够大时,图像锐化作用削弱,输出图像接近原始图像整数倍;特别地,当A=1,K=1时为常用的拉普拉斯高频增强模板。
    常见的拉普拉斯高频增强模板:
    [010151010][111191111][121252121] \begin{bmatrix} 0 &amp; -1 &amp; 0 \\ -1 &amp; 5* &amp; -1 \\ 0 &amp; -1 &amp; 0 \end{bmatrix} \begin{bmatrix} -1 &amp; -1 &amp; -1 \\ -1 &amp; 9* &amp; -1 \\ -1 &amp; -1 &amp; -1 \end{bmatrix} \begin{bmatrix} 1 &amp; -2 &amp; 1 \\ -2 &amp; 5* &amp; -2 \\ 1 &amp; -2 &amp; 1 \end{bmatrix}

    3.5 伪彩色处理

    原理:不同灰度级赋予不同彩色。
    1、灰度分层法:类似于等高线、卫星云图、天气预报图等
    2、灰度变换法:红外热成像仪等
    3、频域滤波法:在频率域进行伪彩色处理

    3.6 同态滤波

    同态滤波:在压缩动态范围的同时增强图像对比度,既增强暗区的图像细节又不损失亮区的图像细节。同态滤波用于消除图像中的非均匀光照,对乘性噪声的滤波效果也比较好。
    通常认为,像素的灰度值为光照的入射分量与物体的反射分量的乘积决定。
    f(x,y)=i(x,y)r(x,y) f(x,y)=i(x,y)r(x,y)
    入射分量描述景物的照明,与景物无关,在空间均匀或缓慢变化,频谱特性集中在低频部分。由于景物具有较多细节内容,因而反射分量随空间变化较大,其频谱特性主要集中在高频部分。通过消除场景关照的不均匀性可以增强图像细节。
    对上式两边取对数
    lnf(x,y)=lni(x,y)+lnr(x,y) \mathrm{ln}f(x,y)=\mathrm{ln}i(x,y)+\mathrm{ln}r(x,y)
    两边做傅里叶变换,得
    Ff(u,v)=Fi(u,v)+Fr(u,v) F_f(u,v)=F_i(u,v)+F_r(u,v)
    高斯高通同态滤波器:
    H(u,v)=(γHγL)[1ecD2(u,v)D02]+γL H(u,v)=(\gamma _H-\gamma _L)[1- e^{-c\frac{D^2(u,v)}{D_0^2}}]+\gamma _L
    γH\gamma _HγL\gamma _L用于控制滤波强度,c用于控制滤波器斜面的锐化程度,D2(u,v)D^2(u,v)为频谱上点(u,v)到频谱中心的距离,D02D_0^2为截止半径。
    同态滤波结果:
    g(x,y)=exp{F1[Ff(u,v)H(u,v)]} g(x,y)=exp\{F^{-1}[F_f(u,v)H(u,v)]\}

    第4章 图像的几何变换

    4.1 几何变换基础

    1、概述
    2、齐次坐标
    标准化齐次坐标是几何变换的基础。
    3、二维图像几何变换矩阵
    P=TP0P0=[x1x2...xny1y2...yn11...1]P=[Hx1Hx2...HxnHy1Hy2...HynHH...H]T=[abpcdq001] P=TP_0 \\ P_0=\begin{bmatrix}x_1 &amp; x_2 &amp; ... &amp; x_n \\ y_1 &amp; y_2 &amp; ... &amp; y_n \\ 1 &amp; 1 &amp; ... &amp; 1\end{bmatrix} \\ \\ P_=\begin{bmatrix}Hx_1&#x27; &amp; Hx_2&#x27; &amp; ... &amp; Hx_n&#x27; \\ Hy_1&#x27; &amp; Hy_2&#x27; &amp; ... &amp; Hy_n&#x27; \\ H &amp; H &amp; ... &amp; H\end{bmatrix} \\ T=\begin{bmatrix}a &amp; b &amp; p \\ c &amp; d &amp; q \\ 0 &amp; 0 &amp; 1\end{bmatrix}

    4.2 图像比例缩放

    1、图像比例放缩变换
    全比例放缩:x轴方向和y轴方向缩放比例相同
    几何畸变:x轴方向和y轴方向缩放比例不相同,会改变像素间的相对位置,产生几何畸变
    插值处理:比例缩放可能导致出现空穴,必须进行插值。插值方法有最邻近插值法和插值算法(如双线性内插值法)
    (1)图像的比例缩小
    I(x,y)=F(int(cx),int(cy)),c=1k I(x,y)=F(int(cx),int(cy)), c=\frac 1 k
    (2)图像的非比例缩小
    I(x,y)=F(int(c1x),int(c2y)),c1=1k1,c2=1k2 I(x,y)=F(int(c_1x),int(c_2y)), c_1=\frac 1 {k_1}, c_2=\frac 1 {k_2}
    (3)图像的比例放大
    最邻近插值法:原图像对应元素如果不存在就取邻近的元素。
    线性插值法:
    g(x,y)=(1q)[(1p)f([x],[y]+1)+pf([x]+1,[y])]+q[(1p)f([x],[y]+1)+pf([x]+1,[y]+1)] g(x,y)=(1-q)[(1-p)f([x],[y]+1)+pf([x]+1,[y])]+q[(1-p)f([x],[y]+1)+pf([x]+1,[y]+1)]
    在这里插入图片描述
    2、比例缩放的实现 (略)

    4.3 图像平移

    没啥说的

    4.4 图像镜像

    没啥说的

    4.5 图像旋转

    1、图像的旋转变换
    变换矩阵没啥说的
    插值方法:行插值、列插值、双线性插值
    2、图像旋转的实现(略)

    4.6 图像复合变换

    复合平移、复合比例、复合旋转、图像转置、任意点比例缩放、任意点旋转
    插值方法:
    在这里插入图片描述
    插值算法:双线性插值、最邻近插值

    4.7 透视变换

    1、透视变换
    投影变换:把空间坐标系中的三维物体或对象转变为二维图像表示的过程称为投影变换。根据视点和投影平面之间的距离的不同,投影可分为平行投影(距离∞)和透视投影(有限距离)。
    平行投影:投影线互相平行的投影称为平行投影,分为正投影和斜投影。正投影要求投影线垂直于投影面,分为正交投影和正轴测投影,正交投影要求坐标轴必须正交,正轴测投影要求坐标轴夹角都相等即为120°,根据坐标轴单位长度是否都相等分为正等轴测图、正二轴测图、正三轴测图。斜投影不要求投影线与投影面垂直,根据坐标轴单位长度是否相等分为斜等测投影和斜二测投影。
    透视投影:投影线不相互平行的投影,根据灭点的数量分为一点透视、两点透视和三点透视。
    2、其他变换
    几何畸变:成像与目标之间不相似的情况称为几何畸变。
    (1)非矩形像素坐标的转换
    极坐标、柱坐标、球坐标→笛卡尔坐标系
    (2)图像错切
    平面景物在投影平面上的非垂直投影。
    水平错切、垂直错切
    (3)图像卷绕
    通过指定一系列控制点的位移来定义空间变换的图像变形的处理技术,非控制点的位移则通过控制点进行插值。

    4.8 几何畸变的矫正

    在这里插入图片描述
    几何畸变两个关键步骤:图像空间像素坐标的几何变换——空间变换;变换后的标准图像空间的各像素灰度值的计算——灰度值计算。
    校正函数的建立步骤:
    (1)利用控制点对图像数据建立一个模拟几何畸变的数学模型,以建立畸变图像空间与标准空间的对应关系
    (2)用这种对应关系把畸变空间中的全部元素变换到标准空间中去。
    重采样的方法:
    (1)直接成图法
    畸变图像元素→标准图像空间正确的位置
    (x,y)=f(u,v)(x,y)=\boldsymbol f(u,v)
    (2)间接成图法(重采样成图法)
    标准图像空间某个位置→对应畸变图像位置
    (u,v)=f1(x,y)(u,v)=\boldsymbol f^{-1}(x,y)
    两种方法的区别:校正函数不同,直接成图法通过亮度重配置获得亮度值,间接成图法通过亮度重采样获得亮度值。
    多项式校正法:将几何畸变看成各种类型仿射变换复合作用的结果。
    {u=gu(x,y)=i=0nj=0niaijxiyjv=gv(x,y)=i=0nj=0nibijxiyj \left \{ \begin{matrix} u=g_u(x,y)=\sum_{i=0}^{n}\sum_{j=0}^{n-i}a_{ij}x^iy^j \\ \\ v=g_v(x,y)=\sum_{i=0}^{n}\sum_{j=0}^{n-i}b_{ij}x^iy^j \end{matrix} \right.
    拟合误差平方和:
    {εu=k=1K(uki=0nj=0niaijxkiykj)2εv=k=1K(vki=0nj=0nibijxkiykj)2 \left \{ \begin{matrix} \varepsilon_u=\sum_{k=1}^K(u_k-\sum_{i=0}^{n}\sum_{j=0}^{n-i}a_{ij}x_k^iy_k^j)^2 \\ \\ \varepsilon_v=\sum_{k=1}^K(v_k-\sum_{i=0}^{n}\sum_{j=0}^{n-i}b_{ij}x_k^iy_k^j)^2 \end{matrix} \right.
    使用最小二乘法计算系数时,控制点的数目不能小于n。

    第5章 频域处理

    数字图像处理的两类方法:空域法、频域法
    频域法:把图像信号从空域转换为频域进行图像分析
    频域处理的应用:图像特征的提取、图像压缩编码、减小计算维数

    5.1 频域与频域变换

    频域变换的理论基础:任意波形都可以表示为一系列正弦波的加和
    幅频特性——振幅与频率之间的关系
    相频特性——初相与频率之间的关系
    时域和频域的变换:
    f(x)A(ω),Φ(ω)F(ω)f(x)\begin{matrix}正变换 \\ \Leftrightarrow \\ 逆变换\end{matrix}A(\omega),\Phi(\omega) \rightarrow F(\omega)
    5.2 傅里叶变换
    1、连续函数的傅里叶变换
    关键词:狄利克雷条件、二维傅里叶变换
    2、离散傅里叶变换
    定义:
    F[f(x)]=F(u)=x=0N1f(x)ej2πuxNF1[F(u)]=f(x)=1Nu=0N1F(u)ej2πuxNF[f(x)]=F(u)=x=0N1f(x)[cos(2πNux)jsin(2πNux)]F1[F(u)]=f(x)=1Nu=0N1F(u)[cos(2πNux)+jsin(2πNux)] \mathscr{F}[f(x)]=F(u)=\sum_{x=0}^{N-1}f(x)e^{-j\frac {2\pi ux}{N}} \\ \mathscr{F}^{-1}[F(u)]=f(x)=\frac 1 N \sum_{u=0}^{N-1}F(u)e^{j\frac {2\pi ux}{N}} \\ \mathscr{F}[f(x)]=F(u)=\sum_{x=0}^{N-1}f(x)[cos(\frac {2\pi} Nux)-j\cdot sin(\frac {2\pi} Nux)] \\ \mathscr{F}^{-1}[F(u)]=f(x)=\frac 1 N \sum_{u=0}^{N-1}F(u)[cos(\frac {2\pi} Nux)+j\cdot sin(\frac {2\pi} Nux)] \\
    离散傅里叶变换的结果仍然是一个离散的序列,对每一个u对应的傅里叶变换结是所有输入序列f(x)的加权和,u决定了每个傅里叶变换结果的频率
    如果F(u)可以表示为F(u)=R(u)+jI(u)F(u)=R(u)+jI(u),且R(u)和I(u)是实函数,则称F(u)=R2(u)+I2(u)|F(u)|=\sqrt {R^2(u)+I^2(u)}为f(x)的频谱,φ(u)=arctan(I(u)R(u))\varphi(u)=arctan(\frac {I(u)}{R(u)})为f(x)的相位谱。频谱的平方称为能量谱。
    二维离散傅里叶变换:
    F[f(x,y)]=F(u,v)=x=0M1y=0N1f(x,y)ej2π(uxM+vyN)F1[f(x,y)]=F(u,v)=1MNu=0M1v=0N1F(u,v)ej2π(uxM+vyN) \mathscr{F}[f(x,y)]=F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)e^{-j2\pi (\frac {ux} M+\frac {vy} N)} \\ \mathscr{F}^{-1}[f(x,y)]=F(u,v)=\frac 1 {MN}\sum_{u=0}^{M-1}\sum_{v=0}^{N-1}F(u,v)e^{j2\pi (\frac {ux} M+\frac {vy} N)}
    3、离散傅里叶变换的性质
    在这里插入图片描述
    在这里插入图片描述
    4、离散傅里叶变换的openCV 不考

    5.3 频域变换的一般表达式

    1、可分离变换
    二维傅里叶变换通用表达式:
    F(u,v)=x=0M1y=0N1f(x,y)g(x,y,u,v)f(x,y)=u=0M1v=0N1F(u,v)h(x,y,u,v) F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)\cdot g(x,y,u,v) \\ f(x,y)=\sum_{u=0}^{M-1}\sum_{v=0}^{N-1}F(u,v)\cdot h(x,y,u,v)
    其中g和h分别被称为正向变换核与负向变换核。
    可分离的:
    如果
    g(x,y,u,v)=g1(x,u)g2(y,v)h(x,y,u,v)=h1(x,u)h2(y,v) g(x,y,u,v)=g_1(x,u)\cdot g_2(y,v) \\ h(x,y,u,v)=h_1(x,u)\cdot h_2(y,v)
    则称正反变换核是可分离的。进一步地,如果g1和g2,h1和h2在函数形式上一致,则称该变换核是对称的。
    2、图像变换的矩阵表示
    F=PfQf=P1FQ1P(u,x)=g1(x,u)=ej2πuxMQ(y,v)=g2(y,v)=ej2πvyN \boldsymbol {F=PfQ} \\ \boldsymbol {f=P^{-1}FQ^{-1}} \\ P(u,x)=g_1(x,u)=e^{-j\frac {2\pi ux} M} \\ Q(y,v)=g_2(y,v)=e^{-j\frac {2\pi vy} N}

    5.4 离散余弦变换(DCT)

    1、一维离散余弦变换
    DCT变换核定义:
    g(x,u)=C(u)2Ncos(2x+1)uπ2NC(u)={12,u=01,else \begin{matrix} g(x,u)=C(u)\sqrt {\frac 2 N cos \frac {(2x+1)u\pi} {2N}} \\ \\ C(u)=\left \{ \begin{matrix} \frac 1 {\sqrt 2}, u=0 \\ \\ 1,else\end{matrix}\right. \end{matrix}
    一维DCT定义:
    F(u)=x=0N1f(x)g(x,u)F=Gf(G(u,x)=g(x,u) F(u)=\sum_{x=0}^{N-1}f(x)g(x,u) \\ \boldsymbol {F=Gf}(矩阵形式,G(u,x)=g(x,u))
    在这里插入图片描述
    DCT逆变换IDCT:
    h(x,u)=g(x,u)=C(u)2Ncos(2x+1)uπ2Nf(x)=u=0N1F(u)h(x,u) h(x,u)=g(x,u)=C(u)\sqrt {\frac 2 N cos \frac {(2x+1)u\pi} {2N}} \\ f(x)=\sum_{u=0}^{N-1}F(u)h(x,u)
    2、二维离散余弦变换
    2D-DCT:
    g1(x,u)=2MC(u)cos(2x+1)uπ2Mg2(y,v)=2NC(v)cos(2x+1)vπ2Ng(x,y,u,v)=g1(x,u)g2(y,v)F(u,v)=x=0M1y=0N1f(x,y)g(x,y,u,v) g_1(x,u)= \sqrt {\frac 2 M} C(u) cos \frac {(2x+1)u\pi} {2M} \\ g_2(y,v)= \sqrt {\frac 2 N} C(v) cos \frac {(2x+1)v\pi} {2N} \\ g(x,y,u,v)=g_1(x,u)g_2(y,v) \\ F(u,v)=\sum_{x=0}^{M-1}\sum_{y=0}^{N-1}f(x,y)g(x,y,u,v)
    2D-IDCT:
    h1(x,u)=g1(x,u)h2(y,v)=g2(y,v)h(x,y,u,v)=h1(x,u)h2(y,v)f(x,y)u=0M1v=0N1F(u,v)h(x,y,u,v) h_1(x,u)=g_1(x,u) \\ h_2(y,v)=g_2(y,v) \\ h(x,y,u,v)=h_1(x,u)\cdot h_2(y,v) \\ f(x,y)\sum_{u=0}^{M-1}\sum_{v=0}^{N-1}F(u,v)h(x,y,u,v)

    5.5 频域中图像处理的实现

    1、理解数字图像的频谱图
    数字图像平移后的频谱中,图像的能量将集中到频谱中心(低频成分),细节信息分散在图像频谱的边缘。频谱中的低频成分代表了图像的概貌,高频成分代表了图像中的细节。
    2、频域图像处理步骤
    在这里插入图片描述
    3、频域滤波
    低通滤波器、高通滤波器、带通滤波器、带阻滤波器
    高通巴特沃斯滤波器:H(u,v)=11+[D0D(u,v)]2nH(u,v)=\frac 1 {1+[\frac {D_0} {D(u,v)}]^{2n}}
    低通巴特沃斯滤波器:H(u,v)=11+[D(u,v)D0]2nH(u,v)=\frac 1 {1+[\frac {D(u,v)} {D_0}]^{2n}}

    5.6 小波变换简介(暂略)

    第6章 数学形态学处理

    数学形态学四种基本运算:腐蚀、膨胀、开运算、闭运算

    6.1 引言

    1、数学形态学
    数学形态学的基本思想:用具有一定形态的结构元素去量度和提取图像中的对应形状,已以达到图像分析和识别的目的。
    2、基本符号和术语
    元素和集合、交并补差、平移反射、目标图像与结构元素
    击中与击不中:交集为空击不中,交集不为空击中

    6.2 二值形态学

    1、腐蚀
    XS={xXS+xX}X\ominus S=\{x\in X |S+x\subseteq X\}
    理解:把结构体元素放在目标图像中移动,则结构体元素的原点的集合构成腐蚀的结果。
    2、膨胀
    XS={X+ssS}={S+xxX}={x(Sv+x)X}X\oplus S=\bigcup\{X+s|s\in S\}=\bigcup\{S+x|x\in X\}=\{x|(S^v+x) \cap X\neq \varnothing\}
    理解:第二种定义比较好理解,即吧结构体元素原点放在目标图像中移动,所有结构体元素的并。
    运算律:
    X(YZ)=(XY)(XZ)X(YZ)=(XY)(XZ)(XY)Z(XZ)(YZ)(XY)Z=(XZ)(YZ)(XY)Z=(XZ)(YZ)(XY)Z(XZ)(YZ) X\ominus(Y\cap Z)=(X\ominus Y)\cap(X\ominus Z) \\ X\oplus(Y\cap Z)=(X\oplus Y)\cap(X\oplus Z) \\ (X\cap Y)\ominus Z\supset(X\ominus Z)\cap (Y\ominus Z) \\ (X\cap Y)\oplus Z=(X\oplus Z)\cap (Y\oplus Z) \\ (X\cup Y)\ominus Z=(X\ominus Z)\cup (Y\ominus Z) \\ (X\cup Y)\oplus Z\subseteq(X\oplus Z)\cup (Y\oplus Z)
    3、开闭运算
    开运算:XS=(XS)SX○S=(X\ominus S)\oplus S
    闭运算:XS=(XS)SX\cdot S=(X\oplus S)\ominus S
    开闭运算的代数性质:
    (1)对偶性:(XCS)C=XS;(XCS)=XS(X^C○S)^C=X\cdot S; (X^C\cdot S)=X○S
    (2)扩展性:XSXXSX○S\subseteq X \subseteq X\cdot S
    开运算恒使图像缩小,闭运算恒使图像扩展。
    (3)单调性:XYXSYS,XSYSX\subseteq Y \Rightarrow X\cdot S\subseteq Y\cdot S, X○ S\subseteq Y○ S
    YZZY=ZXYXZY\subseteq Z\wedge Z\cdot Y=Z \Rightarrow X\cdot Y\subseteq X \cdot Z
    (4)平移不变性:(X+h)S=(XS)+h(X+h)\cdot S=(X\cdot S)+h
    (X+h)S=(XS)+h(X+h)○ S=(X○ S)+h
    X(S+h)=XSX\cdot (S+h)=X\cdot S
    X(S+h)=XSX○ (S+h)=X○ S
    (5)等幂性:(XS)S=XS,(XS)S=XS(X\cdot S)\cdot S = X\cdot S,(X○ S)○ S = X○ S
    (6)开闭运算与集合的关系:
    (i=0nXi)Si=0n(XiS)(\bigcup_{i=0}^{n}X_i)○S\supseteq \bigcup_{i=0}^{n}(X_i○S)
    (i=0nXi)Si=0n(XiS)(\bigcap_{i=0}^{n}X_i)○S\subseteq \bigcap_{i=0}^{n}(X_i○S)
    (i=0nXi)Si=0n(XiS)(\bigcup_{i=0}^{n}X_i)\cdot S\supseteq \bigcup_{i=0}^{n}(X_i\cdot S)
    (i=0nXi)Si=0n(XiS)(\bigcap_{i=0}^{n}X_i)\cdot S\subseteq \bigcap_{i=0}^{n}(X_i\cdot S)
    4、击中击不中变换
    XS={xS1+xXS2+xXC}=(XS1)(XCS2)X\odot S=\{x|S_1+x\subseteq X \wedge S_2+x\subseteq X^C\}=(X\ominus S_1)\cap(X^C\ominus S_2)

    6.3 灰值形态学

    1、灰值腐蚀
    (fb)(s,t)=min{f(s+x,t+y)b(x,y)s+x,t+yDfx,yDb}(f\ominus b)(s,t)=min\{f(s+x,t+y)-b(x,y)|s+x,t+y\in D_f \wedge x,y \in D_b\}
    腐蚀的计算是在由结构元素确定的领域中选取fbf\ominus b的最小值,所以灰值图像的腐蚀操作会有两类效果:如果结构体元素的值都为正,则输出图像会比原图像暗;如果输入图像中亮细节的尺寸比结构元素小,则其影响会被减弱。
    2、灰值膨胀
    (fb)(s,t)=max{f(sx,ty)+b(x,y)sx,tyDfx,yDb}(f\oplus b)(s,t)=max\{f(s-x,t-y)+b(x,y)|s-x,t-y\in D_f \wedge x,y \in D_b\}
    膨胀的计算是在由结构元素确定的领域中选取fbf\oplus b的最大值,所以对灰值图像的膨胀有两类效果:如果结构体元素的值都为正,则输出图像会比原图像亮;如果输入图像中暗细节的灰度值及形状相对于结构体元素的大小,则其被消减或消除。
    膨胀或腐蚀满足以下对偶关系:
    (fb)C=fCbV(f\oplus b)^C=f^C \ominus b^V
    (fb)C=fCbV(f\ominus b)^C=f^C \oplus b^V
    3、灰值开闭运算
    定义与二值形态学定义类似,亦满足类似的对偶关系。
    灰值开运算削平山峰。灰值闭运算填平深谷。
    实际中常用开运算操作消除与结构元素相比尺寸较小的亮细节,而保持整体灰度值和大的亮区域;实际应用中常使用闭运算操作消除与结构元素相比尺寸较小的暗细节,而保持图像整体灰值和大的暗区域。

    6.4 形态学的应用

    灰值形态学的主要算法有:灰值形态学梯度、形态学平滑、纹理分割、顶帽变换等
    二值形态学的主要算法有:二值形态学滤波、骨架抽取等
    1、形态学滤波
    将开运算与闭运算相结合可以构成形态学噪声滤除器,开运算滤除黑色背景上的白色噪声,闭运算滤除白色前景中的黑色噪声。
    2、骨架提取
    骨架定义方法:火种法、最大圆盘法
    (1)基于腐蚀和开运算的细化
    定义骨架子集Sk(X)S_k(X)为图像X内所有最大圆盘kB(至少与两条边相切的内切圆)的圆心x构成的集合。从骨架的定义可知,骨架是所有骨架子集的并,即
    Sk(X)={Sk(X)k=0,1,...,n} S_k(X)=\bigcup\{S_k(X)|k=0,1,...,n\}
    可以证明骨架子集可以表示为:
    Sk(X)=(XkB)[(XkB)B]XkB=(X(k1)B)B S_k(X)=(X\ominus kB)-[(X\ominus kB)○ B] \\ 递推公式:X\ominus kB=(X\ominus (k-1)B)\ominus B
    所以:
    S(X)={(XkB)[(XkB)B]k=0,1,2,...,n} S(X)=\bigcup\{(X\ominus kB)-[(X\ominus kB)○B]|k=0,1,2,...,n\}
    停止迭代的时机:XkBX\ominus kB\varnothing
    (2)快速形态学细化算法

    在这里插入图片描述
    (1)(2)(4)(6)都不能删除,(2)(4)可以删除
    可以删除的情况:内部点不可删除、孤立点不可删除、直线端点不可删除、去掉后连通分量不增加。

    第7章 图像分割

    图像分割就是把图象分成一系列有意义的、各具特征的目标或区域的技术和过程。这里的特征包括图像的统计特征和视觉特征。统计特征包括图像的直方图、矩和频谱等,图像的视觉特征主要包括区域的亮度、纹理或轮廓等。
    图像分割一般基于像素灰度值的两个性质:不连续性和相似性。区域之间的边界往往具有有灰度不连续性,而区域内部一般具有灰度相似性。
    图像分割算法一般分为两类:利用灰度不连续性——基于边界的分割;利用灰度相似性——基于区域的分割
    常用算法:阈值分割、区域生长、区域分裂与合并、边缘检测与边界连接、区域标记与轮廓跟踪、分水岭分割、Mean Shift和Graph Cuts算法

    7.1 阈值分割

    1、概述
    基本假设:目标与背景相邻像素间灰度值高度相关;目标与边界两侧像素灰度值差别很大;目标与背景的灰度分布都是单峰的。
    阈值分割过程:阶跃函数
    阈值分割的关键——阈值的确定:
    (1)种类:全局阈值、局部阈值、动态阈值(自适应阈值)
    (2)阈值分割的要素:T=T[x,y,f(x,y),p(x,y)]T=T[x,y,f(x,y),p(x,y)], f(x,y)表示灰度值,p(x,y)表示某种局部性质。
    2、全局阈值
    适用条件:“双峰”性质
    确定全局阈值的方法:
    (1)极小点阈值法:取直方图谷底位置作为阈值
    (2)迭代阈值法:初始阈值T1T_1→像素划分为G1G_1G2G_2→计算平均灰度μ1\mu_1μ2\mu_2→计算新的阈值T2=μ1+μ22T_2=\frac {\mu_1+\mu_2} 2→迭代→终止条件T2T1&lt;T0|T_2-T_1| &lt;T_0
    (3)最优阈值法:选择一个阈值使得总的分类误差概率降到最低。
    p(z)p(z)为灰度概率密度函数,p1(z)p_1(z)p2(z)p_2(z)分别为背景和目标灰度条件概率密度函数,P1P_1P2P_2为背景和目标像素出现的概率,那么由全概率公式得:
    p(z)=P1p1(z)+P2p2(z) p(z)=P_1p_1(z)+P_2p_2(z)
    把目标像素错分为背景像素的误差条件概率为:
    E1(T)=Tp1(z)dz E_1(T)=\int_{-\infty}^Tp_1(z)\mathrm{d}z
    把背景像素错分为背景像素的误差条件概率为:
    E2(T)=T+p2(z)dz E_2(T)=\int_T^{+\infty}p_2(z)\mathrm{d}z
    由全概率公式得总误差概率为:
    E(T)=P2E1(T)+P1E2(T) E(T)=P_2E_1(T)+P_1E_2(T)
    一般认为目标与背景的灰度服从高斯分布,利用概率论与数理统计中最大似然估计方法可以得到最优解
    T=μ1+μ22+σ2μ1μ2ln(P2P1) T=\frac {\mu_1+\mu_2} 2+\frac {\sigma^2} {\mu_1-\mu_2}ln(\frac{P_2}{P_1})
    (4)Otsu方法:使阈值分割后各个像素类的类间方差最大。
    步骤:将像素按灰度值进行分级,计算从第0个灰度级到第k个灰度级的概率和均值(数学期望),M个阈值将灰度值分为M+1个像素类,计算每个像素类的概率、平均灰度、方差,所有像素类的概率之和为1,图像总的平均灰度是所有像素类灰度的数学期望,类内方差定义为像素类灰度方差的数学期望,类间方差定义为像素类灰度均值的方差。
    (5)p参数法
    选取一个阈值T使得目标面积与背景面积的比为p:(1-p)
    3、局部阈值
    (1)直方图变换法
    对波谷进行切割或峰谷颠倒、根据像素的梯度值进行加权
    (2)散射图
    二维坐标图,横轴为灰度,纵轴为某种局部性质(如梯度值),亮度表示频数。根据亮色进行聚类。
    4、动态阈值
    网格划分,每个子图像定一个阈值。
    一种动态阈值算法:
    子图像分解→对于具备“双峰”采用最优阈值→插值得到其他阈值→分割

    7.2 基于区域的分割

    1、区域生长
    实质是bfs,需要初始种子,相似性准则
    2、区域分裂与合并
    先进行迭代四分裂,满足一致性条件后停止迭代,然后进行合并

    7.3 边缘检测

    常见的边缘类型:阶跃型、斜坡型、线状型、屋顶型
    1、微分算子
    在这里插入图片描述
    结论:一阶导数的幅度值可以用来检测边缘的存在,通过检测二阶导数的过零点可以确定边缘的中心位置,利用二阶导数在过零点附近的符号可以判断是在边缘的亮区还是暗区,处理之前要先消噪。
    (1)梯度算子:
    Krisch、Prewitt,均可沿8个方向
    (2)高斯-拉普拉斯算子
    结合了高斯平滑滤波器与拉普拉斯锐化滤波器。
    在这里插入图片描述
    在这里插入图片描述
    (3)Canny边缘检测
    Canny算子是一个非常有效的边界检测算子。
    ①首先对灰度图像进行高斯平滑。
    ②接着计算每个像素的梯度幅值和梯度方向。
    ③ 然后细化边缘。如果当前像素的梯度幅值不高于梯度方向上两个邻点的梯度幅值,则抑制该像素响应,这种方法称之为非最大抑制。
    ④ Canny算子使用两个幅值阈值,高阈值用于检测梯度幅值大的强边缘,低阈值用于检测梯度幅值较小的弱边缘。低阈值通常取为高阈值的一半。
    ⑤ 边缘细化后,就开始跟踪具有高幅值的轮廓。
    ⑥ 最后,从满足高阈值的边缘像素开始,顺序跟踪连续的轮廓段,把与强边缘相连的弱边缘连接起来。
    2、边界连接
    幅度阈值、角度阈值
    3、哈夫变换
    前提条件:已知区域形状
    (1)直线检测
    y=ax+b→b=-ax+y→{b=axi+yib=axj+yj\left \{\begin{matrix}b=-ax_i+y_i \\ b=-ax_j+y_j\end{matrix}\right.
    在这里插入图片描述
    如果多个点在同一条直线上,则在参数空间中对应直线必交于同一点。
    步骤:参数a、b进行量化,对于目标空间的每一个点,让a取遍每一个值apa_p,代入b=-ax+y,得到bpb_p,给A(p,q)++,处理完所有像素查找峰值即可知道最可能的a与b。
    斜截式方程有缺陷,一般可以换为法线式方程:ρ=xcosθ+ysinθ\rho=xcos\theta +ysin\theta
    (2)圆的检测:
    {a=xrcosθb=yrsinθ \left \{ \begin{matrix} a=x-rcos\theta \\ b=y-rsin\theta \end{matrix} \right.
    (3)任意曲线的检测:类似做法

    7.4 区域标记与轮廓追踪

    1、区域标记
    递归标记:BFS
    序贯标记:左、左上、上、右上邻点,如果都是背景,当前点新建标记;如果有一个被标记,复制标记;如果有两个不同标记,赋值之一,并在等价表中记录,再次扫描把等价的标记改为最小标记。
    2、轮廓提取
    八面合围置为背景
    3、轮廓追踪
    步骤:扫描图像,选定左上角点,初始dir为左下方向(4方向中为向下),逆时针查找边界点,查找到的新边界点作为当前点,在顺时针转回一个方向,迭代直到回到起始点。

    7.5 分水岭分割

    1、基本分水岭算法
    降雨法:降水,递归寻找低洼点,雨水流向>=2个低洼的是分水岭。
    淹没法:提升水位,如果水流溢出地外就筑坝,最后堤坝就是分水岭。
    2、Vincent-Soille算法
    类似并查集,提升水位,水平面与一些点相交,对于这些点,如果邻接点没有标记,新建标记,如果有标记,复制标记(取最近的积水盆地)
    使用分水岭分割之前先做距离变换,去除粘连。

    7.6 现代分割方法(略)

    7.7 图像分割实例

    大米计数:
    (1)高斯滤波、中值滤波或开闭运算消噪
    (2)消除非均匀光照:背景照度估计、灰值形态学、同态滤波
    (2)区域分割

    第8章 图像特征与理解

    图像特征:人视觉能够识别的自然特征,分为全局特征和局部特征。
    ,全局特征用于描述图像或目标的颜色或形状等整体特征,局部特征指一些能够稳定出现并具有良好可区分性的特征。

    8.1 图像的基本特征

    提取图像几何特征之前,分割和二值化处理。
    1、几何特征
    (1)位置和方向
    位置:质心
    方向:最小二阶矩轴(最小转动惯量)
    (2)周长
    隙码:把像素看成小方块后图形的绝对周长
    链码:边界像素中心点连线的长度
    边界点数之和:边界像素的个数
    (3)面积
    像素计数面积:统计边界内部像素的个数
    由边界行程码计算面积:
    ①已知区域的行程编码,只需把值为1的行程长度相加,即为区域面积。
    ②若给定边界的某种表示,则相应连通区域的面积应为区域外边界包围的面积,减去它的内边界包围的面积(空的面积)
    yk=y0+i=0kΔyiΔyi={1,εi=1,2,30,εi=0,41,εi=5,6,7Δxi={1,εi=0,1,70,εi=2,61,εi=3,4,5A=i=1n(yi1Δxi+a) y_k=y_0+\sum_{i=0}^k\Delta y_i \\ \Delta y_i=\left \{\begin{matrix}-1,\varepsilon _i = 1,2,3 \\ 0,\varepsilon _i = 0,4\\ 1,\varepsilon _i = 5,6,7 \\\end{matrix}\right. \\ \Delta x_i=\left \{\begin{matrix}-1,\varepsilon _i = 0,1,7 \\ 0,\varepsilon _i = 2,6\\ 1,\varepsilon _i = 3,4,5 \\\end{matrix}\right. \\ A=\sum_{i=1}^n(y_{i-1}\Delta x_i+a)
    由边界坐标计算面积:利用格林公式,A=12i=1Nb(xiyi+1xi+1yi]A=\frac 1 2 \sum_{i=1}^{N_b}(x_iy_{i+1}-x_{i+1}y_i]
    (4)长轴和短轴
    最小外接矩形的长与宽
    (5)距离
    欧式距离、市区距离、棋盘距离
    2、形状特征
    (1)矩形度=物体面积/最小外接矩形面积
    长宽比=最小外接矩形的宽与长的比值
    (2)圆形度:
    致密度=周长^2/面积
    边界能量:物体的周长为P,p表示边界点到某一起始点的距离,该点处的曲率半径为r§,则曲率为K§=1/r§,边界能量为E=1P0pK(p)2dpE=\frac 1 P\int_{0}^{p}|K(p)|^2\mathrm{d}p,在面积相同的情况下,圆具有最小的边界能量E0=(2πP)2=(1R)2E_0=(\frac {2\pi} P)^2=(\frac 1 R)^2
    原型性=区域质心到边界点的平均距离/区域质心到边界点的距离均方差,当区域R趋向圆形时,圆形性趋向无穷。
    面积与平均距离平方的比值=面积/内部点到边界点的平均距离
    3、球状性=内切圆半径/外接圆半径
    4、偏心率=区域长轴/区域短轴
    5、形状描述子
    (1)边界链码
    在这里插入图片描述
    在这里插入图片描述
    (2)一阶差分链码
    为了改进边界链码在旋转过程中会改变的情况。
    在这里插入图片描述
    (3)傅里叶描述子
    原理:将二维问题转化为一维问题进行处理,可以将边界曲线转化为一维函数,或者将边界曲线转化为复平面上点的序列。假定有一个复数序列,可以对其采用采用离散傅里叶变换,得到的结果就成为傅里叶变换子。

    8.2 角点特征

    角点:亮度变化最剧烈、图像边缘曲线上曲率最大,具有高信息密度和旋转不变的特性
    角点检测算法的4个准则:检测性、定位性、稳定性、复杂性
    角点检测方法的分类:基于边缘的检测算法、基于灰度变化的检测算法。前者做法是找曲率最大边界点或拐点或进行多边形拟合,但抗噪差且依赖边缘提取结果。后者做法为对局部结果进行分析,进行角点性质检测。
    1、Moravec算法
    灰度变化定义为沿各个方向移动窗口的灰度值与当前窗口灰度值差的平方和。
    E(u,v)=(x,y)W(I(x+u,y+v)I(x,y))2 E(u,v)=\sum_{(x,y)\in W}(I(x+u,y+v)-I(x,y))^2
    在这里插入图片描述
    2、Harris算法
    在Moravec算法基础上给不同方向的灰度变化方差加上权值,该权值为二维高斯窗口函数。
    E(u,v)=(x,y)Ww(x,y)(I(x+u,y+v)I(x,y))2w(x,y)=e(xx0)2+(yy0)22σ2I(x+u,y+v)I(x+u,y+v)=I(x,y)+uIx+vIy:E(u,v)=[u,v]M[u,v]TM=(x,y)Ww(x,y)[Ix2IxIyIxIyIy2]=[abcd] E(u,v)=\sum_{(x,y)\in W}w(x,y)(I(x+u,y+v)-I(x,y))^2 \\ w(x,y)=e^{-\frac {(x-x_0)^2+(y-y_0)^2} {2\sigma^2}} \\ 对I(x+u,y+v)进行泰勒展开:I(x+u,y+v)=I(x,y)+uI_x+vI_y \\ 代入上面的式子得:E(u,v)=[u,v]\boldsymbol M[u,v]^T \\ \boldsymbol M=\sum_{(x,y)\in W}w(x,y)\begin{bmatrix}I_x^2 &amp; I_xI_y \\ I_xI_y &amp; I_y^2 \end{bmatrix}=\begin{bmatrix}a &amp; b \\ c &amp; d \end{bmatrix}
    特征值λ1与λ2决定了矩阵M的性质:
    在这里插入图片描述
    3、SUSAN算法
    角点处的SUSAN面积具有局部最小值
    在这里插入图片描述

    8.3~8.6 (略)

    附加:图像匹配

    方法:投影法与差影法
    投影法:分为水平投影法和垂直投影法。基本原理是统计每行或每列目标像素的个数,得到一个直方图,根据直方图很容易就能找到目标图像的位置。
    差影法:利用同一景物同一时刻或不同时刻的图像,进行加、减、乘、除代数运算,分析得出某一物体的位置和运动情况

    第9章图像编码

    9.1 图像编码概述

    1、图像编码的基本原理和方法
    (1)图像数据冗余:
    空间冗余:内部相邻像素较强的相关性导致的冗余
    时间冗余:相邻两帧图像之间的相关性导致的冗余
    信息熵冗余:编码冗余,用于表示信源符号的平均比特数大于其信息熵时所产生的冗余。信息熵H=i=1Npilbpi=i=1Npilb1pilbNH=-\sum_{i=1}^{N}p_ilbp_i=\sum_{i=1}^{N}p_ilb\frac 1 {p_i}\le lbN
    结构冗余:图像中存在较强的纹理结构和自相似性
    知识冗余:图像中包含与某些先验知识有关的信息
    视觉冗余:人眼不能感知的那部分信息
    (2)图像编码方法
    分类:有损编码和无损编码;熵编码、预测编码、变换编码、量化编码
    熵编码:
    ①哈夫曼编码、香农-范诺编码、算术编码
    ②理论基础:平均码长等于信息熵时,总可设计出一种无损编码
    ③等长编码与变长编码
    ④变长编码定理:若一个离散无记忆信源的符号集具有r个码元,熵为H,则总可以找到一种无失真编码,构成单义可译码,使其平均码长L满足HlbrLHlbr+1\frac H {lbr}\le L \le \frac H {lbr}+1
    预测编码:基于图像数据的空间或时间冗余性,利用相邻已知像素预测当前像素的值,再对预测误差进行量化和编码。
    变换编码:空间域图像正交变换到另一变换域上,降低相关性。
    量化编码:通过将动态范围较大的输入信号映射到有限个离散值上。
    2、图像编码新技术(略)
    3、图像编码评价
    编码效率:平均码字长度L,压缩比CRC_R,编码效率η
    L=i=1NpiLiCR=BLη=HL L=\sum_{i=1}^{N}p_iL_i \\ C_R=\frac B L \\ \eta = \frac H L
    编码质量:均方误差MSE、峰值信噪比PSNR
    算法复杂度和算法的适用范围

    9.2 哈夫曼编码

    不会的挨打

    9.3 香农-范诺编码

    1、基本方法:
    信源符号出现概率降序排序;
    计算符号对应码字长度:logDPiNilogDPi+1-log_DP_i\le N_i \le -log_DP_i+1
    计算累加概率:Ai=k=0i1piA_i=\sum_{k=0}^{i-1}p_i
    将累加概率转换为二进制,取前NiN_i位。
    2、二分法香农-范诺编码方法
    在这里插入图片描述

    9.4 算术编码

    两种模式:基于信源概率统计特性的固定编码模式、针对未知信源概率模型的自适应模式
    在这里插入图片描述

    9.5 行程编码

    aabbbcddddd=2a3b1c5d

    9.6 LZW编码

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 图像处理之霍夫变换(直线检测算法) 霍夫变换是图像变换的经典手段之一,主要用来从图像分离出具有某种相同特征的几何 形状(如,直线,圆等)。霍夫变换寻找直线与圆的方法相比与其它方法可以更好的...

    图像处理之霍夫变换(直线检测算法)

    霍夫变换是图像变换中的经典手段之一,主要用来从图像中分离出具有某种相同特征的几何

    形状(如,直线,圆等)。霍夫变换寻找直线与圆的方法相比与其它方法可以更好的减少噪

    声干扰。经典的霍夫变换常用来检测直线,圆,椭圆等。

     

    霍夫变换算法思想:

    以直线检测为例,每个像素坐标点经过变换都变成都直线特质有贡献的统一度量,一个简单

    的例子如下:一条直线在图像中是一系列离散点的集合,通过一个直线的离散极坐标公式,

    可以表达出直线的离散点几何等式如下:

    X *cos(theta) + y * sin(theta)  = r 其中角度theta指r与X轴之间的夹角,r为到直线几何垂

    直距离。任何在直线上点,x, y都可以表达,其中 r, theta是常量。该公式图形表示如下:

    然而在实现的图像处理领域,图像的像素坐标P(x, y)是已知的,而r, theta则是我们要寻找

    的变量。如果我们能绘制每个(r, theta)值根据像素点坐标P(x, y)值的话,那么就从图像笛卡

    尔坐标系统转换到极坐标霍夫空间系统,这种从点到曲线的变换称为直线的霍夫变换。变换

    通过量化霍夫参数空间为有限个值间隔等分或者累加格子。当霍夫变换算法开始,每个像素

    坐标点P(x, y)被转换到(r, theta)的曲线点上面,累加到对应的格子数据点,当一个波峰出现

    时候,说明有直线存在。同样的原理,我们可以用来检测圆,只是对于圆的参数方程变为如

    下等式:

    (x –a ) ^2 + (y-b) ^ 2 = r^2其中(a, b)为圆的中心点坐标,r圆的半径。这样霍夫的参数空间就

    变成一个三维参数空间。给定圆半径转为二维霍夫参数空间,变换相对简单,也比较常用。

     

    编程思路解析:

    1.      读取一幅带处理二值图像,最好背景为黑色。

    2.      取得源像素数据

    3.      根据直线的霍夫变换公式完成霍夫变换,预览霍夫空间结果

    4.       寻找最大霍夫值,设置阈值,反变换到图像RGB值空间(程序难点之一)

    5.      越界处理,显示霍夫变换处理以后的图像

     

    关键代码解析:

    直线的变换角度为[0 ~ PI]之间,设置等份为500为PI/500,同时根据参数直线参数方程的取值

    范围为[-r, r]有如下霍夫参数定义:

    [java] view plain copy
    1. // prepare for hough transform  
    2. int centerX = width / 2;  
    3. int centerY = height / 2;  
    4. double hough_interval = PI_VALUE/(double)hough_space;  
    5.       
    6. int max = Math.max(width, height);  
    7. int max_length = (int)(Math.sqrt(2.0D) * max);  
    8. hough_1d = new int[2 * hough_space * max_length];  

    实现从像素RGB空间到霍夫空间变换的代码为:

    [java] view plain copy
    1. // start hough transform now....  
    2. int[][] image_2d = convert1Dto2D(inPixels);  
    3. for (int row = 0; row < height; row++) {  
    4.     for (int col = 0; col < width; col++) {  
    5.         int p = image_2d[row][col] & 0xff;  
    6.         if(p == 0continue// which means background color  
    7.           
    8.         // since we does not know the theta angle and r value,   
    9.         // we have to calculate all hough space for each pixel point  
    10.         // then we got the max possible theta and r pair.  
    11.         // r = x * cos(theta) + y * sin(theta)  
    12.         for(int cell=0; cell < hough_space; cell++ ) {  
    13.             max = (int)((col - centerX) * Math.cos(cell * hough_interval) + (row - centerY) * Math.sin(cell * hough_interval));  
    14.             max += max_length; // start from zero, not (-max_length)  
    15.             if (max < 0 || (max >= 2 * max_length)) {// make sure r did not out of scope[0, 2*max_lenght]  
    16.                 continue;  
    17.             }  
    18.             hough_2d[cell][max] +=1;  
    19.         }  
    20.     }  
    21. }  

    寻找最大霍夫值计算霍夫阈值的代码如下:

    [java] view plain copy
    1. // find the max hough value  
    2. int max_hough = 0;  
    3. for(int i=0; i<hough_space; i++) {  
    4.     for(int j=0; j<2*max_length; j++) {  
    5.         hough_1d[(i + j * hough_space)] = hough_2d[i][j];  
    6.         if(hough_2d[i][j] > max_hough) {  
    7.             max_hough = hough_2d[i][j];  
    8.         }  
    9.     }  
    10. }  
    11. System.out.println("MAX HOUGH VALUE = " + max_hough);  
    12.   
    13. // transfer back to image pixels space from hough parameter space  
    14. int hough_threshold = (int)(threshold * max_hough);  

    从霍夫空间反变换回像素数据空间代码如下:

    [java] view plain copy
    1. // transfer back to image pixels space from hough parameter space  
    2. int hough_threshold = (int)(threshold * max_hough);  
    3. for(int row = 0; row < hough_space; row++) {  
    4.     for(int col = 0; col < 2*max_length; col++) {  
    5.         if(hough_2d[row][col] < hough_threshold) // discard it  
    6.             continue;  
    7.         int hough_value = hough_2d[row][col];  
    8.         boolean isLine = true;  
    9.         for(int i=-1; i<2; i++) {  
    10.             for(int j=-1; j<2; j++) {  
    11.                 if(i != 0 || j != 0) {  
    12.                   int yf = row + i;  
    13.                   int xf = col + j;  
    14.                   if(xf < 0continue;  
    15.                   if(xf < 2*max_length) {  
    16.                       if (yf < 0) {  
    17.                           yf += hough_space;  
    18.                       }  
    19.                       if (yf >= hough_space) {  
    20.                           yf -= hough_space;  
    21.                       }  
    22.                       if(hough_2d[yf][xf] <= hough_value) {  
    23.                           continue;  
    24.                       }  
    25.                       isLine = false;  
    26.                       break;  
    27.                   }  
    28.                 }  
    29.             }  
    30.         }  
    31.         if(!isLine) continue;  
    32.           
    33.         // transform back to pixel data now...  
    34.         double dy = Math.sin(row * hough_interval);  
    35.         double dx = Math.cos(row * hough_interval);  
    36.         if ((row <= hough_space / 4) || (row >= 3 * hough_space / 4)) {  
    37.             for (int subrow = 0; subrow < height; ++subrow) {  
    38.               int subcol = (int)((col - max_length - ((subrow - centerY) * dy)) / dx) + centerX;  
    39.               if ((subcol < width) && (subcol >= 0)) {  
    40.                   image_2d[subrow][subcol] = -16776961;  
    41.               }  
    42.             }  
    43.           } else {  
    44.             for (int subcol = 0; subcol < width; ++subcol) {  
    45.               int subrow = (int)((col - max_length - ((subcol - centerX) * dx)) / dy) + centerY;  
    46.               if ((subrow < height) && (subrow >= 0)) {  
    47.                   image_2d[subrow][subcol] = -16776961;  
    48.               }  
    49.             }  
    50.           }  
    51.     }  
    52. }  
    霍夫变换源图如下:

    霍夫变换以后,在霍夫空间显示如下:(白色表示已经找到直线信号)


    最终反变换回到像素空间效果如下:


    一个更好的运行监测直线的结果(输入为二值图像):


    完整的霍夫变换源代码如下:

    [java] view plain copy
    1. package com.gloomyfish.image.transform;  
    2.   
    3. import java.awt.image.BufferedImage;  
    4.   
    5. import com.process.blur.study.AbstractBufferedImageOp;  
    6.   
    7. public class HoughLineFilter extends AbstractBufferedImageOp {  
    8.     public final static double PI_VALUE = Math.PI;  
    9.     private int hough_space = 500;  
    10.     private int[] hough_1d;  
    11.     private int[][] hough_2d;  
    12.     private int width;  
    13.     private int height;  
    14.       
    15.     private float threshold;  
    16.     private float scale;  
    17.     private float offset;  
    18.       
    19.     public HoughLineFilter() {  
    20.         // default hough transform parameters  
    21.         //  scale = 1.0f;  
    22.         //  offset = 0.0f;  
    23.         threshold = 0.5f;  
    24.         scale = 1.0f;  
    25.         offset = 0.0f;  
    26.     }  
    27.       
    28.     public void setHoughSpace(int space) {  
    29.         this.hough_space = space;  
    30.     }  
    31.       
    32.     public float getThreshold() {  
    33.         return threshold;  
    34.     }  
    35.   
    36.     public void setThreshold(float threshold) {  
    37.         this.threshold = threshold;  
    38.     }  
    39.   
    40.     public float getScale() {  
    41.         return scale;  
    42.     }  
    43.   
    44.     public void setScale(float scale) {  
    45.         this.scale = scale;  
    46.     }  
    47.   
    48.     public float getOffset() {  
    49.         return offset;  
    50.     }  
    51.   
    52.     public void setOffset(float offset) {  
    53.         this.offset = offset;  
    54.     }  
    55.   
    56.     @Override  
    57.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
    58.         width = src.getWidth();  
    59.         height = src.getHeight();  
    60.   
    61.         if ( dest == null )  
    62.             dest = createCompatibleDestImage( src, null );  
    63.   
    64.         int[] inPixels = new int[width*height];  
    65.         int[] outPixels = new int[width*height];  
    66.         getRGB( src, 00, width, height, inPixels );  
    67.         houghTransform(inPixels, outPixels);  
    68.         setRGB( dest, 00, width, height, outPixels );  
    69.         return dest;  
    70.     }  
    71.   
    72.     private void houghTransform(int[] inPixels, int[] outPixels) {  
    73.         // prepare for hough transform  
    74.         int centerX = width / 2;  
    75.         int centerY = height / 2;  
    76.         double hough_interval = PI_VALUE/(double)hough_space;  
    77.           
    78.         int max = Math.max(width, height);  
    79.         int max_length = (int)(Math.sqrt(2.0D) * max);  
    80.         hough_1d = new int[2 * hough_space * max_length];  
    81.           
    82.         // define temp hough 2D array and initialize the hough 2D  
    83.         hough_2d = new int[hough_space][2*max_length];  
    84.         for(int i=0; i<hough_space; i++) {  
    85.             for(int j=0; j<2*max_length; j++) {  
    86.                 hough_2d[i][j] = 0;  
    87.             }  
    88.         }  
    89.           
    90.         // start hough transform now....  
    91.         int[][] image_2d = convert1Dto2D(inPixels);  
    92.         for (int row = 0; row < height; row++) {  
    93.             for (int col = 0; col < width; col++) {  
    94.                 int p = image_2d[row][col] & 0xff;  
    95.                 if(p == 0continue// which means background color  
    96.                   
    97.                 // since we does not know the theta angle and r value,   
    98.                 // we have to calculate all hough space for each pixel point  
    99.                 // then we got the max possible theta and r pair.  
    100.                 // r = x * cos(theta) + y * sin(theta)  
    101.                 for(int cell=0; cell < hough_space; cell++ ) {  
    102.                     max = (int)((col - centerX) * Math.cos(cell * hough_interval) + (row - centerY) * Math.sin(cell * hough_interval));  
    103.                     max += max_length; // start from zero, not (-max_length)  
    104.                     if (max < 0 || (max >= 2 * max_length)) {// make sure r did not out of scope[0, 2*max_lenght]  
    105.                         continue;  
    106.                     }  
    107.                     hough_2d[cell][max] +=1;  
    108.                 }  
    109.             }  
    110.         }  
    111.           
    112.         // find the max hough value  
    113.         int max_hough = 0;  
    114.         for(int i=0; i<hough_space; i++) {  
    115.             for(int j=0; j<2*max_length; j++) {  
    116.                 hough_1d[(i + j * hough_space)] = hough_2d[i][j];  
    117.                 if(hough_2d[i][j] > max_hough) {  
    118.                     max_hough = hough_2d[i][j];  
    119.                 }  
    120.             }  
    121.         }  
    122.         System.out.println("MAX HOUGH VALUE = " + max_hough);  
    123.           
    124.         // transfer back to image pixels space from hough parameter space  
    125.         int hough_threshold = (int)(threshold * max_hough);  
    126.         for(int row = 0; row < hough_space; row++) {  
    127.             for(int col = 0; col < 2*max_length; col++) {  
    128.                 if(hough_2d[row][col] < hough_threshold) // discard it  
    129.                     continue;  
    130.                 int hough_value = hough_2d[row][col];  
    131.                 boolean isLine = true;  
    132.                 for(int i=-1; i<2; i++) {  
    133.                     for(int j=-1; j<2; j++) {  
    134.                         if(i != 0 || j != 0) {  
    135.                           int yf = row + i;  
    136.                           int xf = col + j;  
    137.                           if(xf < 0continue;  
    138.                           if(xf < 2*max_length) {  
    139.                               if (yf < 0) {  
    140.                                   yf += hough_space;  
    141.                               }  
    142.                               if (yf >= hough_space) {  
    143.                                   yf -= hough_space;  
    144.                               }  
    145.                               if(hough_2d[yf][xf] <= hough_value) {  
    146.                                   continue;  
    147.                               }  
    148.                               isLine = false;  
    149.                               break;  
    150.                           }  
    151.                         }  
    152.                     }  
    153.                 }  
    154.                 if(!isLine) continue;  
    155.                   
    156.                 // transform back to pixel data now...  
    157.                 double dy = Math.sin(row * hough_interval);  
    158.                 double dx = Math.cos(row * hough_interval);  
    159.                 if ((row <= hough_space / 4) || (row >= 3 * hough_space / 4)) {  
    160.                     for (int subrow = 0; subrow < height; ++subrow) {  
    161.                       int subcol = (int)((col - max_length - ((subrow - centerY) * dy)) / dx) + centerX;  
    162.                       if ((subcol < width) && (subcol >= 0)) {  
    163.                           image_2d[subrow][subcol] = -16776961;  
    164.                       }  
    165.                     }  
    166.                   } else {  
    167.                     for (int subcol = 0; subcol < width; ++subcol) {  
    168.                       int subrow = (int)((col - max_length - ((subcol - centerX) * dx)) / dy) + centerY;  
    169.                       if ((subrow < height) && (subrow >= 0)) {  
    170.                           image_2d[subrow][subcol] = -16776961;  
    171.                       }  
    172.                     }  
    173.                   }  
    174.             }  
    175.         }  
    176.           
    177.         // convert to hough 1D and return result  
    178.         for (int i = 0; i < this.hough_1d.length; i++)  
    179.         {  
    180.           int value = clamp((int)(scale * this.hough_1d[i] + offset)); // scale always equals 1  
    181.           this.hough_1d[i] = (0xFF000000 | value + (value << 16) + (value << 8));  
    182.         }