11、霍夫线变换:使用OpenCV的以下函数 HoughLines 和 HoughLinesP

霍夫线变换是一种用来寻找直线的方法。 是用霍夫线变换之前, 首先要对图像进行边缘检测的处理,也即霍夫线变换的直接输入只能是边缘二值图像。

OpenCV实现了以下两种霍夫线变换:

  标准霍夫线变换

HoughLines

    

统计概率霍夫线变换

HoughLinesP

步骤:

Canny( );  边缘检测

cvtColor( );

vector<Vec2f> lines;

HoughLines( );

line( );

代码:

#include "opencv2/highgui/highgui.hpp"
 
 
#include "opencv2/imgproc/imgproc.hpp"
 
 
 
 
#include <iostream>
 
 
 
 
using namespace cv;
 
 
using namespace std;
 
 
 
 
void help()
 
 
{
 
 
 cout << "\nThis program demonstrates line finding with the Hough transform.\n"
 
 
  "Usage:\n"
 
 
  "./houghlines <image_name>, Default is pic1.jpg\n" << endl;
 
 
}
 
 
 
 
int main(int argc, char** argv)
 
 
{
 
 
 const char* filename = argc >= 2 ? argv[1] : "e:\\jay.jpg";
 
 
 
 
 Mat src = imread(filename, 0);
 
 
 if (src.empty())
 
 
 {
 
 
  help();
 
 
  cout << "can not open " << filename << endl;
 
 
  return -1;
 
 
 }
 
 
 
 
 Mat dst, cdst;
 
 
 Canny(src, dst, 50, 200, 3);
 
 
 cvtColor(dst, cdst, CV_GRAY2BGR);
 
 
 
 
#if 0
 
 
 vector<Vec2f> lines;
 
 
 HoughLines(dst, lines, 1, CV_PI / 180, 100, 0, 0);
 
 
 
 
 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(cdst, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);
 
 
 }
 
 
#else
 
 
 vector<Vec4i> lines;
 
 
 HoughLinesP(dst, lines, 1, CV_PI / 180, 50, 50, 10);
 
 
 for (size_t i = 0; i < lines.size(); i++)
 
 
 {
 
 
  Vec4i l = lines[i];
 
 
  line(cdst, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, CV_AA);
 
 
 }
 
 
#endif
 
 
 imshow("source", src);
 
 
 imshow("detected lines", cdst);
 
 
 
 
 waitKey();
 
 
 
 
 return 0;
 
 
}

      霍夫圆变换

HoughCircles

代码:

#include "opencv2/highgui/highgui.hpp" 

 

  #include "opencv2/imgproc/imgproc.hpp" 

 

  #include <iostream> 

 

  #include <stdio.h> 

 
 
 
 

  using namespace cv; 

 

  using namespace std; 

 
 
 
 

  /** @function main */ 

 

  int main(int argc, char** argv) 

 

  { 

 

   Mat src, src_gray; 

 
 
 
 

   /// Read the image 

 

   src = imread("e:\\test_circle.jpg"); 

 
 
 
 

   if (!src.data) 

 

   { 

 

    return -1; 

 

   } 

 
 
 
 

   /// Convert it to gray 

 

   cvtColor(src, src_gray, CV_BGR2GRAY); 

 
 
 
 

   /// Reduce the noise so we avoid false circle detection 

 

   GaussianBlur(src_gray, src_gray, Size(9, 9), 2, 2); 

 
 
 
 

   vector<Vec3f> circles; 

 
 
 
 

   /// Apply the Hough Transform to find the circles 

 

   HoughCircles(src_gray, circles, CV_HOUGH_GRADIENT, 1, src_gray.rows / 8, 200, 100, 0, 0); 

 
 
 
 

   /// Draw the circles detected 

 

   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 center 

 

    circle(src, center, 3, Scalar(0, 255, 0), -1, 8, 0); 

 

    // circle outline 

 

    circle(src, center, radius, Scalar(0, 0, 255), 3, 8, 0); 

 

   } 

 
 
 
 

   /// Show your results 

 

   namedWindow("Hough Circle Transform Demo", CV_WINDOW_AUTOSIZE); 

 

   imshow("Hough Circle Transform Demo", src); 

 
 
 
 

   waitKey(0); 

 

   return 0; 

 

  }

12、重映射

使用OpenCV函数  remap  来实现简单重映射.

remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0));

上面用到的重映射函数 remap. 参数说明:

src: 源图像

dst: 目标图像,与  src

map_x: x方向的映射参数. 它相当于方法 

map_y: y方向的映射参数. 注意  map_y 和  map_x 与  src

CV_INTER_LINEAR: 非整数像素坐标插值标志. 这里给出的是默认值(双线性插值).

BORDER_CONSTANT: 默认

更新重映射矩阵的 4种不同方法:

图像宽高缩小一半,并显示在中间:

所有成对的参数  处理后都符合:  和 

图像上下颠倒: 

图像左右颠倒: 

同时执行b和c的操作: 

代码:

#include "opencv2/highgui/highgui.hpp" 

 

  #include "opencv2/imgproc/imgproc.hpp" 

 

  #include <iostream> 

 

  #include <stdio.h> 

 
 

  using namespace cv; 

 
 

  /// Global variables 

 

  Mat src, dst; 

 

  Mat map_x, map_y; 

 

  char* remap_window = "Remap demo"; 

 

  int ind = 0; 

 
 

  /// Function Headers 

 

  void update_map(void); 

 
 

  /** 

 

  * @function main 

 

  */ 

 

  int main(int argc, char** argv) 

 

  { 

 

   /// Load the image 

 

   src = imread("e:\\jay.jpg"); 

 
 

   /// Create dst, map_x and map_y with the same size as src: 

 

   dst.create(src.size(), src.type()); 

 

   map_x.create(src.size(), CV_32FC1); 

 

   map_y.create(src.size(), CV_32FC1); 

 
 

   /// Create window 

 

   namedWindow(remap_window, CV_WINDOW_AUTOSIZE); 

 
 

   /// Loop 

 

   while (true) 

 

   { 

 

    /// Each 1 sec. Press ESC to exit the program 

 

    int c = waitKey(1000); 

 
 

    if ((char)c == 27) 

 

    { 

 

     break; 

 

    } 

 
 

    /// Update map_x & map_y. Then apply remap 

 

    update_map(); 

 

    remap(src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0, 0, 0)); 

 
 

    /// Display results 

 

    imshow(remap_window, dst); 

 

   } 

 

   return 0; 

 

  } 

 
 

  /** 

 

  * @function update_map 

 

  * @brief Fill the map_x and map_y matrices with 4 types of mappings 

 

  */ 

 

  void update_map(void) 

 

  { 

 

   ind = ind % 4; 

 
 

   for (int j = 0; j < src.rows; j++) 

 

   { 

 

    for (int i = 0; i < src.cols; i++) 

 

    { 

 

     switch (ind) 

 

     { 

 

     case 0: 

 

      if (i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75) 

 

      { 

 

       map_x.at<float>(j, i) = 2 * (i - src.cols*0.25) + 0.5; 

 

       map_y.at<float>(j, i) = 2 * (j - src.rows*0.25) + 0.5; 

 

      } 

 

      else 

 

      { 

 

       map_x.at<float>(j, i) = 0; 

 

       map_y.at<float>(j, i) = 0; 

 

      } 

 

      break; 

 

     case 1: 

 

      map_x.at<float>(j, i) = i; 

 

      map_y.at<float>(j, i) = src.rows - j; 

 

      break; 

 

     case 2: 

 

      map_x.at<float>(j, i) = src.cols - i; 

 

      map_y.at<float>(j, i) = j; 

 

      break; 

 

     case 3: 

 

      map_x.at<float>(j, i) = src.cols - i; 

 

      map_y.at<float>(j, i) = src.rows - j; 

 

      break; 

 

     } // end of switch 

 

    } 

 

   } 

 

   ind++; 

 

  }

13、仿射变换

warpAffine

getRotationMatrix2D 来获得一个 

原理、步骤:

   矩阵 ) , 对src通过warpAffine应用求得的仿射变换warp_mat即可得出变换后的图像warp_dst,然后rot_mat =getRotationMatrix2D(center, angle, scale)获得旋转矩阵rot_mat ,再通过 warpAffine函数实现旋转,得到先变换后旋转的图像warp_rotate_dst。

代码:

#include "opencv2/highgui/highgui.hpp" 

 

  #include "opencv2/imgproc/imgproc.hpp" 

 

  #include <iostream> 

 

  #include <stdio.h> 

 
 
 
 

  using namespace cv; 

 

  using namespace std; 

 
 
 
 

  /// 全局变量 

 

  char* source_window = "Source image"; 

 

  char* warp_window = "Warp"; 

 

  char* warp_rotate_window = "Warp + Rotate"; 

 
 
 
 

  /** @function main */ 

 

  int main(int argc, char** argv) 

 

  { 

 

   Point2f srcTri[3]; 

 

   Point2f dstTri[3]; 

 
 
 
 

   Mat rot_mat(2, 3, CV_32FC1); 

 

   Mat warp_mat(2, 3, CV_32FC1); 

 

   Mat src, warp_dst, warp_rotate_dst; 

 
 
 
 

   /// 加载源图像 

 

   src = imread("e:\\jay.jpg"); 

 
 
 
 

   /// 设置目标图像的大小和类型与源图像一致 

 

   warp_dst = Mat::zeros(src.rows, src.cols, src.type()); 

 
 
 
 

   /// 设置源图像和目标图像上的三组点以计算仿射变换 

 

   srcTri[0] = Point2f(0, 0); 

 

   srcTri[1] = Point2f(src.cols - 1, 0); 

 

   srcTri[2] = Point2f(0, src.rows - 1); 

 
 
 
 

   dstTri[0] = Point2f(src.cols*0.0, src.rows*0.33); 

 

   dstTri[1] = Point2f(src.cols*0.85, src.rows*0.25); 

 

   dstTri[2] = Point2f(src.cols*0.15, src.rows*0.7); 

 
 
 
 

   /// 求得仿射变换 

 

   warp_mat = getAffineTransform(srcTri, dstTri); 

 
 
 
 

   /// 对源图像应用上面求得的仿射变换 

 

   warpAffine(src, warp_dst, warp_mat, warp_dst.size()); 

 
 
 
 

   /** 对图像扭曲后再旋转 */ 

 
 
 
 

   /// 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵 

 

   Point center = Point(warp_dst.cols / 2, warp_dst.rows / 2); 

 

   double angle = -50.0; 

 

   double scale = 0.6; 

 
 
 
 

   /// 通过上面的旋转细节信息求得旋转矩阵 

 

   rot_mat = getRotationMatrix2D(center, angle, scale); 

 
 
 
 

   /// 旋转已扭曲图像 

 

   warpAffine(warp_dst, warp_rotate_dst, rot_mat, warp_dst.size()); 

 
 
 
 

   /// 显示结果 

 

   namedWindow(source_window, CV_WINDOW_AUTOSIZE); 

 

   imshow(source_window, src); 

 
 
 
 

   namedWindow(warp_window, CV_WINDOW_AUTOSIZE); 

 

   imshow(warp_window, warp_dst); 

 
 
 
 

   namedWindow(warp_rotate_window, CV_WINDOW_AUTOSIZE); 

 

   imshow(warp_rotate_window, warp_rotate_dst); 

 
 
 
 

   /// 等待用户按任意按键退出程序 

 

   waitKey(0); 

 
 
 
 

   return 0; 

 

  }

14、直方图均衡化

通过拉伸像素强度分布范围来增强图像对比度的一种方法。

 cvtColor(src, src, CV_BGR2GRAY);

  equalizeHist ( src , dst );

15、在图像中寻找轮廓

findContours

drawContours

16、计算物体的凸包

convexHull

17、创建包围轮廓的矩形和圆形边界框

boundingRect

minEnclosingCircle

18、为轮廓创建可倾斜的边界框和椭圆

minAreaRect

fitEllipse

19、轮廓矩

moments

contourArea

arcLength

***20、多边形测试

pointPolygonTest

21、直方图计算

split

calcHist

normalize

直方图的一些具体细节:

dims: 需要统计的特征的数目, 在上例中,  dims = 1

bins: 每个特征空间  子区段 的数目,在上例中,  bins = 16

range: 每个特征空间的取值范围,在上例中,  range = [0,255]

22、直方图对比

compareHist

    - 如何使用不同的对比标准来对直方图进行比较。

23、反向投影

calcBackProject

mixChannels

24、模板匹配

matchTemplate

minMaxLoc

25、为程序界面添加滑动条

createTrackbar

26、OpenCV的视频输入和相似度测量

    - 如何打开和读取视频流

    - 两种检查相似度的方法:PSNR和SSIM

27、用OpenCV创建视频

你可能已经不满足于读取视频,还想要将你产生的一系列结果保存到一个新建的视频文件中。使用OpenCV中的 VideoWriter

    - 如何用OpenCV创建一个视频文件

    - 用OpenCV能创建什么样的视频文件

    - 如何释放视频文件当中的某个颜色通道