OpenCV Basics - Image Processing

转自OpenCV入门教程

1. DFT - Discrete Fourier Transform

关于傅里叶分析的基本概念,这里有一篇精彩易懂的分析

对于图像的傅里叶变换,是将图像从空间域(可以理解为二维的时间域)转换为频率域。

在频域中,高频代表图像的细节、纹理信息;低频代表了大致的轮廓信息,可以在频率域中通过滤波得到需要的图像。

DFT-Example use opencv

2. Linear filter

  • 方框滤波,boxblur:kernel值均为1,有是否进行normalize的参数
  • 均值滤波,blur:是boxblur normalized后的特殊情况,去噪的同时很难保存图像细节
  • 高斯滤波,GaussianBlur:图像与正态分布做卷积

3. Non-linear filter

  • 中值滤波,medianBlur:去除散粒噪声,同时保存边缘细节,但是运行至少慢5x。对于细节(细、尖顶)多的图像不适合
  • 双边滤波,bilateralFilter:保护边缘,在平滑滤波时同时考虑了像素间的几何距离和色彩距离。采用高斯函数之后,当邻域像素点的欧式距离比较大,或是两个像素值相差比较大时,该像素点的权重就比较小,导致该像素点对滤波后的像素点的影响较小。分析
  • 上述5种Filter的例程

4. Morphology filter

  • 膨胀,dilate:高亮区域慢慢变大,求局部最大值
  • 腐蚀,erode:低亮区域逐渐变大,求局部最小值
  • 开运算,morphologyEx(MORPH_OPEN):先腐蚀(扩大黑)后膨胀(扩大亮),消除小物体,连接纤细处,平滑边界不明显改变物体大小
  • 闭运算,morphologyEx(MORPH_CLOSE):先膨胀(扩大亮)后腐蚀(扩大黑),能够排除小型黑洞
  • 形态学梯度,morphologyEx(MORPH_GRADIENT):膨胀图与腐蚀图做差,边缘突出出来,保留物体的边缘轮廓.例程
  • 顶帽,morphologyEx(MORPH_TOPHAT):原图与开运算之差,突出了比原来轮廓周围更明亮的地方,背景提取
  • 黑帽,morphologyEx(MORPH_BLACKHAT):原图与闭运算之差,突出比原来轮廓周围更暗的地方,保存轮廓
  • 上述几种形态学操作的例程

5. Floodfill

6. pyrUp/pyrDown/resize

7. threshold

8. Edge detection

  • Laplacian:二阶导数为0的点,是一阶导数的极值,也就是图像上的阶跃的位置,即边缘(对噪声敏感,会产生双边效果)
// 高斯滤波消除噪声
GaussianBlur( src, src, Size(3,3), 0, 0, BORDER_DEFAULT );
// 转换为灰度图
cvtColor( src, src_gray, COLOR_RGB2GRAY );
// 使用 Laplace函数
Laplacian( src_gray, dst, CV_16S, 3, 1, 0, BORDER_DEFAULT );
// 计算绝对值,并将结果转换成8位
convertScaleAbs( dst, abs_dst );
  • Sobel: Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度.
// 求 X方向梯度
Sobel( g_srcImage, g_sobelGradient_X, CV_16S, 1, 0, (2*g_sobelKernelSize+1), 1, 1, BORDER_DEFAULT );
convertScaleAbs( g_sobelGradient_X, g_sobelAbsGradient_X );//计算绝对值,并将结果转换成8位
// 求Y方向梯度
Sobel( g_srcImage, g_sobelGradient_Y, CV_16S, 0, 1, (2*g_sobelKernelSize+1), 1, 1, BORDER_DEFAULT );
convertScaleAbs( g_sobelGradient_Y, g_sobelAbsGradient_Y );//计算绝对值,并将结果转换成8位
// 合并梯度
addWeighted( g_sobelAbsGradient_X, 0.5, g_sobelAbsGradient_Y, 0.5, 0, g_dstImage );
  • Scharr滤波: 当内核大小为3时, Sobel内核可能产生比较明显的误差(Sobel算子只是求取了导数的近似值), 为解决这一问题,OpenCV提供了Scharr函数,但该函数仅作用于大小为3的内核。该函数的运算与Sobel函数一样快,但结果却更加精确,其内核是-3,+3, -10,+10
// 求 X方向梯度
Scharr(g_srcImage, g_scharrGradient_X, CV_16S, 1, 0, 1, 0, BORDER_DEFAULT);
convertScaleAbs(g_scharrGradient_X, g_scharrAbsGradient_X);  //计算绝对值,并将结果转换成8位
// 求Y方向梯度
Scharr(g_srcImage, g_scharrGradient_Y, CV_16S, 0, 1, 1, 0, BORDER_DEFAULT);
convertScaleAbs(g_scharrGradient_Y, g_scharrAbsGradient_Y);  //计算绝对值,并将结果转换成8位
// 合并梯度
addWeighted(g_scharrAbsGradient_X, 0.5, g_scharrAbsGradient_Y, 0.5, 0, g_dstImage);
  • Canny: 1.消除噪声 2.计算梯度幅值和方向(同Sobel) 3.非极大值抑制(只保留8邻域梯度方向的局部极大值) 4.滞后阈值(推荐的高低阈值比在2:1到3:1)
// 先使用 3x3内核来降噪
blur(g_srcGrayImage, g_cannyDetectedEdges, Size(3, 3));
// 运行我们的Canny算子, 输出二值图
Canny(g_cannyDetectedEdges, g_cannyDetectedEdges, g_cannyLowThreshold, g_cannyLowThreshold * 3, 3);

9. Hough transform

原理:对x,y平面上的直线y=kx+b,有无数的k,b的直线通过点(x0,y0)和(x1,y1),但是同时通过2点的只有一种k,b组合,也就是在k,b平面相交于一点,交点大于阈值即判定为直线

HoughLines:

//【2】进行边缘检测
Canny(srcImage, midImage, 50, 200, 3);  //进行一此canny边缘检测
//【3】进行霍夫线变换, 二值图上做
vector<Vec2f> lines;  //定义一个矢量结构lines用于存放得到的线段矢量集合
HoughLines(midImage, lines, 1, CV_PI / 180, g_nthreshold, 0, 0);
//【4】依次在图中绘制出每条线段
for (size_t i = 0; i < lines.size(); i++) {
  float rho = lines[i][0], theta = lines[i][1];
  Point pt1, pt2;
  double a = cos(theta), b = sin(theta);
  double x0 = a * rho, y0 = b * rho;
  pt1.x = cvRound(x0 + 1000 * (-b));
  pt1.y = cvRound(y0 + 1000 * (a));
  pt2.x = cvRound(x0 - 1000 * (-b));
  pt2.y = cvRound(y0 - 1000 * (a));
  line( srcImage, pt1, pt2, Scalar(55,100,195), 1, LINE_AA);
}

HoughLinesP: 区别是找segments, 输入也是要求二值图,概率hough变换速度,快些用的更多

vector<Vec4i> mylines;
HoughLinesP(midImage, mylines, 1, CV_PI / 180, g_nthreshold, 50, 10);
//循环遍历绘制每一条线段
for (size_t i = 0; i < mylines.size(); i++) {
  Vec4i l = mylines[i];
  line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23,180,55), 1, LINE_AA);
}

HoughCircles: 输入不同,灰度图即可,不需要是二值图

//【3】转为灰度图并进行图像平滑
cvtColor(srcImage, midImage, COLOR_BGR2GRAY);  //转化边缘检测后的图为灰度图
GaussianBlur(midImage, midImage, Size(9, 9), 2, 2);
//【4】进行霍夫圆变换
vector<Vec3f> circles;
HoughCircles(midImage, circles, HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
//【5】依次在图中绘制出圆
for (size_t i = 0; i < circles.size(); i++) {
  //参数定义
  Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
  int radius = cvRound(circles[i][2]);
  //绘制圆心
  circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);
  //绘制圆轮廓,有可能radius不准
  circle( srcImage, center, radius, Scalar(155,50,255), 3, 8, 0 );
}

10. remap

重映射Link,代表一种查询表

11. Affine transformation

getAffineTransform, warpAffine: 3个点的仿射变换 getPerspectiveTransform, warpPerspective:4个点的变换 findHomography:多个点的RANSAC拟合best transform 以上几点的区别Link, 例程

12. Contours

findContours: 二值图,查找contour,findContours and drawContours example, mode设置为CV_RETR_TREE,即可拿到contours之间的层次关系,可以参考 convexHull: 遍历contours,寻找凸包 example

boundingRect(): 返回正方向的Rect minAreaRect(): 返回RotatedRect, 面积最小的矩形,可以旋转的, 例程 minEnclosingCircle(): 对给定的 2D 点集,寻找最小面积的包围圆, 例程 fitEllipse(): 返回RotatedRect,内接椭圆,函数说明 approxPolyDP(): 用指定精度逼近多边形曲线 例程

13. Moments

图像的矩: 例程

  • 使用moments计算图像所有的矩(最高到3阶)
  • 使用contourArea计算轮廓面积
  • 使用arcLength计算轮廓或曲线长度

14. watershed

分水岭算法 例程

15. inpaint

图像修复算法 例程

Loading Disqus comments...
Table of Contents