《学习OpenCV3》第10章 滤波与卷积

  • 1. 预备知识
    • 1.1 滤波、核和卷积
    • 1.2 边界外推和边界处理
      • 1.2.1 自定义边框
      • 1.2.2 自定义外推
  • 2. 阈值化操作
    • 2.1 threshold
      • 2.1.1 函数介绍
      • 2.1.2 例程10-1 图像相加和阈值化操作
    • 2.2 Otsu算法
    • 2.3 自适应阈值
      • 2.3.1 adaptiveThreshold()
      • 2.3.2 例程10-3 自适应阈值代码
  • 3. 平滑
    • 3.1 简单模糊和方框型滤波器
      • 3.1.1 简单模糊
      • 3.1.2 方框型滤波器
    • 3.2 中值滤波器
    • 3.3 高斯滤波器
    • 3.4 双边滤波器
  • 4. 导数和梯度
    • 4.1 索贝尔导数
    • 4.2 Scharr滤波
    • 4.3 拉普拉斯变换
  • 5. 图像形态学
    • 5.1 膨胀和腐蚀
      • 5.1.1 原理和应用
      • 5.1.2 erode()和dilate()
    • 5.2 通用形态学函数
      • 5.2.1 morphologyEx()
      • 5.2.2 开操作和闭操作
      • 5.2.3 形态学梯度
      • 5.2.4 顶帽和黑帽
    • 5.3 自定义核
      • 5.3.1 getStructuringElement()
  • 6. 用任意线性滤波器做卷积
      • 6.1 分解卷积核
    • 6.2 用cv::filter2D()进行卷积
    • 6.3 通过cv::sepFilter2D使用可分核
    • 6.4 生成卷积核
      • 6.4.1 Sobel核和Scharr核
      • 6.4.2 高斯核

1. 预备知识

1.1 滤波、核和卷积

  • 滤波器 是一种由一幅图像 I(x,y) 根据像素点x,y附近的区域计算得到的一幅新图像 I’(x,y) 的算法。其中,模板规定了滤波器的形状以及这个区域内像素的值的组成规律,也称“滤波器”或“核”。

1.2 边界外推和边界处理

  • OpenCV中的滤波操作(如cv::blur(),cv::erode(),cv::dilate()等 )得到的输出图像与源图像的形状是一样的。为了实现这种效果,OpenCV采用的方法是在源图像周围添加虚拟像素。cv::blur() 函数实现了对图像每个像素与周围像素进行均值操作。

1.2.1 自定义边框

  • 在处理图像时,只要告诉调用的函数添加虚拟像素的规则,库函数就会自动创建虚拟像素。同样,为了阐明一个操作的意图,就要注意函数在创建虚拟像素时所采用的的方法。
  • cv::copyMakerBorder() 就是一个为图像创建边框的函数,通过制定两幅图像,第一幅是源图像,第二幅是扩充之后的图像,同时指明填充方法,这个函数就会将第一幅图像填补后的结果保存在第二幅图像中。
 void copyMakeBorder(InputArray src, OutputArray dst,int top, int bottom,int left, int right,int borderType, //像素填充的方式const Scalar& value = Scalar());
  • 边界类型
边框类型 效果
cv::BORDER_CONSTANT 复制指定的常量扩展边界
cv::BORDER_WRAP 复制对边的像素扩展边界
cv::BORDER_REPLICATE 复制边缘的像素扩展边界
cv::BORDER_REFLECT 通过镜像复制扩展边界
cv::BORDER_REFLECT_101 通过镜像复制扩展边界,边界像素除外
cv::BORDER_DEFAULT 默认为 cv::BORDER_REFLECT_101

1.2.2 自定义外推

  • 在某些情况下,我们需要计算某一特定像素所参考的像素的位置。比如,给定一幅宽为w、高为h的图像,我们需要知道用哪个像素为虚拟像素**(w+dx,h+dy)**赋值,计算这个结果的函数是 cv::borderInterpolate()
 int borderInterpolate(int p, //坐标int len, //长度(在关联方向上的图像的实际大小)int borderType //边界类型);
  • cv::borderInterpolate() 一次计算一个维度上的外推,举一个例子,我们可以在混合的边界条件下计算一个特定像素的值,在一个维度中使用** cv::BORDER_REFLECT_101 ,在另一个维度中使用cv::BORDER_WRAP样式**。
 float val = img.at<float>(cv::borderInterpolate(100, img.rows, BORDER_REFLECT_101),cv::borderInterpolate(100, img.rows, BORDER_WRAP));
  • 在OpenCV内部,这是一个经常使用的函数,比如cv::copyMakeBorder,也可以在自定义的算法中调用这个函数。

2. 阈值化操作

2.1 threshold

2.1.1 函数介绍

  • 根据个人喜好,可以把阈值化操作理解为一个用1×1的核进行卷积,对每个像素进行一次给线性操作。
 double threshold(InputArray src, OutputArray dst,double thresh, //阈值double maxval, //给定的最大值int type  //操作类型);
阈值类型 操作
cv::THRESH_BINARY DST=(SRC>thresh)?MAXVALUE:0
cv::THRESH_BINARY_INV DST=(SRC>thresh)?0:MAXVALUE
cv::THRESH_TRUNC DST=(SRC>thresh)?THRESH:SRC
cv::THRESH_TOZERO DST=(SRC>thresh)?SRC:0
cv::THRESH_TOZERO_INV DST=(SRC>thresh)?0:SRC

2.1.2 例程10-1 图像相加和阈值化操作

// Example10_1.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <opencv2\opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;/**********将一幅图像的三个通道相加并将像素值限制在100以内
**/void sum_rgb(const Mat& src, Mat& dst)
{vector<Mat> planes;split(src, planes);Mat b = planes[0], g = planes[1], r = planes[2], s;//我们没有直接将数据相加并存入一个8位的数组(这可能会引起越界)//而是将三个通道取相同权值后进行相加然后截断大于100的值addWeighted(r, 1. / 3, g, 1. / 3, 0.0, s);addWeighted(s, 1., b, 1. / 3, 0.0, s);threshold(s, dst, 100, 100, THRESH_TRUNC);
}/*****************组合和阈值图像平面的替代方法
*/
void sum_rgb2(const Mat& src, Mat& dst)
{vector<Mat> planes;split(src, planes);Mat b = planes[0], g = planes[1], r = planes[2];// accumulate可以将8位整型的图像累加到一幅浮点型的图像中Mat s = Mat::zeros(b.size(), CV_32F);accumulate(b, s);accumulate(g, s);accumulate(r, s);threshold(src, s, 100, 100, THRESH_TRUNC);s.convertTo(dst, b.type());
}int main()
{Mat src = imread("./faces.png"), dst;if (src.empty())cout << "无法打开图像" << endl;sum_rgb(src, dst);imshow("src", src);imshow("dst", dst);Mat dst2;sum_rgb(src, dst2);imshow("dst2", dst2);waitKey(0);return 0;
}

2.2 Otsu算法

  • threshold()也可以自动决定最优的阈值,你只需对参数thresh传递值cv::THRESH_OTSU即可。
  • OTSU算法就是遍历所有可能的阈值,然后对每个阈值结果的两类像素计算方差(即低于阈值和高于阈值的两类像素)。
  • 这种方法不管是最小方差还是最大方差,耗费的时间都一样。原因是需要遍历所有可能的阈值,这不是一个相对高效的过程。

2.3 自适应阈值

2.3.1 adaptiveThreshold()

 void adaptiveThreshold(InputArray src, OutputArray dst,double maxValue, //最大值int adaptiveMethod, //支持两种最适应阈值方法int thresholdType, //操作类型int blockSize,  double C);
  • 下面两种方法都是诸葛像素的计算自适应阈值T(x,y),方法是通过计算每个像素位置周围的b×b区域的加权平均值,然后减去常数C,其中bblockSize给定。
  • cv::ADAPTIVE_THRESH_MEAN_C,均值时取得权值是想等的;
  • cv::ADAPTIVE_THRESH_GAUSSIAN_C,(x,y)周围的像素的权值则根据其到中心点的距离通过高斯方程得到;
  • 阈值在整个过程中自动产生变化
  • 当图像中出现比较大的明暗差异时,自适应阈值非常有效。
  • 这个函数仅处理单通道8位浮点型图像,并且要求源图像和目标图像不同。

2.3.2 例程10-3 自适应阈值代码

// Example10_3.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include <opencv2\opencv.hpp>
using namespace cv;int main()
{Mat srcImage = imread("./fruits.jpg", IMREAD_GRAYSCALE);Mat mat1, mat2;threshold(srcImage, mat1, 100, 254, THRESH_BINARY);adaptiveThreshold(srcImage, mat2, 100, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 15, 10);imshow("src", srcImage);imshow("1", mat1);imshow("2", mat2);waitKey(0);return 0;
}

3. 平滑

  • 平滑图像的目的通常是为了减少噪声和伪影,在降低分辨率的时候,平滑也十分重要。

3.1 简单模糊和方框型滤波器

3.1.1 简单模糊

 void blur(InputArray src, OutputArray dst,Size ksize,  Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT //边缘像素的平滑方式);
  • blur() 实现了简单模糊,目标图像中的每个值都是源图像中相应位置一个核中像素的平均值。
  • ksize : Kernal size 核尺寸。
  • anchor : 指定计算时核与源图像的对齐方式,默认情况为 cv::Point(-1,-1),表示核相对滤波器居中。
  • 如果源图像是一幅多通道图像,则分别对每个通道进行计算。

3.1.2 方框型滤波器

 void boxFilter(InputArray src,OutputArray dst,int ddepth,Size ksize,Point anchor = Point(-1, -1),bool normalize = true,  //是否归一化int borderType = BORDER_DEFAULT);
  • 方框滤波器是矩形的,滤波器中所有的值K都相等。
  • 通常所有的值K都为11/A,A是滤波器的面积。为 1/A 时称为归一化方框型滤波器
  • boxFilter() 是一种一般化的形式,而 blur() 是一种特殊化的形式。
  • 两者之间根本的区别是前者可以以归一化形式调用,并且输出图像深度可以控制(**blur()**输出的深度与源图像保持一致)。
  • 假如变量ddepth设为 -1 ,目标图像的深度将与源图像保持一致;否则可以设置为其他任意一种深度,如CV_32F

3.2 中值滤波器

 void medianBlur(InputArray src,OutputArray dst, int ksize);
  • 中值滤波器将每个像素替换为围绕这个像素的矩形邻域内的中值或“中值”像素(相对于平均像素)。
  • 中值滤波对有比较大的孤立的异常值(比如数字影像中的拍摄噪声)非常敏感。
  • 少量具有较大偏差的点也会严重影响得到均值滤波,而中值滤波可以采用取中间点的方式消除异常值的影响。
  • 中值滤波是一种非线性核。

3.3 高斯滤波器

void GaussianBlur(InputArray src, OutputArray dst,Size ksize,double sigmaX,double sigmaY = 0,int borderType = BORDER_DEFAULT);
  • 高斯滤波器是最有用的一种滤波器,它对输入数组进行规范化的高斯核滤波,然后输出目标数组。
  • 对于高斯滤波器,ksize指定滤波器核的宽度和高度,sigmaX表示高斯核在x方向上的sigma值。如果只给定了x,同时y设为0,那么y将会与x相等;
  • OpenCV为常用的内核提供性能上的优化。3×35×57×7的标准sigma核(sigmaX=0)比其他核性能更优。

3.4 双边滤波器

 void bilateralFilter(InputArray src, OutputArray dst,int d, //像素邻域的直径 对算法效率影响很大,视频处理一般不超过5,你可以将其设为-1,函数将自动为图像设计sigmaSpace的量double sigmaColor,  //颜色空间滤波器的sigma值和sigmaColor,其与高斯滤波器中的参数sigma相似double sigmaSpace, //坐标空间中滤波器的sigma值sigmaSpace。sigmaColor越大,平滑是所包括的强度(色彩)越大int borderType = BORDER_DEFAULT);
  • 双边滤波器是一种比较大的图像分析算子,也就是边缘保持平滑。
  • 高斯模糊的过程是减缓像素在空间上的变化,因此与邻域的关系紧密,而随机噪声在像素间的变化幅度又会非常的大(即噪声不是空间相关的)。基于这种前提高斯平滑很好地减弱了噪声并且保留了小信号。但是这种方式破坏了边缘信息,最终结果是高斯模糊把边缘也模糊了。
  • 相似于高斯平滑,双边滤波对每个像素及其区域内的像素进行了加权平均。其权重由两部分组成:第一部分同高斯平滑;第二部分也是高斯权重,不同的是它不是基于空间距离,而是彩色强度差计算而来,在过通道(彩色)图像上强度差由各分量的加权累加代替。
  • 可以把双边滤波当做是高斯平滑,只是相似程度更高的像素权值更高,边缘更明显,对比度更高。双边滤波的效果就是将源图像变成一幅水彩画,这种想过在多次迭代后更见显著,因此这种方法在图像分割领域十分有用。

4. 导数和梯度

4.1 索贝尔导数

 void Sobel(InputArray src, OutputArray dst, int ddepth, //目标图像的深度或类型,例如src是一幅8位图像,那么dst至少需要CV_16S深度保证不出现溢出int dx, //求导顺序   0 表示在这个方向不求导int dy, //求导顺序   0 表示在这个方向不求导int ksize = 3, //奇数 > 1才有意义  表示调用的滤波器的宽和高,目前最大支持到31double scale = 1, //缩放因子  double delta = 0, //偏移因子   int borderType = BORDER_DEFAULT);
  • 表示微分最常用的算子是Sobel,它可以实现任意阶导数和混合偏导数。
  • Sobel算子有一个好处就是可以将核定义为各种大小,并且可以快速、迭代式地构造这些核。
  • 大的核可以更好的近似导数,因为可以消除噪声影响。不过。假如导数在空间上变化剧烈,核太大会使结果发生偏差。
  • Sobel不是真正的导数,因为它定义在离散空间上。它实际上是一个多项式,在x方向上进行二阶Sobel运算表示的并不是二阶导数,而是对抛物线函数的局部拟合。这也说明了为什么要使用一个更大的核,更大的核拟合了更多的像素。

4.2 Scharr滤波

  • Sobel算子的缺点是核比较小的时候准确度不高。对于大型的核,近似过程使用了较多的点,因此精度问题不太显著。
  • 对于3×3Sobel滤波器,梯度角距离水平或垂直方向越远,误差越明显。
  • 调用Sobel时设置ksizecv::SCHARR,即可消除3×3这样小但是快的Sobel导数滤波器所带来的误差。Scharr同样很快,但是精度更高。

4.3 拉普拉斯变换

 void Laplacian(InputArray src,OutputArray dst, int ddepth,int ksize = 1, double scale = 1,double delta = 0,int borderType = BORDER_DEFAULT);
  • Laplacian() 可以用于各种场景处理,一种常见的应用就是匹配斑点
  • Laplacian() 就是图像在x, y轴方向上的导数之和,这意味着一个被包围的点或小斑点(比ksize小)处的值将会变得很大。相反,被较小值包围的点或小斑点处的的值将会在负方向上变得很大。
  • 因此,Laplacian同样可以用于边缘检测。

5. 图像形态学

5.1 膨胀和腐蚀

5.1.1 原理和应用

  • 膨胀腐蚀是最基础的形态学变换,它们可以应用在消除噪声、元素分割和连接上面。
  • 膨胀是一种卷积操作,它将目标像素的值替换为卷积核覆盖区域的局部最大值。这是一个非线性核,通常膨胀采用的核是一个四边形或圆形的实心核,其锚点在中心。膨胀的作用是使图中填充区域生长。
  • 腐蚀是与膨胀相反的操作,腐蚀操作计算的是核覆盖范围内的局部最小值。
  • 图像的形态学操作通常在阈值化后的布尔图像上进行,不过由于膨胀和腐蚀知识最大和最小操作,因此形态学操作也可以在强度图像上进行。
  • 总的来说,膨胀扩张了明亮区域,腐蚀缩减了明亮区域;膨胀填充凹面,腐蚀消除凸起。
  • 腐蚀操作通常用于消除图中斑点一样的噪声,原理是斑点经过腐蚀后会消失,而大的可见区域不会受影响。
  • 膨胀操作通常用于发现连通分支(大的颜色或强度相似像素的离散区域)。膨胀出现的原因是,在很多情况下,由于噪声或者阴影等因素,大的区域可能被分解成多个分支。一些细微的膨胀会导致这些分支相遇并组合成一个整体。
  • 另外需要注意的是:如果不是布尔类型图像的话,最小化(腐蚀)和最大化(膨胀)操作就不是那么有用了。

5.1.2 erode()和dilate()

 //腐蚀void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor = Point(-1, -1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue());//膨胀void dilate(InputArray src, OutputArray dst, InputArray kernel,Point anchor = Point(-1, -1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue());
  • erode()dilate() 都需要传入源图像和目标图像,并且都支持就地调用(源图像和目标图像是同一幅图像)。
  • kernel:这个参数是,你可以传入一个为被初始化的cv::Mat(),不过这会导致函数使用默认的锚点在中心的3×3核
  • iterations:这个参数是迭代次数,如果不为1,将会自动重复多次调用这个函数。

5.2 通用形态学函数

  • 当处理的对象是二值图像和像素只可能是开(>0)或关(=0)的图像掩膜时,基本的腐蚀和膨胀操作就够用了。需要对灰度图或者彩色图进行处理时,一些其他的操作就非常有用,它就是morphologyEx()

5.2.1 morphologyEx()

 void morphologyEx(InputArray src,OutputArray dst,int op, InputArray kernel,Point anchor = Point(-1, -1), int iterations = 1,int borderType = BORDER_CONSTANT,const Scalar& borderValue = morphologyDefaultBorderValue());
操作值 形态学操作 是否需要临时图像
MOP_OPEN 开操作
MOP_CLOSE 闭操作
MOP_GRADIENTN 形态学梯度 总是需要
MOP_TOPHAT 顶帽操作 就地调用需要(src = dst)
MOP_BALCKHAT 黑帽操作 就地调用需要(src = dst)

5.2.2 开操作和闭操作

  • 开操作闭操作实际上就是腐蚀和膨胀的简单组合。
  • 开操作是先腐蚀后膨胀,常用于对二值图像中的区域进行计数。
  • 闭操作是先膨胀后腐蚀,作用于复杂连通分支算法中减少无用或噪声驱动的片段。对于连通分支,通常先进行腐蚀或闭操作消除噪声,然后通过开操作连接相互靠近的大型区域。
  • 尽管开和闭操作的效果与腐蚀相近,但这些新操作在保持连通域的精度上更加可靠。

5.2.3 形态学梯度

  • 形态学梯度 是 膨胀操作的结果(扩张亮域)减 腐蚀操作的结果(缩减亮域) ,这就是边缘。
  • 对于灰度图,其结果就是计算明暗变换的趋势。形态学梯度通常用于显示明亮区域的边界,然后便可以将他们看做目标或者目标的部分。用扩张的图像减去了收缩的图像,如此一来就找出了完整的边界。这与计算梯度不同,它不会关注某一个物体的周围。

5.2.4 顶帽和黑帽

  • 这两种操作分别用于显示与其邻域相比更亮或更暗的部分。当试图根据物体的亮度变化分离依附于物体的某些部分时,就会用到这些方法。
  • 顶帽作用源图像减去其开操作后的图像。开操作的效果是放大裂缝和局部小洞。因此用源图像减去开操作后的图像得到了比源图像更亮的环绕部分。
  • 黑帽操作显示的是比源图像更暗的环绕部分。

5.3 自定义核

5.3.1 getStructuringElement()

  • 你可以创建任意一种你需要的构造元素用于 erode()、dilate()、morphologyEx()
 Mat getStructuringElement(int shape, //控制构造元素的基本形状Size ksize, //大小Point anchor = Point(-1, -1)  //锚点);
形状值 元素 描述
MORPH_RECT 矩形 Ei,j = 1, 所有的 i,j
MORPH_ELLIPSE 椭圆 ksize.width 和 ksize.height 为两个半径做椭圆
MORPH_CROSS 交叉 Ei,j = 1, 当 i == anchor.y 或 j == anchor.x

6. 用任意线性滤波器做卷积

6.1 分解卷积核

  • 一个可分核可以理解成两个一维核,在卷积时先调用x内核,然后调用y内核。两个矩阵进行卷积所产生的消耗可以用两个矩阵的面积的积来估算,如此一来,用n×n的核对面积为A的图像进行卷积所需的时间是An2,但如果分解成 n×11×n 的两个核,那么代价就是 An +An = 2An ,因此分解卷积核可以提高卷积计算的效率。只要n不小于3,这种计算方式就能提高效率,并且随着n的增大,这种效益愈发明显。

6.2 用cv::filter2D()进行卷积

  • 对一幅图像进行卷积的操作时十分巨大的,至少从第一印象看操作数大概是图像中的像素数量乘以卷积核中的像素数,如此复杂的操作导致没人愿意通过使用for循环和一维指针去计算卷积。因此OpenCV为我们提供了filter2D()
 void filter2D(InputArray src,OutputArray dst, int ddepth,InputArray kernel, //核Point anchor = Point(-1, -1), //如果定义了锚点,那么核的大小可以是偶数,否则必须是奇数double delta = 0, //滤波的结果与源图像的偏移int borderType = BORDER_DEFAULT);

6.3 通过cv::sepFilter2D使用可分核

  • 当参与卷积的核是可分核时,那么现将其分解为两个一维核,然后传递到OpenCV中计算,会获得最佳的计算性能。
 void sepFilter2D(InputArray src, OutputArray dst, int ddepth,InputArray kernelX,  // n1 × 1核InputArray kernelY,  // 1 × n2核  n1和n2可以不相等Point anchor = Point(-1, -1),double delta = 0, int borderType = BORDER_DEFAULT);

6.4 生成卷积核

6.4.1 Sobel核和Scharr核

  • 导数滤波器的核实际上是通过**getDerivKernels()**生成的。
  • 导数核(Sobel核和Scharr核)是可以分解的。
  • 导数核永远都是正方形的,因此 ksize 是一个整数。
 void getDerivKernels(OutputArray kx, //1 × ksize 行向量OutputArray ky, //ksize × 1 列向量int dx,int dy,int ksize, //可以是1、3、5、7或cv::SCHARRbool normalize = false, //是否将核元素规范化,如果目标是浮点型图像,就应当设置为真int ktype = CV_32F);

6.4.2 高斯核

  • 高斯滤波器所使用的核由**getGaussianKernel()**生成。
  • 高斯核也是可分的。
 Mat getGaussianKernel(int ksize, //是奇数double sigma, //近似高斯分布的标准差int ktype = CV_64F);

《学习OpenCV3》第10章 滤波与卷积相关推荐

  1. c语言程序设计第四版乌云高娃,C语言程序设计教学课件作者第3版乌云高娃学习手册C语言程序设计教学课件作者第3版乌云高娃学习手册学习手册第10章文件及其应用课件.docx...

    C语言程序设计教学课件作者第3版乌云高娃学习手册C语言程序设计教学课件作者第3版乌云高娃学习手册学习手册第10章文件及其应用课件.docx 学习手册(1):文本文件的操作学习内容文本文件的操作学习目标 ...

  2. HTML5与CSS3基础教程第八版学习笔记7~10章

    第七章,CSS构造块 CSS里有控制基本格式的属性(font-size,color),有控制布局的属性(position,float),还有决定访问者打印时在哪里换页的打印控制元素.CSS还有很多控制 ...

  3. 江哥MySQL视频学习笔记--第10章 MySQL存储过程和函数70-MySQL-批量数据处理(掌握)

    需求: 往数据库里存储一万条数据 实现方案: 1.写一万条insert into语句 2.将insert into语句封装到存储过程或者函数中 将来怎么使用? 是配合其它SQL语句使用, 还是单独使用 ...

  4. 《学习OpenCV3(中文版)》图书目录

    计算机视觉是在图像处理的基础上发展起来的新兴学科.OpenCV是一个开源的计算机视觉库,是英特尔公司资助的两大图像处理利器之一.它为图像处理.模式识别.三维重建.物体跟踪.机器学习和线性代数提供了各种 ...

  5. Machine Learning with Python Cookbook 学习笔记 第9章

    Chapter 9. Dimensionality Reduction Using Feature Extraction 前言 本笔记是针对人工智能典型算法的课程中Machine Learning w ...

  6. 《学习OpenCV3》第2章 OpenCV初探

    学习OpenCV系列博客 上一章: OpenCV的下载和配置的文章已经很多了,所以我没写.就是懒! 下一章: 了解OpenCV的数据类型 <学习OpenCV3>第2章 OpenCV初探 1 ...

  7. 《学习OpenCV3》第11章 常见的图像变换

    <学习OpenCV3>第11章 常见的图像变换 1. 拉伸.收缩.扭曲和旋转 1.1 均匀调整 1.2 图像金字塔(Adelson84) 1.2.1 pyrDown() 1.2.2 bui ...

  8. 【深度学习(deep learning)】花书第10章 序列建模:循环和递归网络 读书笔记

    [深度学习(deep learning)]花书第10章 序列建模:循环和递归网络 读书笔记 第10章 序列建模:循环和递归网络 [深度学习(deep learning)]花书第10章 序列建模:循环和 ...

  9. 《学习OpenCV3》第3章 了解OpenCV的数据类型

    学习OpenCV系列博客 上一章: <学习OpenCV3>第2章 OpenCV初探 下一章: <学习OpenCV3>第4章 图像和大型数组类型(持续更新) <学习Open ...

最新文章

  1. try-catch-finally中return的执行情况
  2. cfa三级真题和mock_两年高分过CFA三级的女学霸:复习秘诀刷爆了朋友圈!
  3. pycharm中安装可以贴图片的Markdown插件
  4. JavaScript 中 JSON.parse()和JSON.stringify()
  5. android intent.putextras,关于android:如何使用putExtra()和getExtra()来表示字符串数据
  6. mybatis动态更新xml文件后热部署,不重启应用的方法
  7. java质因数算法_Java实现的质因数分解操作示例【基于递归算法】
  8. 几个不错的开源的.net界面控件[转贴]
  9. 160. Intersection of Two Linked Lists(剑指Offer-两个链表的第一个公共结点)
  10. ic卡消费管理系统_详述食堂消费系统的功能特点
  11. php自定义类生成lib,thinkphp引入自定义封装类
  12. 职称计算机考试f11,2016全国职称计算机考试PowerPoint单选试题3
  13. 网络收包LRO GRO测试总结
  14. 关于解决无线拨号(PPPOE)上网的若干问题(WISP)
  15. 吴晓波:谷歌亚马逊抖音拼多多,15年前就被他成功预言--长尾理论/推荐系统/数据和消费
  16. 2015年全国大学生电子设计竞赛专题系列之综合测评-Multisim使用技巧
  17. 干货 | 什么是ABCDE轮融资?
  18. QT从下载到安装的具体教程
  19. css解决图片缩小变模糊问题
  20. 2022-2027年中国煤矿安全设备行业市场全景评估及发展战略研究报告

热门文章

  1. SharePoint Web Service系列: Add或Update其他各种类型的项
  2. 在 Ubuntu 中更换字体
  3. 如何让Win7不再弹出升级Win10的提醒窗口
  4. Teraterm的Log设定
  5. 扫盲——敏捷开发 Agile development 之 Scrum开发
  6. 问题的提出方式。(【先】说出最关键的【结果】,然后再描述细节)
  7. Eclipse,工程builed失败的原因。
  8. 【Python-3.5】matplotlib绘制气温折线图
  9. 移动端常见兼容性问题及解决办法
  10. 【Android 异常】 Parcelable encountered IOException writing serializable object