图像滤波总结(面试经验总结)
目录
图像平滑处理,6种滤波总结的综合示例
【盒式滤波、均值滤波、高斯滤波、中值滤波、双边滤波导向滤波】
1-图像滤波
2-代码演示
3-显示结果
4-程序说明
5 角点检测(Harris,Fast,surf)
图像平滑处理,6种滤波总结的综合示例
【盒式滤波、均值滤波、高斯滤波、中值滤波、双边滤波导向滤波】
本文力求用最简洁的语言,详细的代码将此部分内容讲解清楚,但由于博主同样是刚刚接触OpenCV,或许表达上有些瑕疵,还望读者能够指教探讨,大家共同进步。
机器配置为:VS2017+opencv3.2.0+Win-64bit。
若本文能给读者带来一点点启示与帮助,我就很开心了。
====================分割线====================
1-图像滤波
- 1.图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。
- 2.消除图像中的噪声成分叫作图像的平滑化或滤波操作。信号或图像的能量大部分集中在幅度谱的低频和中频段是很常见的,而在较高频段,感兴趣的信息经常被噪声淹没。因此一个能降低高频成分幅度的滤波器就能够减弱噪声的影响。
- 3.平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑会使边缘信息损失的越大,从而使输出的图像变得模糊,因此需合理选择邻域的大小。
- 4.关于滤波器,一种形象的比喻法是:我们可以把滤波器想象成一个包含加权系数的窗口,当使用这个滤波器平滑处理图像时,就把这个窗口放到图像之上,透过这个窗口来看我们得到的图像。
- 滤波目的:
- 1、消除图像中混入的噪声。2、为图像识别抽取出图像特征。
滤波要求:
- 1、不能损坏图像轮廓及边缘 。2、图像视觉效果应当更好。
滤波器的种类有很多, 本文结合前几节的内容,写了个综合示例,包含6种滤波方法:
盒式滤波、平滑处理1线性滤波之——盒式滤波(方框滤波)
均值滤波、平滑处理2线性滤波之——均值滤波
高斯滤波、平滑处理3线性滤波之——高斯滤波
中值滤波、平滑处理4非线性滤波之——中值滤波
双边滤波、平滑处理5非线性滤波之——双边滤波
导向滤波、平滑处理6——引导滤波/导向滤波(Guided Filter)
其中阈值量可通过滑动条来调节,下面来看看程序是如何实现的。
2-代码演示
/* 功能:用滚动条来控制6种滤波方式的参数值。 盒式滤波、均值滤波、高斯滤波、中值滤波、双边滤波、导向滤波。
*/
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv; #define WINDOWNAME "【滤波处理结果窗口】" //---------------【全局变量声明部分】-------------------------
Mat g_srcIamge, g_dstImage1, g_dstImage2, g_dstImage3, g_dstImage4, g_dstImage5, g_dstImage6;
int g_nBoxFilterValue = 1;//盒式滤波内核值
int g_nMeanBlurValue = 1;//均值滤波内核值
int g_nGaussianBlurValue = 1;//高斯滤波内核值
int g_nMedianBlurValue = 1;//中值滤波内核值
int g_nBilateralFilterValue = 1;//双边滤波内核值
int g_nGuidedFilterValue = 1;//导向滤波内核值
const int g_nMaxVal = 20; //预设滑动条最大值
//--------------【全局函数声明部分】-------------------------
//轨迹条回调函数
static void on_BoxFilter(int, void*);//盒式滤波器
static void on_MeanBlur(int, void*);//均值滤波器
static void on_GaussianBlur(int, void*);//高斯滤波器
static void on_MedianBlur(int, void*);//中值滤波器
static void on_BilateralFilter(int, void*);//双边滤波器
static void on_GuidedFilter(int, void*);//导向滤波器
void guidedFilter(Mat &srcMat, Mat &guidedMat, Mat &dstImage, int radius, double eps);//导向滤波器 //----------------------------【主函数】---------------------------
int main()
{ //------------【1】读取源图像并检查图像是否读取成功------------ g_srcIamge = imread("D:\\OutPutResult\\ImageTest\\boatLong.jpg"); if (!g_srcIamge.data) { cout << "读取图片错误,请重新输入正确路径!\n"; system("pause"); return -1; } namedWindow("【源图像】", 1);//创建窗口 imshow("【源图像】", g_srcIamge);//显示窗口 //------------【2】在WINDOWNAME窗口上分别创建滤波6个滑动条------------ namedWindow(WINDOWNAME);//创建窗口 createTrackbar("方框滤波", WINDOWNAME, &g_nBoxFilterValue, g_nMaxVal, on_BoxFilter);//创建方框滤波轨迹条 on_BoxFilter(g_nBoxFilterValue, 0); //轨迹条的回调函数 createTrackbar("均值滤波", WINDOWNAME, &g_nMeanBlurValue, g_nMaxVal, on_MeanBlur);//创建均值滤波轨迹条 on_MeanBlur(g_nMeanBlurValue, 0); createTrackbar("高斯滤波", WINDOWNAME, &g_nGaussianBlurValue, g_nMaxVal, on_GaussianBlur);//创建高斯滤波轨迹条 on_GaussianBlur(g_nGaussianBlurValue, 0); createTrackbar("中值滤波", WINDOWNAME, &g_nMedianBlurValue, g_nMaxVal, on_MedianBlur);//创建中值滤波轨迹条 on_MedianBlur(g_nMedianBlurValue, 0); createTrackbar("双边滤波", WINDOWNAME, &g_nBilateralFilterValue, g_nMaxVal, on_BilateralFilter);//创建双边滤波轨迹条 on_BilateralFilter(g_nBilateralFilterValue, 0); createTrackbar("导向滤波", WINDOWNAME, &g_nGuidedFilterValue, g_nMaxVal, on_GuidedFilter);//创建导向滤波轨迹条 on_GuidedFilter(g_nGuidedFilterValue, 0); //------------【3】退出程序------------ cout << "\t按下'q'键,退出程序~!\n" << endl; while (char(waitKey(1)) != 'q'){} return 0;
} //----------------------【on_BoxFilter()函数】------------------------
static void on_BoxFilter(int, void*)
{ boxFilter(g_srcIamge, g_dstImage1, -1, Size(g_nBoxFilterValue * 2 + 1, g_nBoxFilterValue * 2 + 1)); cout << "\n当前为【盒式滤波】处理效果,其内核大小为:" << g_nBoxFilterValue * 2 + 1 << endl; imshow(WINDOWNAME, g_dstImage1);
}
//----------------------【on_MeanBlur()函数】------------------------
static void on_MeanBlur(int, void*)
{ blur(g_srcIamge, g_dstImage2, Size(g_nMeanBlurValue * 2 + 1, g_nMeanBlurValue * 2 + 1), Point(-1, -1)); cout << "\n当前为【均值滤波】处理效果,其内核大小为:" << g_nMeanBlurValue * 2 + 1 << endl; imshow(WINDOWNAME, g_dstImage2);
}
//----------------------【on_GaussianBlur()函数】------------------------
static void on_GaussianBlur(int, void*)
{ GaussianBlur(g_srcIamge, g_dstImage3, Size(g_nGaussianBlurValue * 2 + 1, g_nGaussianBlurValue * 2 + 1), 0, 0); cout << "\n当前为【高斯滤波】处理效果,其内核大小为:" << g_nGaussianBlurValue * 2 + 1 << endl; imshow(WINDOWNAME, g_dstImage3);
}
//----------------------【on_MedianBlur()函数】------------------------
static void on_MedianBlur(int, void*)
{ medianBlur(g_srcIamge, g_dstImage4, g_nMedianBlurValue * 2 + 1); cout << "\n当前为【中值滤波】处理效果,其内核大小为:" << g_nMedianBlurValue * 2 + 1 << endl; imshow(WINDOWNAME, g_dstImage4);
}
//----------------------【on_BilateralFilter()函数】------------------------
static void on_BilateralFilter(int, void*)
{ bilateralFilter(g_srcIamge, g_dstImage5, g_nBilateralFilterValue, g_nBilateralFilterValue * 2, g_nBilateralFilterValue / 2); cout << "\n当前为【双边滤波】处理效果,其内核大小为:" << g_nBilateralFilterValue << endl; imshow(WINDOWNAME, g_dstImage5);
}
//----------------------【on_GuidedFilter()函数】------------------------
static void on_GuidedFilter(int, void*)
{ vector<Mat> vSrcImage, vResultImage; //【1】对源图像进行通道分离,并对每个分通道进行导向滤波操作 split(g_srcIamge, vSrcImage); for (int i = 0; i < 3; i++) { Mat tempImage; vSrcImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0);//将分通道转换成浮点型数据 Mat cloneImage = tempImage.clone(); //将tempImage复制一份到cloneImage Mat resultImage; guidedFilter(tempImage, cloneImage, resultImage, g_nGuidedFilterValue * 2 + 1, 0.01);//对分通道分别进行导向滤波 vResultImage.push_back(resultImage);//将分通道导向滤波后的结果存放到vResultImage中 } //【2】将分通道导向滤波后结果合并 merge(vResultImage, g_dstImage6); cout << "\n当前处理为【导向滤波】,其内核大小为:" << g_nGuidedFilterValue * 2 + 1 << endl; imshow(WINDOWNAME, g_dstImage6);
} //-------------------【实现导向滤波器函数部分】-------------------------
void guidedFilter(Mat &srcMat, Mat &guidedMat, Mat &dstImage, int radius, double eps)
{ //------------【0】转换源图像信息,将输入扩展为64位浮点型,以便以后做乘法------------ srcMat.convertTo(srcMat, CV_64FC1); guidedMat.convertTo(guidedMat, CV_64FC1); //--------------【1】各种均值计算---------------------------------- Mat mean_p, mean_I, mean_Ip, mean_II; boxFilter(srcMat, mean_p, CV_64FC1, Size(radius, radius));//生成待滤波图像均值mean_p boxFilter(guidedMat, mean_I, CV_64FC1, Size(radius, radius));//生成导向图像均值mean_I boxFilter(srcMat.mul(guidedMat), mean_Ip, CV_64FC1, Size(radius, radius));//生成互相关均值mean_Ip boxFilter(guidedMat.mul(guidedMat), mean_II, CV_64FC1, Size(radius, radius));//生成导向图像自相关均值mean_II //--------------【2】计算相关系数,计算Ip的协方差cov和I的方差var------------------ Mat cov_Ip = mean_Ip - mean_I.mul(mean_p); Mat var_I = mean_II - mean_I.mul(mean_I); //---------------【3】计算参数系数a、b------------------- Mat a = cov_Ip / (var_I + eps); Mat b = mean_p - a.mul(mean_I); //--------------【4】计算系数a、b的均值----------------- Mat mean_a, mean_b; boxFilter(a, mean_a, CV_64FC1, Size(radius, radius)); boxFilter(b, mean_b, CV_64FC1, Size(radius, radius)); //---------------【5】生成输出矩阵------------------ dstImage = mean_a.mul(srcMat) + mean_b;
}
3-显示结果
原始图像窗口,如下图:
盒式滤波/方框滤波操作,如下图:
均值滤波操作,如下图:
高斯滤波操作,如下图:
中值滤波操作,如下图:
双边滤波操作,如下图:
导向滤波操作,如下图:
=====================分割线==================
4-程序说明
【滤波处理结果窗口】中显示的数值并非实际内核大小,真正内核大小还请看黑窗口的提示信息。
其中前五种滤波方式:盒式滤波、均值滤波、高斯滤波、中值滤波、双边滤波,OpenCV都已封装在函数里了,我们直接调用即可,而导向滤波,是需要自己编写,然后调用即可。
为了便于观察各种滤波方式的效果优缺点,我对原图进行了处理,左边的图像是添加了椒盐噪声,而右边的图像是添加了高斯噪声,同学们可以通过滑动条调节,试试看每种滤波方式对噪声的处理结果是如何情况。
====END===================
5 角点检测(Harris,Fast,surf)
前面分析了Sift算法的具体原理,就顺便想看看其他的角点检测算法,和对比。这些看完之后,相比sift的原理比较简单.
Harris:
这个算法通过两张图就看得很清楚了。将被检测点上的window移动一下,然后计算原来的window和移动之后的window对应位置像素差的平方和,如果变化不大说明这个点在物体内部,如果一个方向上变化大,另外一个方向上变化不大说明在边界上。如果任何方向上变化都很大说明这个点就是corner point。
但是这个方法效果不是很好,主要存在两方面的问题:
- .0-1window对噪声比较敏感
- window移动的方向太少,导致该算法对边缘敏感(准确的说是和window移动方向不一致的边缘)
harris(1988)harris(1988)年提出了改进方案。
- 将01window改成了Gaussian window,中心权重比较高,离中心越远权重越低。
- 使用泰勒展开考虑所有方向
通过泰勒展开可以将原window和shift之后的window对应位置像素差的平方和表示为移动方向*该点Hessian矩阵*移动方向。Hessian矩阵的较大特征值和对应特征向量分别表示变化最大方向和对应变化幅度。第二特征值和对应特征向量,表示和变化最大方向相垂直的方向以及该方向变化的幅度。如果最大特征值很小那么说明该点在物体内部;如果第一特征值很大,另外一个特征值接近零说明该点是一个edge point;如果两个特征值都远大于零说明该点是一个corner point。
Harris 为了简化计算提出了一个cornerness的量,越大越说明这个点越corner
角点计算数学原理:
基本数学公式如下:
其中W(x, y)表示移动窗口,I(x, y)表示像素灰度值强度,范围为0~255。根据泰勒级数,计算一阶到N阶的偏导数,最终得到一个Harris矩阵公式:
根据Harris的矩阵计算矩阵特征值,然后计算Harris角度响应值:
其中K为系数值,通常取值范围为0.04 ~ 0.06之间。
算法详细步骤
- 计算图像X方向与Y方向的一阶高斯偏导数Ix与Iy
- 根据第一步结果得到Ix^2 , Iy^2与Ix*Iy值
- 高斯模糊第二步三个值得到Sxx, Syy, Sxy
- 定义每个像素的Harris矩阵,计算出矩阵的两个特质值
- 计算出每个像素的R值
- 使用3X3或者5X5的窗口,实现非最大值压制
- 根据角度检测结果计算,最提取到的关键点以绿色标记,显示在原图上。
Fast角点检测:
Edward Rosten and TomDrummond 在2006年提出了一种简单快速的角点探测算法,该算法检测的角点定义为在像素点的周围邻域内有足够多的像素点与该点处于不同的区域。应用到灰度图像中,即有足够多的像素点的灰度值大于该点的灰度值或者小于该点的灰度值。
考虑下图中p点附近半径为3的圆环上的16个点,一个思路是若其中有连续的12个点的灰度值与p点的灰度值差别超过某一阈值,则可以认为p点为角点。
这一思路可以使用机器学习的方法进行加速。对同一类图像,例如同一场景的图像,可以在16个方向上进行训练,得到一棵决策树,从而在判定某一像素点是否为角点时,不再需要对所有方向进行检测,而只需要按照决策树指定的方向进行2-3次判定即可确定该点是否为角点。
常见的角点检测算法比较:
图像匹配能够应用的场合非常多,如目标跟踪,检测,识别,图像拼接等,而图像匹配最核心的技术就要属角点匹配了,所谓角点匹配是指寻找两幅图像之间的特征像素点的对应关系,从而确定两幅图像的位置关系。
角点匹配可以分为以下四个步骤:
- 提取检测子:在两张待匹配的图像中寻找那些最容易识别的像素点(角点),比如纹理丰富的物体边缘点等。
- 提取描述子:对于检测出的角点,用一些数学上的特征对其进行描述,如梯度直方图,局部随机二值特征等。
- 检测子和描述子的常用提取方法有:sift, harris, surf, fast, agast, brisk, freak, brisk,orb等。
- .匹配:通过各个角点的描述子来判断它们在两张图像中的对应关系。常用方法如 flann
- 去外点:去除错误匹配的外点,保留正确的内点。常用方法有Ransac, GTM。
我对上述这些常用的检测子和描述子的性能和速度做了一个测试,以找出其中性价比最好的组合(不考虑后两步)
图一
图二
上面两幅图是对上述部分检测子与描述子进行测试的结果。
其中图一和图二的x坐标表示不同的检测子与描述子的组合,从1到30分别对应
(surf、agast、brisk、fast、sift、orb)检测子与 (brisk、agast、surf、sift、orb)描述子的线性组合,如第四组表示surf检测子+sift描述子的组合。
图一和图二的y坐标表示一系列测试图片组,每组由两张图组成,这些图片都是质量较低的卫星地图,约2000*2000像素,每组的两张图片是由不同卫星对地面上同一地区进行拍摄的。它们之间的关系可能包含旋转,缩放,仿射变换,亮度变化,模糊,噪音等。从1到11的测试图片组大概对应着以下变换关系:
- 强烈亮度变化
- 旋转
- 仿射变换+尺度变化+旋转
- 仿射变换+亮度变化+旋转
- 仿射变换+噪音
- 模糊+亮度变化
- 旋转+噪音
- 旋转+尺度变化
- 亮度变化+旋转+模糊+噪音
- 亮度变化+旋转+尺度变化
- 亮度变化+旋转+尺度变化+强烈噪音。
图一的z坐标表示成功匹配的像素对的个数。图二的z坐标表示所需计算时间。
从测试结果来看,orb检测子与surf描述子配合的效果是最好的,不过速度也是最慢的。古老的sift和surf依然好用,速度也还是那么不给力。在不考虑旋转和仿射变换的情况下,fast是很不错的选择,在小幅旋转(20度内)的情况下,fast也还是有一定的容错能力的。在旋转变化和尺度变化方面,各家武功相差不多,虽然在理论上sift支持旋转变化,不过测试中它并没有表现出明显的优势。在噪音方面,sift和orb明显强于其它算法;在亮度变化和仿射变换上,orb的鲁棒性是最好的;综合比较,orb的性价比在此次华山论剑中略胜一筹。
下面两张图是上面11组图片的均值,从平均值来看,orb也是最好的
- :http://blog.csdn.net/ben_ben_niao/article/details/47446627
- :http://blog.csdn.net/sinat_36264666/article/details/77823400
- :https://blog.csdn.net/xw20084898/article/details/21822565
相关文章:

【小贴士】DEV 多行注释
多行注释 Ctrl / 取消多行注释 Ctrl ,

JSP+Servlet基础一
2019独角兽企业重金招聘Python工程师标准>>> JSP中的指令: 格式:<%指令的名称(page,taglib,include...) 属性属性值%> 指令中的page:用于整个页面,定义与页面相关的属性。page属性一共有13个。 1、常…

Chameleon跨端框架——壹个理想主义团队的开源作品
文章较长,信息量很大,请耐心阅读,必然有收获。下面正文开始~背景解决方案原理久经考验生产应用举例易用性好多态协议学习成本低渐进式接入业内对比后期规划理想主义历经近20个月打磨,滴滴跨端方案chameleon终于开源了github.com/d…

尺度空间理论与图像金字塔(二)
SIFT简介 整理一下方便阅读,作者写的东西摘自论文,在此感谢xiaowei等的贡献 DoG尺度空间构造(Scale-space extrema detection)http://blog.csdn.net/xiaowei_cqu/article/details/8067881关键点搜索与定位(Keypoint l…

仿桌面通知pnotify插件
在做网站的时候,alert弹出框是非常常见的情形。但是,有些情况下,弹框对用户来说是并不友好的。调研了几个其他的提示插件了,发现pnotify比较好用,可配置性也高。 使用示例: <!DOCTYPE html> <html…

【HDU】1305 Immediate Decodability(字典树:结构体数组,二维数组,链表/指针)
一、用的二维数组 #include <iostream> #include <cstring> #include <algorithm> using namespace std;const int maxn 100; int tr[maxn][2]; int mk[maxn]; int tot;void insert(string s) {int u 0;for(int i0;i<s.length();i){int x s[i]-0;if(tr…

Hyperledger Grid:一个用于分布式供应链解决方案的框架
Hyperledger在最近的一篇博文中发布了一个名为Hyperledger Grid的新项目。Grid是一个用于集成分布式账本技术(DLT)解决方案与供应链行业企业业务系统的框架。该项目提供了一个参考架构、通用数据模型和智能合约,所有这些都是基于开放标准和行…

尺度不变特征变换匹配算法详解
尺度不变特征变换匹配算法详解Scale Invariant Feature Transform(SIFT)Just For Fun对于初学者,从David G.Lowe的论文到实现,有许多鸿沟,本文帮你跨越。1、SIFT综述 尺度不变特征转换(Scale-invariant feature transform或SIFT)是一种电脑视…

【POJ】2503 Babelfish(字典树,map,指针)
一、map 输入时候的格式有点难想,还有一种想法是用gets读取,然后用sscanf分开,分别存到两个数组中去,再加入map中,但是这一种方法目前还没有实现。。 #include <iostream> #include <cstring> #include …

ndk-build: CreateProcess error=193
为什么80%的码农都做不了架构师?>>> 问题:ndk-build": CreateProcess error193 解决:该问题表明,调用了非windows程序,在build.xml中将ndk-build修改为ndk-build.cmd即可ant编译 转载于:https://my.o…

AI芯片初创公司单纯卖芯片还是捆绑算法的商业模式更好?...
雷锋网在《资本寒冬,这样的AI芯片公司2019年危矣》一文中已经提到,2019年的资本寒冬以及整个半导体行业的低迷,将会让那些没有技术独特性以及缺乏商业落地能力,且现金流控制不好的AI芯片公司面临巨大的挑战,甚至大概率…
VS2017配置OpenCV3.2+contrib3.2
VS2017配置OpenCV3.2contrib3.2前言opecv3.2opencv_contrib3.2模块都编译配置了在配置contrib之前,尝试直接配置OpeCV3.2-vc14,发现可以正常使用,也就是说官方包虽然只有vc14,但vs2017(vc15)也支持的很好。操作环境:WIN10 64bit &…

【ACM】二叉搜索树(Binary Search Tree /BS Tree) 小结
动态管理集合的数据结构——二叉搜索树 搜索树是一种可以进行插入,搜索,删除等操作的数据结构,可以用字典或者优先队列。 二叉排序树又称为二叉查找树,他或者为空树,或者是满足如下性质的二叉树。 (1&…

android安卓动态设置控件宽高
LayoutParams layoutParamsp_w_picpathView.getLayoutParams();layoutParams.width100;layoutParams.height200;p_w_picpathView.setLayoutParams(layoutParams);转载于:https://blog.51cto.com/11020803/1860242

《深入java虚拟机》读书笔记类加载
概述 类加载机制是指虚拟机将描述类的数据从Class文件中加载到内存,并进行数据验证、解析、初始化等过程,最后形成可以直接被虚拟机使用的java类型。在java语言中类的加载、链接、初始化等过程并不是在编译时期完成,而是在运行时期才进行的&a…
SLAM之特征匹配(一)————RANSAC-------OpenCV中findFundamentalMat函数使用的模型
目录 1.RANSAC原理 2. RANSAC算法步骤: 3. RANSAC源码解析 step one niters最初的值为2000,这就是初始时的RANSAC算法的循环次数,getSubset()函数是从一组对应的序列中随机的选出4组(因为要想计算出一…

I hope so 2016-Oct-10
2019独角兽企业重金招聘Python工程师标准>>> <I hope so> - A joke A: Do you think your son will forget all he learned at college? B: I hopse so. He certainly cant make a living by kissing girls! 转载于:https://my.oschina.net/u/553266/blog/75…
【Codeforces】158B-Taxi(贪心,怎么贪咧)
贪心 emmmm http://codeforces.com/contest/158/problem/B 题目大意:有四种旅客,四人一组,三人一组,两人一组,一人一组,一辆出租车最多可以坐四个人,并且一组里的人必须坐一辆车,…

90 后 CTO 创业 6 年,做了一件改变互联网的“小事”
TGO 鲲鹏会在武汉举行了一场线下分享活动 —— 冲破壁垒,打造精英的技术团队 。来自极验的 90 后 CTO 黄胜蓝分享了他的团队故事,以及在他看来一个创新团队应该具备的特征。极验 CTO \u0026 TGO 鲲鹏会会员黄胜蓝在现场进行分享 1. 创新:非典…
ORB特征(二)
为了满足实时性的要求,前面文章中介绍过(具体链接如下)快速提取特征点算法Fast,以及特征描述子Brief。本篇文章介绍的ORB算法结合了Fast和Brief的速度优势,并做了改进,且ORB是免费Ethan Rublee等人2011年在《ORB&#…

【POJ】2377 Bad Cowtractors(最大生成树)
简单题,模板题 求解最大生成树,提交一直WA,感觉没有什么问题啊,就是在求解最小生成树的模板基础上稍加修改即可,后来发现在输出a,b,c给map二维数组的时候还必须有判断条件,略为有点…
使用let替换var实现块级作用域的小发现
在讲述javascript没有块级作用域的时候都会提到一个非常经典的例子: var obj{name:helo,age:15 }; var arr[];for(var i0;i<5;i){arr[i]i;console.log(i);} console.log(arr); console.log(i);因为javascript没有块级作用域,所以控制台打印出来的结果…

windows系统下node、npm的安装和卸载
Greta有话说:我是在有道云笔记只弄个记录的笔记,粘贴过来之后,没有图片,我的笔记地址为: 有道云笔记,请点我 一、卸载 1、node.js、nvm、 npm (1)在cmd中输入where node找到node…
OpenCV4Android开发实录(2): 使用OpenCV3.4.1库实现人脸检测
OpenCV4Android开发实录(2): 使用OpenCV3.3.0库实现人脸检测 转载请声明出处:http://write.blog.csdn.net/postedit/78992490OpenCV4Android系列: 1. OpenCV4Android开发实录(1):移植OpenCV3.3.0库到Android Studio 2.OpenCV4Andr…
活动|跟着微软一起,拥抱开源吧!
由开源社主办的中国开源年会2016 (COSCon16 - China Open Source Conference 2016) 即将于今年10月15日-16日在北京举办。微软大咖将为您呈现区块链,容器,大数据,Xamarin等时下热点技术,参会者还可获取价值1,500 元 Azure 服务使用…

【HDU/算法】最短路问题 杭电OJ 2544 (Dijkstra,Dijkstra+priority_queue,Floyd,Bellman_ford,SPFA)
最短路径问题是图论中很重要的问题。 解决最短路径几个经典的算法 1、Dijkstra算法 单源最短路径(贪心),还有用 priority_queue 进行优化的 Dijkstra 算法。 2、bellman-ford算法 例题:【ACM】POJ 3259 Wormholes 允许负权边…

javaSE基础知识 1.5整数类型
整数的四种声明类型它们分别是,byte,short,int,long,这四种类型所占用的空间是不同的byte是占用1个字节,它的取值范围是 -128~127,short是占用2个字节,他的取值范围是-32768~32767&a…

源码分析-GLSurfaceView的内部实现
GLSurfaceView类是继承自SurfaceView的,并且实现了SurfaceHolder.Callback2接口。GLSurfaceView内部管理着一个surface,专门负责OpenGL渲染。GLSurfaceView内部通过GLThread和EGLHelper为我们完成了EGL环境渲染和渲染线程的创建及管理,使我们…

【POJ/算法】 3259 Wormholes(Bellman-Ford算法, SPFA ,FLoyd算法)
Bellman-Ford算法 Bellman-Ford算法的优点是可以发现负圈,缺点是时间复杂度比Dijkstra算法高。而SPFA算法是使用队列优化的Bellman-Ford版本,其在时间复杂度和编程难度上都比其他算法有优势。 Bellman-Ford算法流程分为三个阶段: 第一步&am…

进程控制概念简介 多线程上篇(三)
进程控制 进程的基本数据信息是操作系统控制管理进程的数据集合,这些信息就是用来控制进程的,此处我们说的进程控制就是进程的管理。比如进程有状态,那么进程的创建、终止,状态的切换,这都不是进程自主进行的ÿ…