精华内容
下载资源
问答
  • fpga过零检测算法

    千次阅读 2014-09-06 16:01:45
    算法分为两部分,零点的确定和脉冲波的产生。

    过零检测法也就是比较器的作用,可以将一定频率的正弦波转换为方波或脉冲波。这在测频率等地方是必要的,因为fpga只认沿,而不认识正弦波。

    算法分为两部分,零点的确定和脉冲波的产生。

    为什么需要确定零点。我们知道,一般的ad是比如0~5V转为0~255之类的,或者可以-2~2V输入,内部会有转化的电路。所以一般的零点不会是0,而更可能是125或者126。不过为了更加精确,真正的零点应该是(max+min)/2。采集最大值和最小值的程序很常见,就是来一个暂存器不断更新,一段时间后把值赋给max或min。

    例如:

    if(aft>maxtmp) then maxtmp<=aft; endif;

    if(aft<mintmp) then mintmp<=aft; endif;

    而脉冲波的产生则是比较前后两个数据点,如果前一个小于零点,后一个大于零点,则产生一个过零脉冲。

    这里有个技巧,以前我们检测前后两个值的方法是用拼接运算符。但ad的输出一般是多位的,用拼接运算符不方便,所以我们可以借用非阻塞赋值的特点:

    aft<=sin_in;

    prev<=aft;

    这样一来,aft就是后一个值,prev是前一个值。事实上,这种方法应当是通法。接下来就简单了:

    if(prev<=zero) and (aft>=zero) then

    pulse<='1';

    else pulse<='0';

    endif;

    展开全文
  • 过零检测

    千次阅读 2019-12-11 17:24:41
    过零检测主要有三个作用: (1) 可控硅触发。通过检测AC220V零点,可以调节可控硅的导通时间,从而进行电压控制等。 (2) 继电器保护。当使用继电器控制AC220v通断时,如果继电器在AC220v的峰值附近闭合,则会产生很...

    AC-220V零点检测
    一般系统结构都是如下图所示。
    http://bbs.21ic.com/data/attachment/forum/201705/08/130422eerrnrn9shz28gzd.png.thumb.jpg
    过零检测主要有三个作用:
    (1) 可控硅触发。通过检测AC220V过零点,可以调节可控硅的导通时间,从而进行电压控制等。
    (2) 继电器保护。当使用继电器控制AC220v通断时,如果继电器在AC220v的峰值附近闭合,则会产生很大的火花,影响继电器的寿命并产生各种电磁干扰,如果在AC220v的过零点处闭合,就会减少影响。
    (3) 计时。AC220v频率为50Hz,周期为20ms。经过全波整流后,在每个零点产生中断,可以以10ms为单位进行计时。

     

    设计原理:
    过零检测原理图如图 所示,AC220v经过变压器降为AC 9v,然后全波整流,整流后的信号便可以直接用于过零检测。滤波电容c1接后续电路如7805可以作为它用。二极管D1用来隔离整流和滤波部分,保持Zero处的波形,给过零点检测提供信号源。
    在Zero处得到取样信号,然后用两个10K电阻分压,分压后接三极管。三极管工作在开关方式,当基极电压Vbe≥0.7V时,三极管导通,输出低电平给PB4;反之三极管工作于截止状态,输出高电平给PB4。Zero处的取样信号和PB4的输入信号对应关系如图 2-2所示。利用PB4的上升沿产生10ms外部中断,每次中断产生时便是AC220v的零点。
    本范例使用6个LED作为显示,当每次过零中断产生时刷新LED显示,LED刷新频率如下:
    LED0 50HZ 闪烁10ms点亮,10ms熄灭,点亮和熄灭与电源零点同步
    LED1 25HZ闪烁20ms点亮,20ms熄灭,点亮和熄灭与电源零点同步
    LED2 12.5HZ闪烁40ms点亮,40ms熄灭,点亮和熄灭与电源零点同步
    LED3 6.25HZ闪烁80ms点亮,80ms熄灭,点亮和熄灭与电源零点同步
    LED4 3.125HZ闪烁160ms点亮,160ms熄灭,点亮和熄灭与电源零点同步
    LED5 1.5625HZ闪烁320ms点亮,320ms熄灭,点亮和熄灭与电源零点同步

    http://bbs.21ic.com/data/attachment/forum/201705/08/130700ryveqgz7moe64mue.png.thumb.jpg
    过零检测原理图

    http://bbs.21ic.com/data/attachment/forum/201705/08/130752ggxm9u9mn2rkfrr7.png.thumb.jpg

    过零中断产生与实际AC220v零点之间的时间误差
    http://bbs.21ic.com/data/attachment/forum/201705/08/130851vl8yavwxsl8sak86.png.thumb.jpg

    如上图所示,当电压降到0.7V时,PB4口得到上升沿,中断产生。中断地产生与真正的零点有一段时间差,这段时间差与变压器的输出电压和三极管前端的电阻分压有关。在本电路中,中断产生和零点之间的时间差的理论计算式为:
    0.7=4.5√2 *sin(w * t)
    其中 4.5√2是由电压峰值9√2经过两个10k电阻分压所得
    w=2*3.14* f (f为50Hz)
    经过计算,t=350us。
    经示波器实际测量,中断产生和零点之间的时间差约为500us。

     

     

     

     

     

     

    交流电的过零点检测方案较多,目前较常见的也是我之前所使用的方案如图1所示:

    http://bbs.21ic.com/data/attachment/forum/201705/08/154025wylydir421pzipdl.jpg.thumb.jpg

    图1 交流电光耦过零检测电路

    图1的电路可以检测到交流电经过零点的时间,但是它存在诸多的弊端,现列举如下:

    1. 电阻消耗功率太大,发热较多。220V交流电,按照有效值进行计算三个47K的电阻平均每个电阻的功率为220^2/(3*47k)/3=114.42mw。对于0805的贴片电阻按照1/8w的功率计算,当前的消耗功率接近其额定功率,电阻 发热大较大。同时需要注意市电的有效值为220V,其峰值电压为311V,以此计算我们可以得到每个电阻的瞬时最大功率为228mw,严重超过了电阻的额定功率,因此使用是存在危险的。
    2. 光耦的过零点反应速度慢,TZA上升沿时间长。实际测试发现光耦过零点上升沿和下降沿的跳变时间为120us左右(高低电平压差为3.3V)。对于一般的应用可以接受,但是对于通信中的同步应用该反应时间将严重影响通信质量。因为在120us内都可以认为是发生了过零事件,也就是说我对过零的判断可能存在最高达120us的偏差。
    3. 根据光耦的导通特性,该电路的零点指示滞后实际交流电发生的零点。滞后时间可以根据光耦的导通电流计算,NEC2501的典型值是10ma,实际上,当前向电流达到1ma的时候光耦一般就已经导通了。现以1ma电流计算,电阻3×47k=141k,则电压为141V,相应的滞后零点时间约为1.5ms。假设0.5ma导通则电压为70V,则滞后时间为722us。
    4. 光耦导通时间较长,即光耦电流由0变为导通电流这个渐变过程较长,导致光耦特性边缘时间差异明显,产品一致性差。假设以1ma作为光耦的导通电流,那么在220v交流电由0V变化到141V的过程需要1.5ms。而因为期间的一致性问题,部分光耦可能会在0.5ma的时候就导通,部分可能在0.7ma的时候导通。现假设一致性带来的最低导通电流为0.5ma,那么对应导通电压为71V,对应滞后零点时间为736us,这表明,不同光耦之间零点差异可能达到764us!(实际测试中我检测了10个样品,其中两个光耦导通性能差别最大的时间差达到50us,其他普遍在10us左右)。这为不同设备使用该电路进行同步制造了很大的麻烦。
    5. 受光耦导通电流限制,该电路能够检测的交流信号幅度范围较窄。以1ma计算,该光耦只能检测交流信号幅度大于141V的信号。如果该信号用于同步,那么在设备进行低压测试时将不能获取同步信号。
    6. TZA输出波形和标准方波相差较大,占空比高于50%。实际测试中占空比的时间误差达到1.2ms,在应用中该时差不能被忽略。

    基于以上列出的各个问题导致利用交流电过零点进行同步质量较差,需要改进。首先我想到的方案是利用比较器的比较功能来产生标准的方波。在交流电的正半周比较器输出高电平,在交流电的负半周比较器输出低电平。该方案的时间误差仅取决于比较器电平跳变的响应速度和比较器的差分电平分辨率。以lm319为例,偏置电压最大为10mv,比较灵敏度为5mv,5V输出电平跳变响应时间在300ns以内,加上asin(10e-3/311)/2//pi/50 = 100ns。二者总共相差约400ns,远低于图1所示的方案。在实际应用中我使用了LM358来代替比较器,其偏置电流为50na,串接1M的电阻,满足偏置电流的电压为50na×1M=50mv。按照st-lm358资料,其开环频率响应1k一下可以达到100db,因此理论上输入1mv的电平依然可以识别,和前边假设相比取50mv,asin(50mv/311)/2/pi/50 = 500ns,放大器的SR为0.6V/us,假设转换到4V,需要7us。因此使用LM358的绝对误差为7.5us,而实际上由于每个器件的共性,因此在同步上偏差应该小于1.5us。

     

    方案定下来以后就应该进行电路设计了,在实际电路调试的时候遇到很多问题,现记录于此供以后参考。主要问题包括有:

    • 对于差分运放电路缺乏基本的认识,最初考虑用电阻分压电路,按照最大电压311V,电阻分压1:100,选用2M电阻串接一个20k,取20k两端的电压,理论最大差为3.11V的样子,电路如图2-1所示。该电路最终以失败告终。经过学习和查找原因,是因为没有可靠的工作点,或者说没有统一的参考地,浮地输入无法实现放大。同样因为这个原因,在网上寻找的如图2-2所示的电路也以失败告终。

    http://bbs.21ic.com/data/attachment/forum/201705/08/154026ahd0hlzbdhhgwdzd.jpg.thumb.jpg

    • 为了能够对差分放大电路提供统一的参考基准最终对图2-2进行修改,分别从差分输入的+端和-端引一个大电阻到测试系统的“地”,因为是单电源放大考虑到LM358的共模输入信号范围0-VCC-1.5V,由于二极管限幅,二极管两端电压最多0.7V,又因为对于去其中间电平连接到地,正负端对地输入的电压范围为-0.35到+0.35。最终电路如图3所示,该电路可以实现设计功能。

    http://bbs.21ic.com/data/attachment/forum/201705/08/154026serdtkq7zzsdqied.jpg.thumb.jpg

     

     

    经验总结:

    1. 理解运算放大器的共模输入范围,这对运放电路设计很重要。如果输入信号超过共模电压范围,放大器将不能正常工作。
    2. 任何信号耦合都是需要电流驱动的,放大器限流以及不同设备间“地”的连接不是电阻越大越好。当初设计图3的电路,最初R2和R3取500K时,用示波器双通道同时测试测试地到R2,R3两端差分电压,显示其具有相同的波形,幅度8V左右。理论上其原R2,R3两端波形幅度应该为0.35V,相位相反。经过反复试验,发现其原因就在于经过R2,R3电流太小已经没有达到共“地”的效果了,降低R2,R3阻值测试波形和理论一致。
    3. 当初为了安全测试220V端电压波形,查阅了浮地测试技术的相关资料。同时经过实验验证,浮地测试必须要将示波器和被测试系统的公共地断开,具体来说就是让测试仪器和被测试平台不具备相同的参考地电位,这样短接示波器探头的地到被测试平台才不会发生事故。拿本实验举例,假设我们需要测量市电实时波形,怎么测量呢。我们可以这样测试,示波器供电时三芯插头只连接L和N端,接地不连接,这样就可以通过接地夹夹在市电的一端,用探头去测量另一端的波形了。当然最好还是在接地夹串接以大电阻去接市电一端,探头也串接一大电阻去接市电另一端。如果不这样测试会有什么后果???如果不这样测试,因为示波器探头的接地夹是和三芯插头地线导通的,在通过接地夹去夹火线或者零线是就相当于把火线或零线直接与大地相连,如果是零线还没事,如果是火线那必然短路!非常危险!!!

     

    ——转自21IC社区

    http://bbs.21ic.com/icview-1714198-1-1.html

     

    展开全文
  • 主流图像边缘检测算法

    万次阅读 多人点赞 2016-09-06 23:54:52
    本文内容包括:图像噪声添加与去除、几种滤波算法【高斯滤波,方框滤波,均值滤波,中值滤波,双边滤波,小波变换】、几种检测算法【Canny算子、Sobel算子、Laplace算子、Roberts算子、Susan Krisch Prewitt角点检测...

    前言:最近在学习关于图像边缘检测技术,更新此博文仅为 了记录个人学习过程,也供有共同志趣的朋友参考!

    本文内容包括:图像噪声添加与去除、几种滤波算法【高斯滤波,方框滤波,均值滤波,中值滤波,双边滤波,小波变换】、几种检测算法【Canny算子、Sobel算子、Laplace算子、Roberts算子、Krisch算子、Prewitt算子、Susan角点检测算法】、MFC图形界面实现等。


    作者博客地址:永春小站
    文中所有代码均在本人电脑上正常运行!

    测试环境:VS2013+opevCV2.49


    先上一张最终效果图
    这里写图片描述


    目录:
    一、图像噪声
    1.图像噪声分类
    <1>噪声分类
    <2>滤波算法

    2.给图像添加噪声
    <1>高斯白噪声
    <2>椒盐噪声
    <3>编程实现

    二、滤波算法
    1.关于图像滤波

    2.图像滤波分类

    3.滤波算法介绍
    <1>高斯滤波
    <2>方框滤波
    <3>均值滤波
    <4>中值滤波
    <5>双边滤波

    三、图像增强
    1.对数增强算法
    2.指数增强算法
    3.高曝光
    4.高反差

    四、边缘检测
    1.Canny算子
    2.Sobel算子
    3.Laplace算子
    4.Roberts算子
    5.Krisch算子
    6.Prewitt算子

    7.角点检测算法
    <1>Susan角点检测

    五、MFC实现
    1.框架搭建
    2.功能实现

    六、结论


    一、图像噪声

    1.图像噪声分类

    <1>图像噪声分类
    噪声的分类和该噪声的分布符合什么模型有关,常见的噪声有高斯白噪声、椒盐噪声、泊松分布噪声、指数分布噪声等。

    <2>图像滤波器
    图像滤波器有空域滤波器,比如均值滤波器、中值滤波器、低通滤波器、高斯滤波等;频域滤波器,比如小波变换、傅里叶变换、余弦变换等;形态学滤波器,主要是通过膨胀和腐蚀等形态学操作进行去噪。
    一般平时见的比较多是是高斯白噪声,像用均值滤波、中值滤波、高斯滤波可以去噪。除此以外,像椒盐噪声,一般用中值滤波基本可以去噪。

    2.给图像添加噪声
    以上说了图像噪声的分类,以下则针对常见的高斯白噪声和椒盐噪声进行详解

    <1>高斯白噪声
    高斯白噪声中的高斯是指概率分布是正态函数,而白噪声是指它的二阶矩不相关,一阶矩为常数,是指先后信号在时间上的相关性。这是考查一个信号的两个不同方面的问题。

    <2>椒盐噪声
    椒盐噪声其实是椒噪声和盐噪声的统称,椒噪声即图像中灰度值为255的像素点,盐噪声则为0。

    <3>编程实现

    /*-----------CreateNoise类-------------------*/
    //CreateNoise.h文件
    //功能:产生图像噪声
    //使用:调用成员函数void AddGaussianNoise(Mat&)添加高斯噪声
    //调用成员函数void AddPepperNoise(Mat&int n)添加高斯噪声
    //调用成员函数void AddSaitNoise(Mat&,int n)添加高斯噪声
    
    #ifndef _CREATENOISE
    #define _CREATENOISE
    
    #include <opencv2/core/core.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <iostream>
    
    #define TWO_PI 6.2831853071795864769252866
    
    using namespace cv;
    using namespace std;
    
    class CreateNoise{
    private:
    	double generateGaussianNoise();//创建高斯噪声函数原型
    
    public:
    	void AddPepperNoise(Mat &image, int n);//添加椒噪声
    	void AddSaltNoise(Mat &image, int n);//添加盐噪声
    	void AddGaussianNoise(Mat&);//添加高斯噪声
    };
    
    #endif
    
    //CreateNoise.cpp文件
    /*给图像添加高斯噪声*/
    #include"com.fanyu.createNoise.h"
    
    //产生高斯噪声
    double CreateNoise::generateGaussianNoise(){
    	static bool hasSpare = false;
    	static double rand1, rand2;
    
    	if (hasSpare)
    	{
    		hasSpare = false;
    		return sqrt(rand1) * sin(rand2);
    	}
    
    	hasSpare = true;
    
    	rand1 = rand() / ((double)RAND_MAX);
    	if (rand1 < 1e-100) rand1 = 1e-100;
    	rand1 = -2 * log(rand1);
    	rand2 = (rand() / ((double)RAND_MAX)) * TWO_PI;
    
    	return sqrt(rand1) * cos(rand2);
    }
    
    //高斯噪声
    void CreateNoise::AddGaussianNoise(Mat& I){
    	// accept only char type matrices
    	CV_Assert(I.depth() != sizeof(uchar));
    
    	int channels = I.channels();
    
    	int nRows = I.rows;
    	int nCols = I.cols * channels;
    
    	if (I.isContinuous()){
    		nCols *= nRows;
    		nRows = 1;
    	}
    
    	int i, j;
    	uchar* p;
    	for (i = 0; i < nRows; ++i){
    		p = I.ptr<uchar>(i);
    		for (j = 0; j < nCols; ++j){
    			double val = p[j] + generateGaussianNoise() * 32;
    			if (val < 0)
    				val = 0;
    			if (val > 255)
    				val = 255;
    
    			p[j] = (uchar)val;
    
    		}
    	}
    
    }
    
    //盐噪声
    void CreateNoise::AddSaltNoise(Mat &image, int n) {//n为噪点数目
    	int i, j;
    	for (int k = 0; k<n / 2; k++) {
    
    		// rand() is the random number generator
    		i = std::rand() % image.cols; // % 整除取余数运算符,rand=1022,cols=1000,rand%cols=22
    		j = std::rand() % image.rows;
    
    		if (image.type() == CV_8UC1) { // gray-level image
    
    			image.at<uchar>(j, i) = 255; //at方法需要指定Mat变量返回值类型,如uchar等
    
    		}
    		else if (image.type() == CV_8UC3) { // color image
    
    			image.at<cv::Vec3b>(j, i)[0] = 255; //cv::Vec3b为opencv定义的一个3个值的向量类型
    			image.at<cv::Vec3b>(j, i)[1] = 255; //[]指定通道,B:0,G:1,R:2
    			image.at<cv::Vec3b>(j, i)[2] = 255;
    		}
    	}
    }
    
    //椒噪声
    void CreateNoise::AddPepperNoise(Mat &image, int n) {//n为噪点数目
    
    	int i, j;
    	for (int k = 0; k<n; k++) {
    
    		// rand() is the random number generator
    		i = std::rand() % image.cols; // % 整除取余数运算符,rand=1022,cols=1000,rand%cols=22
    		j = std::rand() % image.rows;
    
    		if (image.type() == CV_8UC1) { // gray-level image
    
    			image.at<uchar>(j, i) = 0; //at方法需要指定Mat变量返回值类型,如uchar等
    
    		}
    		else if (image.type() == CV_8UC3) { // color image
    
    			image.at<cv::Vec3b>(j, i)[0] = 0; //cv::Vec3b为opencv定义的一个3个值的向量类型
    			image.at<cv::Vec3b>(j, i)[1] = 0; //[]指定通道,B:0,G:1,R:2
    			image.at<cv::Vec3b>(j, i)[2] = 0;
    		}
    	}
    }
    

    二、图像滤波

    1.图像滤波说明【来源搜狗词条】

    图像滤波,即在尽量保留图像细节特征的条件下对目标像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。
    由于成像系统、传输介质和记录设备等的不完善,数字图像在其形成、传输记录过程中往往会受到多种噪声的污染。另外,在图像处理的某些环节当输入的像对象并不如预想时也会在结果图像中引入噪声。这些噪声在图像上常表现为一引起较强视觉效果的孤立像素点或像素块。一般,噪声信号与要研究的对象不相关它以无用的信息形式出现,扰乱图像的可观测信息。对于数字图像信号,噪声表为或大或小的极值,这些极值通过加减作用于图像像素的真实灰度值上,在图像造成亮、暗点干扰,极大降低了图像质量,影响图像复原、分割、特征提取、图识别等后继工作的进行。要构造一种有效抑制噪声的滤波机必须考虑两个基本问题能有效地去除目标和背景中的噪声;同时,能很好地护图像目标的形状、大小及特定的几何和拓扑结构特征。

    2.滤波器分类
    对于滤波器的分类按需求可有多种分类方式,滤波方法也各不相同,在此主要根据图像噪声处理介绍一种分类:

    不同的滤波器用于不同的噪声,很难说某一个降噪滤波器能符所有的噪声。
    首先,说一下噪声的类型吧,噪声的分类和该噪声的分布符合什么模型有关,常见的噪声有高斯白噪声、椒盐噪声、泊松分布噪声、指数分布噪声等。
    其次,采用的滤波器有空域滤波器,比如均值滤波器、中值滤波器、低通滤波器、高斯滤波等;频域滤波器,比如小波变换、傅里叶变换、余弦变换等;形态学滤波器,主要是通过膨胀和腐蚀等形态学操作进行去噪。
    第三,对应场合。一般平时见的比较多是是高斯白噪声,像用均值滤波、中值滤波、高斯滤波可以去噪。还有在低照度下,比如晚上拍照时的图像,一般属于泊松分布的噪声,可以采用一些3d去噪算法,比如效果不错的BM3D算法。像椒盐噪声,一般用中值滤波基本可以去噪。

    作者:chaoren xiongmao
    链接:http://www.zhihu.com/question/20095134/answer/14158067
    来源:知乎
    著作权归作者所有,转载请联系作者获得授权。

    3.滤波算法
    <1>高斯滤波算法
    openCV中封装了高斯滤波函数

    C++: void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT )  
    

    第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。它可以是单独的任意通道数的图片,但需要注意,图片深度应该为CV_8U,CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
    第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
    第三个参数,Size类型的ksize高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数。或者,它们可以是零的,它们都是由sigma计算而来。
    第四个参数,double类型的sigmaX,表示高斯核函数在X方向的的标准偏差。
    第五个参数,double类型的sigmaY,表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX,如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。
    为了结果的正确性着想,最好是把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定到。
    第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。
      
    应用:

    /*线性滤波:高斯滤波*/
    bool GaussianBlur(String srcAdress, String dstAdress = "E:/opencv/averageFilter.jpg"){
    
    	Mat srcImage = imread(srcAdress, 1);
    	Mat dstImage;
    	if (!srcImage.data) {
    		cout << "图像读取出错!";
    		return false;
    	}
    
    	//滤波操作
    	GaussianBlur(srcImage, dstImage, Size(7,7),0,0);
    
    	//导出
    	imwrite(dstAdress, dstImage);
    
    	//显示
    	imshow("原图:", srcImage);
    	imshow("高斯滤波效果:", dstImage);
    
    	waitKey(0);
    
    	return true;
    }
    

    效果展示:
    这里写图片描述

    <2>方框滤波算法
    openCV中封装该函数,函数原型为

    C++: void boxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT )  
    

    参数详解:
    第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
    第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
    第三个参数,int类型的ddepth,输出图像的深度,-1代表使用原图深度,即src.depth()。
    第四个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
    第五个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
    第六个参数,bool类型的normalize,默认值为true,一个标识符,表示内核是否被其区域归一化(normalized)了。
    第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

    编程实现

    /*线性滤波:方框滤波*/
    int kenelValue = 3;
    int MaxkenelValue = 50;
    String srcAdress, dstAdress;
    //回调函数
    static void callBackboxFilter(int, void*){
    
    	Mat srcImage = imread(srcAdress,1);
    	Mat dstImage;
    	if (!srcImage.data){
    		cout << "图像读取出错";
    		return;
    	}
    
    	//滤波操作
    	boxFilter(srcImage, dstImage, -1, Size(kenelValue+1, kenelValue+1));
    
    	//显示
    	imshow("方框滤波效果预览:", dstImage);
    
    }
    //创建进度条
    int boxFilter(String ssrcAdress, String sdstAdress = "E:/opencv/boxFilter.jpg"){
    	
    	srcAdress = ssrcAdress;
    	dstAdress=sdstAdress;
    
    	namedWindow("方框滤波效果预览:",WINDOW_AUTOSIZE);
    	
    	//创建进度条
    	createTrackbar("内核大小:", "方框滤波效果预览:", &kenelValue, MaxkenelValue, callBackboxFilter);
    	
    	//回调
    	callBackboxFilter(kenelValue, 0);
    	
    	waitKey(0);
    
    	return 0;
    }
    

    效果展示
    这里写图片描述

    <3>均值滤波算法
    openCV中封装了均值滤波算法函数

    C++: void blur(InputArray src, OutputArraydst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )  
    

    参数详解
    第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
    第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
    第三个参数,Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
    第四个参数,Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
    第五个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。

    应用

    /*线性滤波:均值滤波*/
    bool blur(String srcAdress, String dstAdress = "E:/opencv/averageFilter.jpg"){
    
    	Mat srcImage = imread(srcAdress, 1);
    	Mat dstImage;
    	if (!srcImage.data) {
    		cout << "图像读取出错!";
    		return false;
    	}
    
    	//滤波操作
    	blur(srcImage, dstImage, Size(7, 7));
    
    	//导出
    	imwrite(dstAdress, dstImage);
    
    	//显示
    	imshow("原图:", srcImage);
    	imshow("均值滤波效果:", dstImage);
    
    	waitKey(0);
    
    	return true;
    }
    

    效果
    这里写图片描述

    <4>中值滤波算法
    openCV封装了该算法

    C++: void medianBlur(InputArray src,OutputArray dst, int ksize) 
    

    参数详解:
    第一个参数,InputArray类型的src,函数的输入参数,填1、3或者4通道的Mat类型的图像;当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。
    第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。我们可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
    第三个参数,int类型的ksize,孔径的线性尺寸(aperture linear size),注意这个参数必须是大于1的奇数,比如:3,5,7,9 …

    应用

    /*非线性滤波:中值滤波*/
    bool medianBlur(String src,String dst){
    	Mat srcImage = imread(src,1);
    	Mat dstImage;
    	if (!srcImage.data)
    		return false;
    
    	//滤波操作[注意:中间值取奇数]
    	medianBlur(srcImage,dstImage,7);
    
    	//显示
    	imshow("原图:",srcImage);
    	imshow("中值滤波效果图:",dstImage);
    
    	//导出
    	imwrite(dst,dstImage);
    
    	waitKey(0);
    
    	return true;
    }
    

    效果
    这里写图片描述

    <5>双边滤波算法
    openCV封装了该函数

    C++: void bilateralFilter(InputArray src, OutputArraydst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
    

    参数详解:
    第一个参数,InputArray类型的src,输入图像,即源图像,需要为8位或者浮点型单通道、三通道的图像。
    第二个参数,OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。
    第三个参数,int类型的d,表示在过滤过程中每个像素邻域的直径。如果这个值我们设其为非正数,那么OpenCV会从第五个参数sigmaSpace来计算出它来。
    第四个参数,double类型的sigmaColor,颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
    第五个参数,double类型的sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
    第六个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_DEFAULT。

    应用:

    /*非线性滤波:双边滤波*/
    bool bilateralFilter(String src, String dst){
    	Mat srcImage = imread(src, 1);
    	Mat dstImage;
    	if (!srcImage.data)
    		return false;
    
    	//滤波操作
    	bilateralFilter(srcImage, dstImage, 25*2,25*2*2,25/2*2);
    
    	//显示
    	imshow("原图:", srcImage);
    	imshow("双边滤波效果图:", dstImage);
    
    	//导出
    	imwrite(dst, dstImage);
    
    	waitKey(0);
    
    	return true;
    }
    

    效果:[由图可见,双边滤波对椒盐噪声是无作用的]
    这里写图片描述

    三、图像增强
    1.对数增强算法
    2.指数增强算法
    3.高曝光
    4.高反差
    以上功能集成在下面的cpp文件中

    /************************************************************
    *  图像增强算法【在主函数main中调用即可】
    *  使用说明:
    *   
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include<iostream>  
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    /*对数图像增强算法*/
    //对数图像增强是图像增强的一种常见方法,其公式为: S = c log(r + 1),
    //其中c是常数(以下算法c = 255 / (log(256)),这样可以实现整个画面的亮度增大。
    void LogEnhance(IplImage* img, IplImage* dst)
    {
    	// 由于oldPixel:[1,256],则可以先保存一个查找表
    	uchar lut[256] = { 0 };
    
    	double temp = 255 / log(256);
    
    	for (int i = 0; i<255; i++)
    	{
    		lut[i] = (uchar)(temp* log(i + 1) + 0.5);
    	}
    
    	for (int row = 0; row <img->height; row++)
    	{
    		uchar *data = (uchar*)img->imageData + row* img->widthStep;
    		uchar *dstData = (uchar*)dst->imageData + row* dst->widthStep;
    
    		for (int col = 0; col<img->width; col++)
    		{
    			for (int k = 0; k<img->nChannels; k++)
    			{
    				uchar t1 = data[col*img->nChannels + k];
    				dstData[col*img->nChannels + k] = lut[t1];
    			}
    		}
    	}
    }
    
    
    /*指数图像增强算法*/
    //指数图像增强的表达为:S = cR^r,通过合理的选择c和r可以压缩灰度范围,
    //算法以c = 1.0 / 255.0, r = 2实现。
    void ExpEnhance(IplImage* img, IplImage* dst)
    {
    	// 由于oldPixel:[1,256],则可以先保存一个查找表
    	uchar lut[256] = { 0 };
    
    	double temp = 1.0 / 255.0;
    
    	for (int i = 0; i<255; i++)
    	{
    		lut[i] = (uchar)(temp*i*i + 0.5);
    	}
    
    	for (int row = 0; row <img->height; row++)
    	{
    		uchar *data = (uchar*)img->imageData + row* img->widthStep;
    		uchar *dstData = (uchar*)dst->imageData + row* dst->widthStep;
    
    		for (int col = 0; col<img->width; col++)
    		{
    			for (int k = 0; k<img->nChannels; k++)
    			{
    				uchar t1 = data[col*img->nChannels + k];
    				dstData[col*img->nChannels + k] = lut[t1];
    			}
    		}
    	}
    }
    
    /*曝光过度问题处理*/
    //对于曝光过度问题,可以通过计算当前图像的反相(255 - image),
    //然后取当前图像和反相图像的较小者为当前像素位置的值。
    // 过度曝光原理:图像翻转,然后求原图与反图的最小值
    void ExporeOver(IplImage* img, IplImage* dst)
    {
    	for (int row = 0; row <img->height; row++)
    	{
    		uchar *data = (uchar*)img->imageData + row* img->widthStep;
    		uchar *dstData = (uchar*)dst->imageData + row* dst->widthStep;
    		for (int col = 0; col<img->width; col++)
    		{
    			for (int k = 0; k<img->nChannels; k++)
    			{
    				uchar t1 = data[col*img->nChannels + k];
    				uchar t2 = 255 - t1;
    				dstData[col*img->nChannels + k] = min(t1, t2);
    			}
    		}
    	}
    }
    
    
    /*高反差保留*/
    //高反差保留主要是将图像中颜色、明暗反差较大两部分的交界处保留下来,
    //比如图像中有一个人和一块石头,那么石头的轮廓线和人的轮廓线以及面部、
    //服装等有明显线条的地方会变被保留,儿其他大面积无明显明暗变化的地方
    //则生成中灰色。其表达形式为:dst = r*(img - Blur(img))。
    Mat HighPass(Mat img)
    {
    	Mat temp;
    	GaussianBlur(img, temp, Size(7, 7), 1.6, 1.6);
    
    	int r = 3;
    	Mat diff = img + r*(img - temp); //高反差保留算法
    	return diff;
    }
    
    

    效果图:
    对数增强
    这里写图片描述

    指数增强
    这里写图片描述

    高曝光
    这里写图片描述

    高反差
    这里写图片描述

    重头戏来了!!!
    上面讲了那么多,其实都只是在为图像检测做准备,以下就是本文的重点!

    四、边缘检测
    1.Canny算子
    关于Canny算子原理请参考百度百科
    http://baike.baidu.com/link?url=ExVCDbWfd9DPB20z2SzPjB4kHDcxHkJD25lVQIDL-cZSc9HVeTNWPCTLHsCveobPulIUaX6HEu8z0lbsGRfi9a

    首先来看openCV中的Canny函数

    C++: void Canny(InputArray image,OutputArray edges, double threshold1, double threshold2, int apertureSize=3,bool L2gradient=false )  
    

    参数详解
    第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
    第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和类型。
    第三个参数,double类型的threshold1,第一个滞后性阈值。
    第四个参数,double类型的threshold2,第二个滞后性阈值。
    第五个参数,int类型的apertureSize,表示应用Sobel算子的孔径大小,其有默认值3。
    第六个参数,bool类型的L2gradient,一个计算图像梯度幅值的标识,有默认值false。

    应用:

    /************************************************************
    *  边缘检测算法函数之Canny算子【在主函数main中调用即可】
    *  使用说明:
    *    两个轨迹条分别表示Canny算子中的滞后阈值和高斯滤波内核值
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include<iostream>  
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    
    
    /*----------------------------------------【Canny算子篇】------------------------------------------*/
    /**Canny算子检测
     *1.原理:
     *(1)图像边缘检测必须满足两个条件:一是能有效地抑制噪声,而是必须尽量精确的确定边缘的位置。
     *(2)根据对信噪比与定位乘积进行测度,得到最优化逼近算子,即Canny算子。
     *(3)先平滑后求导
     *
     *2.Canny的目标是找到一个最优的边缘检测算法,最优的含义是:
     *(1)好的检测—算法能够尽可能多的标识出图像中的实际边缘
     *(2)好的定位—标识出的边缘要尽可能与实际图像中的实际边缘尽可能接近。
     *(3)最小响应—图像中的边缘只能标志一次,并且可能存在的图像杂讯不因该标志为边缘。
     *
     *3.Canny边缘检测步骤:
     *(1)去噪
     *任何边缘检测算法都不可能在未经处理的原始数据上很好地處理,所以第一步是对原始数据与高斯 mask 作卷积,得到的
     *图像与原始图像相比有些轻微的模糊(blurred)。这样,单独的一个像素杂讯在经过高斯平滑的图像上变得几乎没有影响。
     *(2)用一阶偏导的有限差分来计算梯度的幅值和方向。
     *(3)对梯度幅值进行非极大值抑制。
     *仅仅得到全局的梯度并不足以确定边缘,因此为确定边缘,必须保留局部梯度最大的点,而抑制非极大值。解决方法:利用梯度的方向。
     *(4)用双阈值算法检测和连接边缘。
     *减少假边缘段数量的典型方法是对N[i,j]使用一个阈值。将低于阈值的所有值赋零值。但问题是如何选取阈值?
     *解决方法:双阈值算法。双阈值算法对非极大值抑制图象作用两个阈值τ1和τ2,且2τ1≈τ2,从而可以得到两个阈值边缘图象N1[i,j]
     *和N2[i,j]。由于N2[i,j]使用高阈值得到,因而含有很少的假边缘,但有间断(不闭合)。双阈值法要在N2[i,j]中把边缘连接成轮
     *廓,当到达轮廓的端点时,该算法就在N1[i,j]的8邻点位置寻找可以连接到轮廓上的边缘,这样,算法不断地在N1[i,j]中收集边缘,
     *直到将N2[i,j]连接起来为止。
     *在连接边缘的时候,用数组模拟队列的实现。以进行8-连通域搜索。
     */
    
    /*---------------------函数使用-------------------------*/
    //参数初始化
    int thresholdValue1 = 270;//滞后性阈值1
    int kenelValueCanny = 4;//降噪内核值
    const static int MaxKenelValueCanny = 10;
    const static int MaxThresholdValue1 = 300;
    String srcAdressCanny;
    
    //回调函数
    static void callBackCanny(int, void*){
    
    	Mat srcImage = imread(srcAdressCanny, 3);
    	Mat dstImage, grayImage, denoiseImage,cannyImage;
    	if (!srcImage.data){
    		cout << "图像读取出错";
    		return;
    	}
    
    	//创建与srcImage同类型和大小的矩阵 
    	dstImage.create(srcImage.size(), srcImage.type());
    
    	//将原图像转换为灰度图像  
    	cvtColor(srcImage, grayImage, CV_BGR2GRAY);
    
    	//高斯滤波降噪
    	GaussianBlur(grayImage, denoiseImage, Size(kenelValueCanny * 2 + 1, kenelValueCanny * 2 + 1), 0, 0);
    		
    	//使用Canny算子
    	Canny(denoiseImage, cannyImage, thresholdValue1, thresholdValue1 * 2 / 3, 3);
    	
    	//将dstImage内的所有元素设置为0
    	dstImage = Scalar::all(0);
    
    	//以cannyImage作为掩码,将原图srcImage拷到目标图dstImage中
    	srcImage.copyTo(dstImage, cannyImage);
    
    	//显示
    	imshow("原图", srcImage);
    	imshow("Canny算子边缘检测效果预览:", dstImage);
    	imwrite("E:/opencv/Canny.jpg",dstImage);
    }
    
    //创建进度条
    void Canny(String ssrcAdress){
    
    	srcAdressCanny = ssrcAdress;
    
    	namedWindow("Canny算子边缘检测效果预览:", WINDOW_AUTOSIZE);
    
    	//创建进度条
    	createTrackbar("内核值:", "Canny算子边缘检测效果预览:", &kenelValueCanny, MaxKenelValueCanny, callBackCanny);
    	createTrackbar("阈值一:", "Canny算子边缘检测效果预览:", &thresholdValue1, MaxThresholdValue1, callBackCanny);
    	
    	//回调
    	callBackCanny(kenelValueCanny, 0);
    	callBackCanny(thresholdValue1, 0);
    
    	waitKey(0);
    	
    }
    
    

    效果:
    这里写图片描述

    2.Sobel算子
    Sobel 算子是一个主要用作边缘检测的离散微分算子 (discrete differentiation operator)。 它Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子,将会产生对应的梯度矢量或是其法矢量。

    sobel算子的wikipedia:
    http://zh.wikipedia.org/wiki/索貝爾算子

    sobel算子相关概念,还可以参看这篇博文:
    http://www.cnblogs.com/lancidie/archive/2011/07/17/2108885.html

    openCV中的Sobel算子详解

    C++: void Sobel (  
    InputArray src,//输入图  
     OutputArray dst,//输出图  
     int ddepth,//输出图像的深度  
     int dx,  
     int dy,  
     int ksize=3,  
     double scale=1,  
     double delta=0,  
     int borderType=BORDER_DEFAULT );  
    

    参数说明:
    第一个参数,InputArray 类型的src,为输入图像,填Mat类型即可。
    第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
    第三个参数,int类型的ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合:
    若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F
    若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F
    若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F
    若src.depth() = CV_64F, 取ddepth = -1/CV_64F
    第四个参数,int类型dx,x 方向上的差分阶数。
    第五个参数,int类型dy,y方向上的差分阶数。
    第六个参数,int类型ksize,有默认值3,表示Sobel核的大小;必须取1,3,5或7。
    第七个参数,double类型的scale,计算导数值时可选的缩放因子,默认值是1,表示默认情况下是没有应用缩放的。我们可以在文档中查阅getDerivKernels的相关介绍,来得到这个参数的更多信息。
    第八个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
    第九个参数, int类型的borderType,我们的老朋友了(万年是最后一个参数),边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate处得到更详细的信息。

    应用:

    /************************************************************
    *  边缘检测算法函数之Sobel算子【在主函数main中调用即可】
    *  使用说明:
    *    
    *
    *  @author zha_yongchun
    *  @version 2016.8.6.001
    *************************************************************/
    
    #include <opencv2/opencv.hpp>  
    #include<opencv2/highgui/highgui.hpp>  
    #include<opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    
    
    /*----------------------------------------【Sobel算子篇】------------------------------------------*/
    
    bool Sobel(String src, String dst){
    	
    	Mat srcImage = imread(src,3);
    	Mat grad_Image,grayImage;
    	Mat abs_grad_Image, dstImage;
    	if (!srcImage.data) 
    		return false;
    
    	//将原图像转换为灰度图像  
    	cvtColor(srcImage, grayImage, CV_BGR2GRAY);
    
    	//求(x,y)方向梯度
    	Sobel( grayImage, grad_Image, CV_16S, 1, 1, 3, 1, 1, BORDER_DEFAULT );  
    	convertScaleAbs(grad_Image, abs_grad_Image);
    
    	//显示
    	imshow("原图:", srcImage);
    	imshow("Sobel函数效果图:", abs_grad_Image);
    
    	//导出
    	imwrite(dst, abs_grad_Image);
    
    	waitKey(0);
    
    	return true;
    }
    
    

    效果
    这里写图片描述

    3.Laplace算子
    Laplacian 算子是n维欧几里德空间中的一个二阶微分算子,定义为梯度grad()的散度div()。因此如果f是二阶可微的实函数,则f的拉普拉斯算子定义为:

    (1) f的拉普拉斯算子也是笛卡儿坐标系xi中的所有非混合二阶偏导数求和:
    (2) 作为一个二阶微分算子,拉普拉斯算子把C函数映射到C函数,对于k ≥ 2。表达式(1)(或(2))定义了一个算子Δ :C® → C®,或更一般地,定义了一个算子Δ : C(Ω) → C(Ω),对于任何开集Ω。

    关于Laplace算子的相关概念阐述,可以参看这篇博文:
    http://www.cnblogs.com/xfzhang/archive/2011/01/19/1939020.html
    Laplace算子的wikipedia:
    http://zh.wikipedia.org/wiki/拉普拉斯算子

    openCV中的Laplace函数

    C++: void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, intborderType=BORDER_DEFAULT );  
    

    第一个参数,InputArray类型的image,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位图像。
    第二个参数,OutputArray类型的edges,输出的边缘图,需要和源图片有一样的尺寸和通道数。
    第三个参数,int类型的ddept,目标图像的深度。
    第四个参数,int类型的ksize,用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1。
    第五个参数,double类型的scale,计算拉普拉斯值的时候可选的比例因子,有默认值1。
    第六个参数,double类型的delta,表示在结果存入目标图(第二个参数dst)之前可选的delta值,有默认值0。
    第七个参数, int类型的borderType,边界模式,默认值为BORDER_DEFAULT。这个参数可以在官方文档中borderInterpolate()处得到更详细的信息。

    应用

    /************************************************************
    *  边缘检测算法函数之Laplace算子【在主函数main中调用即可】
    *  使用说明:
    *    
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include<iostream>  
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    
    
    /*----------------------------------------【Laplace算子篇】------------------------------------------*/
    
    bool Laplacian(int kenelValue,String src, String dst){
    
    	Mat srcImage, dstImage, grayImage, abs_dstImage,gaussImage;
    	
    	srcImage = imread(src,3);
    	if (!srcImage.data)
    		return false;
    
    	//转为灰度图
    	cvtColor(srcImage,grayImage,CV_RGB2GRAY);
    
    	//高斯滤波
    	GaussianBlur(grayImage, gaussImage, Size(kenelValue,kenelValue), 0, 0, BORDER_DEFAULT);
    
    	//使用Laplace算子
    	Laplacian(gaussImage, abs_dstImage, CV_16S, 3, 1, 0, BORDER_DEFAULT);
    
    	//计算绝对值,并将结果转换成8位  
    	convertScaleAbs(abs_dstImage,dstImage );
    
    	//显示
    	imshow("原图:",srcImage);
    	imshow("Laplace算法:",dstImage);
    
    	//导出
    	imwrite(dst,dstImage);
    
    	waitKey(3000);
    	return true;
    }
    
    

    效果
    这里写图片描述

    4.Roberts算子
    这个函数在openCV库中没有,因此需要自己来实现
    具体代码如下

    /************************************************************
    *  边缘检测算法函数之Robers算子【在主函数main中调用即可】
    *  使用说明:
    *    
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include<iostream>  
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    // roberts算子实现
    cv::Mat roberts(cv::Mat srcImage)
    {
    	cv::Mat dstImage = srcImage.clone();
    	int nRows = dstImage.rows;
    	int nCols = dstImage.cols;
    	for (int i = 0; i < nRows - 1; i++)
    	{
    		for (int j = 0; j < nCols - 1; j++)
    		{
    			// 根据公式计算
    			int t1 = (srcImage.at<uchar>(i, j) -
    				srcImage.at<uchar>(i + 1, j + 1)) *
    				(srcImage.at<uchar>(i, j) -
    				srcImage.at<uchar>(i + 1, j + 1));
    			int t2 = (srcImage.at<uchar>(i + 1, j) -
    				srcImage.at<uchar>(i, j + 1)) *
    				(srcImage.at<uchar>(i + 1, j) -
    				srcImage.at<uchar>(i, j + 1));
    			// 计算对角线像素差
    			dstImage.at<uchar>(i, j) = (uchar)sqrt(t1 + t2);
    		}
    	}
    	return dstImage;
    }
    
    void Robers(String str,String dst){
    	Mat strImage = imread(str,0);
    	Mat dstImage;
    	if (!strImage.data)
    		return;
    
    	imshow("原图",strImage);
    
    	dstImage=roberts(strImage);//调用robers算子
    
    	imshow("Robers算子实现",dstImage);
    	imwrite(dst,dstImage);
    
    	cvWaitKey(0);
    }
    

    效果
    这里写图片描述

    5.Krisch算子
    Kirsch算子是R.Kirsch提出来一种边缘检测新算法,它采用8个模板对图像上的每一个像素点进行卷积求导数,这8个模板代表8个方向,对图像上的8个特定边缘方向作出最大响应,运算中取最大值作为图像的边缘输出(上述算法中用到的8个模板在下面的实现代码中给出)。为了便于读者理解该算法的实现,这里我们给出实现该算法的函数代码,读者可以稍加改动应用到自己的项目中去。[1]
    int ntemplate[8][9]={{5,5,5,-3,0,-3,-3,-3,-3},
      {-3,5,5,-3,0,5,-3,-3,-3},
      {-3,-3,5,-3,0,5,-3,-3,5},
      {-3,-3,-3,-3,0,5,-3,5,5},
      {-3,-3,-3,-3,0,-3,5,5,5},
      {-3,-3,-3,5,0,-3,5,5,-3},
      {5,-3,-3,5,0,-3,5,-3,-3},
      {5,5,-3,5,0,-3,-3,-3,-3}};//3×3
    用这个8个模版来计算每个边缘方向的最大响应值作为边缘特征值-边缘强度。
    详情参见百度百科
    http://baike.baidu.com/link?url=g4TjG-zN4bTLIJmo8wppKe-Ov1STWrL5HON_XiPL3izUNbG-bi0xisrFsHdtIdAFKuY2dTOXvOZmV1rOq-TpVq

    实现代码

    /************************************************************
    *  边缘检测算法函数之Krisch检测算子【在主函数main中调用即可】
    *  使用说明:
    *
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include<iostream>  
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    void Krisch(char* path)
    {
    	IplImage *src;
    	src = cvLoadImage(path, 0); //0 单通道加载
    	if (!src)
    		return;
    	IplImage *dst = cvCloneImage(src);
    	int x, y;
    	float a, b, c, d;
    	float p1, p2, p3, p4, p5, p6, p7, p8, p9;
    	uchar* ps = (uchar*)src->imageData; //ps为指向输入图片数据的指针
    	uchar* pd = (uchar*)dst->imageData; //pd为指向输出图片数据的指针
    	int w = dst->width;
    	int h = dst->height;
    	int step = dst->widthStep;
    
    	for (x = 0; x<w - 2; x++)      //取以(x+1,y+1)为中心的9个邻域像素  1 4 7
    	{                                                            // 2 5 8
    		for (y = 0; y<h - 2; y++)                                     // 3 6 9
    		{
    			p1 = ps[y*step + x];
    			p2 = ps[y*step + (x + 1)];
    			p3 = ps[y*step + (x + 2)];
    			p4 = ps[(y + 1)*step + x];
    			p5 = ps[(y + 1)*step + (x + 1)];
    			p6 = ps[(y + 1)*step + (x + 2)];
    			p7 = ps[(y + 2)*step + x];
    			p8 = ps[(y + 2)*step + (x + 1)];
    			p9 = ps[(y + 2)*step + (x + 2)];//得到(i+1,j+1)周围九个点的灰度值
    			a = fabs(float(-5 * p1 - 5 * p2 - 5 * p3 + 3 * p4 + 3 * p6 + 3 * p7 + 3 * p8 + 3 * p9));    //计算4个方向的梯度值
    			b = fabs(float(3 * p1 - 5 * p2 - 5 * p3 + 3 * p4 - 5 * p6 + 3 * p7 + 3 * p8 + 3 * p9));
    			c = fabs(float(3 * p1 + 3 * p2 - 5 * p3 + 3 * p4 - 5 * p6 + 3 * p7 + 3 * p8 - 5 * p9));
    			d = fabs(float(3 * p1 + 3 * p2 + 3 * p3 + 3 * p4 - 5 * p6 + 3 * p7 - 5 * p8 - 5 * p9));
    			a = (a>b) ? a : b;                                         //取各个方向上的最大值作为边缘强度
    			a = (a>c) ? a : c;
    			a = (a>d) ? a : d;
    			pd[(y + 1)*step + (x + 1)] = a;
    		}
    	}
    	cvNormalize(dst, dst, 0, 255, CV_MINMAX); //归一化处理
    
    	cvNamedWindow("krisch", 0);      /* 定义一个窗口名为src的显示窗口 */
    	cvShowImage("krisch", dst);    /* 在src窗口中,显示src指针所指的图像 */
    	cvWaitKey(0);                      /* 无限等待,即图像总显示 */
    	cvDestroyAllWindows();   /* 销毁窗口 */
    	cvReleaseImage(&dst);
    	cvReleaseImage(&src);
    }
    

    效果:
    这里写图片描述

    6.Prewitt算子
    Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。

    实现代码

    /************************************************************
    *  边缘检测算法函数之Prewitt算子【在主函数main中调用即可】
    *  使用说明:
    *
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include <opencv2/highgui/highgui.hpp>  
    #include "cv.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <cmath>
    #include <cxcore.h>
    
    using namespace cv;
    using namespace std;
    
    void Prewitt(char *path)
    {
    	//-------prewitt算子 适用灰度图 ----
    	IplImage *src = cvLoadImage(path, -1);
    	if (!src)
    		return;
    	IplImage *gray = cvCreateImage(cvGetSize(src), 8, 1);
    	if (src->nChannels == 1)
    	{
    		//复制
    		cvCopy(src, gray);
    	}
    	else
    	{
    		//色彩空间转换,转换类型为CV_BGR2GRAY
    		cvCvtColor(src, gray, CV_BGR2GRAY);
    	}
    	IplImage *dst = NULL;
    	dst = cvCreateImage(cvGetSize(gray), 8, 1);
    	//定义prewitt算子的模板
    	float prewittx[9] =
    	{
    		-1, 0, 1,
    		-1, 0, 1,
    		-1, 0, 1
    	};
    	float prewitty[9] =
    	{
    		1, 1, 1,
    		0, 0, 0,
    		-1, -1, -1
    	};
    	CvMat px;
    	px = cvMat(3, 3, CV_32F, prewittx);
    	CvMat py;
    	py = cvMat(3, 3, CV_32F, prewitty);
    
    	//为输出图像申请空间
    	IplImage *dstx = cvCreateImage(cvGetSize(gray), 8, 1);
    	IplImage *dsty = cvCreateImage(cvGetSize(gray), 8, 1);
    
    	//对图像使用模板,自动填充边界 cvCvtColor(src,gray,CV_RGB2GRAY);
    	cvFilter2D(gray, dstx, &px, cvPoint(-1, -1));
    	cvFilter2D(gray, dsty, &py, cvPoint(-1, -1));
    
    	//计算梯度,范数为2,注意学习指针的使用方法
    	int i, j, temp;
    	float tempx, tempy;  //定义为浮点型是为了避免sqrt函数引起歧义
    	uchar* ptrx = (uchar*)dstx->imageData;
    	uchar* ptry = (uchar*)dsty->imageData;
    	for (i = 0; i<src->width; i++)
    	{
    		for (j = 0; j<src->height; j++)
    		{
    			tempx = ptrx[i + j*dstx->widthStep];   //tempx,tempy表示的是指针所指向的像素
    			tempy = ptry[i + j*dsty->widthStep];
    			temp = (int)sqrt(tempx*tempx + tempy*tempy);
    			dst->imageData[i + j*dstx->widthStep] = temp;
    		}
    	}
    	cvReleaseImage(&dstx);
    	cvReleaseImage(&dsty);
    	cvNamedWindow("Original Image", 0);
    	cvShowImage("Original Image", src);
    	cvNamedWindow("Prewitt", 0);      /* 定义一个窗口名为src的显示窗口 */
    	cvShowImage("Prewitt", dst);    /* 在src窗口中,显示src指针所指的图像 */
    	cvWaitKey(0);                      /* 无限等待,即图像总显示 */
    	cvDestroyAllWindows();   /* 销毁窗口 */
    	cvReleaseImage(&dst);
    	cvReleaseImage(&src);
    	cvReleaseImage(&gray);
    }
    

    效果图
    这里写图片描述

    7.角点检测算法
    角点是图像很重要的特征,对图像图形的理解和分析有很重要的作用。
    目前的角点检测算法可归纳为3类:基于灰度图像的角点检测、基于二值图像的角点检测、基于轮廓曲线的角点检测。

    <1>SUSAN是Smith和Brady提出的一种图像处理方法,该算法是基于像素领域包含若干元素的近似圆形模板,对每个像素基于该模板领域的图像灰度计算角点响应函数(CRF)的数值,如果大于某阈值且为局部极大值,则认为该点为角点。角点的精度与圆形模板大小无关,圆形模板越大,检测的角点数越多,则计算量也越大,本文圆形模板包含37个元素,该近似圆形模板结构如图1所示。

    1)Susan角点检测实现代码

    /************************************************************
    *  边缘检测算法函数之Susan角点检测算子【在主函数main中调用即可】
    *  使用说明:
    *
    *
    *  @author zha_yongchun
    *  @version 2016.8.5.001
    *************************************************************/
    
    #include<iostream>  
    #include <opencv2/core/core.hpp>  
    #include <opencv2/highgui/highgui.hpp>  
    #include <opencv2/imgproc/imgproc.hpp> 
    
    using namespace cv;
    using namespace std;
    
    
    void Susan(char* path)
    {
    	int height, width, step, channels;
    	int i, j, k, same, max, min, thresh, sum;
    	uchar*data0, *data1;
    	//char *filename="result.bmp";
    	IplImage* Img, *nimg; //声明IplImage指针
    	//载入图像
    	Img = cvLoadImage(path, 0); //单通道形式加载
    	if (!Img)
    		return;
    	nimg = cvCreateImage(cvGetSize(Img), 8, 1);
    	height = Img->height;
    	width = Img->width;
    	step = Img->widthStep / sizeof(uchar);
    	channels = Img->nChannels;
    	data0 = (uchar*)Img->imageData;
    	data1 = (uchar*)nimg->imageData;
    
    	printf("Processing a %d X %d image with %d channels\n", width, height, channels);
    	int OffSetX[37] = { -1, 0, 1,
    		-2, -1, 0, 1, 2,
    		-3, -2, -1, 0, 1, 2, 3,
    		-3, -2, -1, 0, 1, 2, 3,
    		-3, -2, -1, 0, 1, 2, 3,
    		-2, -1, 0, 1, 2,
    		-1, 0, 1 };
    	int OffSetY[37] = { -3, -3, -3,
    		-2, -2, -2, -2, -2,
    		-1, -1, -1, -1, -1, -1, -1,
    		0, 0, 0, 0, 0, 0, 0,
    		1, 1, 1, 1, 1, 1, 1,
    		2, 2, 2, 2, 2,
    		3, 3, 3 };
    
    	max = min = data0[0];
    	//for(i=0;i<height;i++)
    	// for(j=0;j<width;j++)
    	//{
    	// if(data0[i*step+j]>max) max = data0[i*step+j];
    	//if(data0[i*step+j]<min)   min = data0[i*step+j];
    	//   }
    	for (i = 3; i<height - 3; i++)
    	for (j = 3; j<width - 3; j++)
    	{
    		same = 0; sum = 0;
    		for (k = 0; k<37; k++)
    		{
    			sum += data0[(i + OffSetY[k])*step + (j + OffSetX[k])];
    			thresh = sum / 37;
    			if (abs(data0[(i + OffSetY[k])*step + (j + OffSetX[k])] - data0[i*step + j]) <= thresh)
    				same++;
    			if (same<18)
    				data1[i*step + j] = 255;
    			else
    				data1[i*step + j] = 0;
    		}
    	}
    
    	cvNamedWindow("SUSAN", 0);      /* 定义一个窗口名为src的显示窗口 */
    	cvShowImage("SUSAN", nimg);    /* 在src窗口中,显示src指针所指的图像 */
    	cvWaitKey(0);                      /* 无限等待,即图像总显示 */
    	cvDestroyWindow("SUSAN");   /* 销毁窗口 */
    	cvReleaseImage(&nimg);
    
    }
    

    效果
    这里写图片描述

    以上叙述了关于图像检测过程中的去噪,增强和检测过程,也给出了实现的代码,为程序的统一可观性,博主用MFC实现了整个程序的界面操作。

    五、MFC实现
    1.框架搭建
    由以上讲解,图像检测的步骤,大致可分噪声种类确定,去除噪声,边缘增强及检测过程。基于这样的过程,此MFC程序通过菜单栏形式也将内容划分为了这样四个部分:
    加噪–>滤波–>增强–>检测
    这里写图片描述

    然后按照易于对比的原则,将窗口划分为五个主要部分,分别显示四个过程的实时图片和选择功能栏
    这里写图片描述

    接下来进行菜单功能的拓展
    文件
    这里写图片描述

    添加噪声
    这里写图片描述

    滤波
    这里写图片描述

    检测
    这里写图片描述

    完整程序界面
    这里写图片描述

    运行结果图
    这里写图片描述

    2.功能实现
    函数的功能实现主要包括了两个部分,其一是MFC界面实现,其二是模块功能代码,其一仅需要基本的MFC基础知识,在此不作解释,其二主要代码则在前文论及。程序源码可到该地址下载

    六、小结
    项目的完成少不了查阅大量的文献以及与他人合作,在此次完成的过程中一个人还是遇到了许多困扰,有一句话最重要:理论结合实践!

    在给出的MFC框架中,有几项功能仍未实现,目前仍在完善中,如有错误,恳请指正!


    项目代码github地址: https://github.com/yooongchun/EdgeDetection

    展开全文
  • 自适应含噪信号过零算法

    千次阅读 2014-09-11 16:58:32
    过零率常用于语音检测识别中,一般叫短时过零率更贴切些(指一段短时平稳信号才能计算过零率),简单有效,近期亦打算将这个简单的概念用于识别脚步声和卡车声(近似短时平稳)。过零率的定义计算一般通过下面的...

    转载请注明出处:http://xiahouzuoxin.github.io/notes/或http://blog.csdn.net/xiahouzuoxin

    本文讨论的是实际使用过程中计算过零率的一种自适应方法。过零率常用于语音检测识别中,一般叫短时过零率更贴切些(指一段短时平稳信号才能计算过零率),简单有效,近期亦打算将这个简单的概念用于识别脚步声和卡车声(近似短时平稳)。过零率的定义计算一般通过下面的表达式描述:

    过零率是对频率从时域进行的一种简单的度量,一般情况下,过零率越大频率近似越高,反正亦然,相关推倒可参考相关文献。

    自适应噪声阈值

    自然信号由于电路、环境引入的噪声会在0水平位置波动,直接按上式计算过零率,严重影响识别效果。因此,本文在计算过零率时,对信号的幅值进行阈值限定,阈值的计算方法是:

    其中F为阈值与峰峰值的系数因子,一般F在0.1~0.2之间,Vpp表示当前短时信号的峰峰值,THR(t)表示t时段的阈值。

    因此增加阈值判别后计算过零率的流程图为:

    过零率流程图

    对应的C程序为:

    
    /* signal thresh adaptive structure */
    struct st_zerorate_thr{
        uint32_t pre;
        uint32_t cur;
    };
    
    /*
     * @brief   
     *   Calculate short time zero cross rate. Short time means n, n often choose to
     *   be a frame(256,512 and so on)
     *
     *   The diffrence with upstairs is that this one consider the adaptive thresh 
     *   when checking the signal, which removes the influence of noise.
     * @inputs  
     *   x[] - input sound signal
     *   n   - size of a frame
     * @outputs 
     * @retval  
     *   zero cross rate in a frame length
     */
    uint16_t zero_rate(int16_t x[], int n, struct st_zerorate_thr thr)
    {
        int      i        = 1;   /* Init to 1 */
        uint16_t zero_cnt = 0;
        float    tmp      = 0;
        uint8_t  x_pre    = 0;
    
        while ( (x[i] < thr.cur) && (x[i] > -thr.cur) && (i<n) ) {
            i++;
        }
        x_pre = x[i++];
        while ((i < n) && ((x[i] > thr.cur) || (x[i] < -thr.cur)) ) {
            tmp   = x[i] * x_pre;
            if (tmp < 0) {
                zero_cnt = zero_cnt + 1;
            }
            x_pre = x[i];
            i++;
        }
    
        return zero_cnt;
    }

    上面代码定义了阈值结构体st_zerorate_thr,更新阈值的方法按(2)式执行,

    #define TH_FACTOR        (0.2f)   /* 0.1~0.2 */
    
    void zerorate_thr_update(struct st_zerorate_thr thr, uint32_t peak_value)
    { 
        thr.pre = thr.cur;
        thr.cur = (uint32_t)(((thr.pre + TH_FACTOR * peak_value) / 2) );
    }

    关于初始阈值的选择:

    改进:增加能量阈值的策略

    这时要考虑的情况有些复杂,除了噪声阈值外,还要考虑能量阈值(确定是否是信号段),如下图:

    signal

    上图为采集的地震信号(比如脚步声信号),只有有些数据才是我们想要分析的,因此可以通过能量对数据进行划分。为简单起见,直接通过信号的幅值对确定有效信号区域也是可以的。

    当大于某个固定的阈值energy_thr时,并持续一段时间时,认为信号进入有效区域,开始按“自适应噪声阈值”的方案进行计算过零率

    能量阈值一般都大于自适应噪声阈值,可以通过实验获得:

    1. 采集无信号时的背景噪声,计算峰峰值;

    2. 采集有目标时的信号,计算峰峰值

    在两者之间找到一条错误率最低的水平分界值,作为能量阈值。

    为简化程序的设计,本程序使用状态机的设计思想,2个状态:安静(无目标)状态、有目标状态。C程序上直接使用switch...case语句就可以了,对应的C程序如下:

    /*
     * @brief   
     *   Calculate short time zero cross rate. Short time means n, n often choose to
     *   be a frame(256,512 and so on)
     *
     *   The diffrence with upstairs is that this one consider the adaptive thresh 
     *   when checking the signal, which removes the influence of noise.
     * @inputs  
     *   x[] - input sound signal
     *   n   - size of a frame
     *   thr - threshold(Vp) for removing noise ripple
     *   energy_thr - threshold(Vp) for ensure wether is signal start or stop
     * @outputs 
     * @retval  
     *   zero cross rate in a frame length
     */
    uint16_t zero_rate(int16_t x[], uint32_t n, struct st_zerorate_thr thr, uint16_t energy_thr)
    {
        uint32_t i          = 0; 
        uint16_t zero_cnt   = 0;
        int16_t  x_pre      = 0;
        uint8_t  status     = 0;
        uint8_t  energy_cnt = 0;
    
    #define CONTINUOUS_BEGIN    (2)  // 持续大于能量阈值的点数,用于检测信号开始
    #define CONTINUOUS_END      (5)  // 持续小于能量阈值的点数,用于检测信号结尾
    
        for (i=0; i<n; i++) {
            switch(status) {
            case 0: // Slience or maybe signal
                if (abs(x[i]) > energy_thr) {
                    if (++energy_cnt >= CONTINUOUS_BEGIN) {
                        status = 1;
                        energy_cnt = 0;
                        x_pre = x[i];
                    } else {
                        // do nothing
                    }
                }
                break;
            case 1: // Signal
                if (abs(x[i]) > thr.cur) {
                    if ( (x[i] * x_pre) < 0) {
                        zero_cnt = zero_cnt + 1;
                    }
                    x_pre = x[i];
                    energy_cnt = 0;
                } else {
                    if (abs(x[i]) < energy_thr) {
                        if (++energy_cnt >= CONTINUOUS_END) {
                            status = 0;
                            energy_cnt = 0;
                        }
                    } else {
                        // do nothing
                    }
                }
                break;
            default:
                status = 0;
                break;
            }
        }
    
        return zero_cnt;
    }

    补充:测试效果及新方法提出

    好吧:结论只有一个:

    在含有低频噪声的环境,使用过零率是很难区分脚步声和卡车的。

    如下,是分别采集脚步声和卡车的图形:

    step car

    因为卡车的采集信号高频都载波到低频信号上了,而在未判断实际目标之前,是无法使用低通滤波进行滤波(可能滤掉脚步声信号)。

    综上,我看过很多的论文,大都提到使用过零率对脚步声了卡车进行识别,而且识别效果还不错,我不知他们的实验环境是什么样的,至少从上面的实验分析,还是有问题的。

    因此,提出新的特征,用于区分两类信号——数字化占空比。其过程是:设定一个阈值,从头到尾扫描一帧信号,大于阈值的点设为1,否则设为0,我称之为数字化过程,然后计算高电平(即1)占所有一帧(512点)的百分比,用该百分比作为脚步声和卡车的识别数学特征。好了,我们用数学表述得专业些:

    其中{x>=THR}表示序列中值大于THR的点数。

    测试结果:取THR=0.4*Vpp,则计算脚步信号的Dutycycle=4,而卡车信号的Dutycycle=113,差异非常明显。

    展开全文
  • 改进的过零检测法的matlab程序

    热门讨论 2009-07-29 14:26:55
    改进的过零检测法的matlab程序,可以克服传统过零检测法的缺点,提高精度。
  • 直线检测算法汇总

    万次阅读 多人点赞 2019-09-21 20:15:07
    目录1、场景需求2、Hough_line直线检测算法2.1 Hough_line实现步骤2.2 Hough_line代码实战2.3 效果展示与分析2.4 HoughP_line代码实战2.5 效果展示与分析3、LSD直线检测算法-[项目主页]...[论文链接]...
  • 边缘检测算法

    千次阅读 2018-03-11 21:22:28
    1.边缘定义及特点边缘是由灰阶等高线定义的,穿过等高线时,灰阶会迅速变化,沿着等高线走,...2.边缘检测的难点(1)数码化:图像的采样不可能使得整个边缘都落在像素边缘上,灰阶的变化可能跨越多个像素,形成带...
  • 目标检测算法评估

    千次阅读 2018-05-17 22:19:14
    本文是对论文《Object count/Area Graphs for the Evaluation of Object Detection and Segmentation Algorithms》的部分理解翻译,用于学习对文本检测算法的评估!!!  目标检测和分割算法的评估 1. 摘要  ...
  • Canny 边缘检测算法

    万次阅读 2018-10-13 18:44:12
    Canny:边缘检测算法:其对受白噪声影响的阶跃型边缘是最优的。 目的: 返回一个二值图像,非数值表示图像中边缘的存在,返回与边缘相关的尺度和方向信息 标准: 检测标准:不丢失重要的边缘,不应有虚假的...
  • 目标检测算法对比

    万次阅读 2018-04-14 21:49:58
    R-CNN。 来自 ICCV 2015,可以说是利用深度学习进行目标检测的开山之作。作者Ross Girshick多次在PASCAL VOC的目标检测竞赛中折桂,...包括本文在内的一系列目标检测算法:RCNN, Fast RCNN, Faster RCNN代表当下目...
  • 使用PyTorch从开始实现YOLO-V3目标检测算法 (一) 点击查看博客原文 标检测是深度学习近期发展过程中受益最多的领域。随着技术的进步,人们已经开发出了很多用于目标检测的算法,包括 YOLO、SSD、Mask RCNN 和 ...
  • 异常检测算法概述(全)

    万次阅读 2019-02-13 16:59:46
    异常检测算法概述(全) ​ ——序列数据异常检测 1、异常的一些概念及异常检测的挑战 2、异常检测问题的不同方面 3、基于分类的异常检测算法 4、基于最近邻的异常检测技术 5、基于聚类的异常检测技术 6、统计异常...
  • YOLO,是目前速度更快的物体检测算法之一。虽然它不再是最准确的物体检测算法,但当您需要实时检测时,它是一个非常好的选择,而不会损失太多的准确性。 Darknet-53 YOLO v2 使用自定义的深度架构 darknet-19,这是...
  • 常用的算法有迫ZF检测、均方误差MMSE、V-BLAST 检测和最大似然检测算法。在最优检测中的最大似然(ML)检测算法虽然性能是这几类中最好的,但其复杂度是随着天线数和信号调制阶数的逐渐的增加而成指数量级快速增加...
  • 异常行为检测算法Anomaly detection is a critical problem that has been researched within diverse research areas and application disciplines. This article aims to construct a structured and ...
  • 社区检测算法总结

    万次阅读 多人点赞 2019-05-06 09:43:18
    社区检测算法 April 26, 2019 1 社区检测 先来说说什么是社区发现吧,学术上的说法是:一个社区由一组连接紧密的结点组成, 同时这些结点与社区外部的结点连接稀疏,如下图所示。那么,社区发现就是在复杂网络中 ...
  • 使用PyTorch从开始实现YOLO-V3目标检测算法 (三) 点击查看博客原文 这是从开始实现YOLO v3检测器的教程的第3部分。第二部分中,我们实现了 YOLO 架构中使用的层。这部分,我们计划用 PyTorch 实现 YOLO 网络...
  • 使用pytorch从开始实现YOLO-V3目标检测算法 (二) 博客翻译 这是从开始实现YOLO v3检测器的教程的第2部分。在上一节中,我解释了YOLO是如何工作的,在这一节中,我们将在PyTorch中实现YOLO的图层。换句话说,这...
  • PCDet可以支持目前已有的绝大多数面向LiDAR点云的3D目标检测算法,包括voxel-based,point-based,point-voxel hybrid以及one-stage/two-stage等等3D目标检测算法。 2. PointPillars网络及工程概述 2.1 ...
  • 使用PyTorch从开始实现YOLO-V3目标检测算法 (四) 点击查看博客原文 这是从开始实现YOLO v3检测器的教程的第4部分,在上一部分中,我们实现了网络的前向传播。这部分,我们计划用 非极大值抑制进行置信度阈值...
  • 汇总|3D点云目标检测算法

    千次阅读 2020-02-15 21:26:19
    作者:Tom Hardy Date:2020-02-14 来源:汇总|3D点云目标检测算法
  • 写在前面的话:文章内容来源于但不限于网络、书籍、个人心得... 基于深度学习模型融合的工业产品(部件)工艺缺陷检测算法简述 1、序言 随着信息与智能化社会的到来,工业产品生产逐渐走向智能化生产,极大地提...
  • Log边缘检测算法

    万次阅读 2016-07-02 14:51:00
    当指定thresh为0时,输出图像具有闭合的轮廓,因为其中包含了输入图像中的所有交叉点。 ;color:#3333ff;">I=rgb2gray(imread('9.jpg')); subplot(121);imshow(I);title('原图'); BW=edge(I,'log'); subplot...
  • MATLAB Simulink 中的过零检测与代数环

    千次阅读 2020-12-02 21:02:57
    过零检测指的是在交流系统中,当波形从正半周向负半周转换时,经过零位时,系统作出的检测。可作开关电路或者频率检测。 2 MATLAB中的过零检测 当SIMULINK仿真一个动态系统的时候,其在每一个时间步使用过零检测技术...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 70,580
精华内容 28,232
关键字:

过零检测算法