当前位置:   article > 正文

opencv--使用opencv实现旋转角度的模板匹配_opencv 模板匹配 旋转

opencv 模板匹配 旋转

下面的例子是简单的使用opencv 实现的模板匹配流程,其中时间性能和精确度还需要调整,如果直接使用会出问题,所以这个只是例子,根据代码原理可以实现尺度变化的模板匹配和旋转尺度变化同时,具体根据实现的旋转代码进一步实现,但是就结果而言和halcon的模板匹配差距较大,性能更不行,因此仅供参考 ,同时本人整理了两个使用各种加速的高性能版本,有兴趣的可以下载看看

  1. struct MatchResult
  2. {
  3. std::vector<cv::Point> points;
  4. double angle;
  5. double score;
  6. MatchResult(std::vector<cv::Point> points, double angle, double score) :points(points), angle(angle), score(score) {};
  7. };
  8. //旋转图像
  9. cv::Mat ImageRotate(cv::Mat image, double angle)
  10. {
  11. cv::Mat newImg;
  12. cv::Point2f pt = cv::Point2f((float)image.cols / 2, (float)image.rows / 2);
  13. cv::Mat M = cv::getRotationMatrix2D(pt, angle, 1.0);
  14. cv::warpAffine(image, newImg, M, image.size());
  15. return newImg;
  16. }
  17. std::vector<cv::Point> GetRotatePoints(cv::Size size, double angle) {
  18. // 定义模板图像的中心点
  19. cv::Point2f center(size.width / 2.0, size.height / 2.0);
  20. // 计算旋转矩阵
  21. cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, 1.0);
  22. // 定义模板图像的四个顶点
  23. std::vector<cv::Point2f> srcPoints = {
  24. cv::Point2f(0, 0),
  25. cv::Point2f(size.width, 0),
  26. cv::Point2f(size.width, size.height),
  27. cv::Point2f(0, size.height)
  28. };
  29. // 存储旋转后的四个顶点
  30. std::vector<cv::Point2f> dstPoints(4);
  31. // 进行仿射变换
  32. cv::transform(srcPoints, dstPoints, rotationMatrix);
  33. // 将结果转换为cv::Point类型并返回
  34. std::vector<cv::Point> resultPoints(4);
  35. for (int i = 0; i < 4; ++i) {
  36. resultPoints[i] = cv::Point(cvRound(dstPoints[i].x), cvRound(dstPoints[i].y));
  37. }
  38. return resultPoints;
  39. }
  40. /*
  41. 旋转模板匹配函数(通过图像金字塔、增大旋转步长来提升匹配速度)
  42. Mat src:原图像
  43. Mat model:模板图
  44. double startAngle:旋转的最小角
  45. double endAngle:旋转的最大角
  46. double firstStep:角度旋转时的最大步长
  47. double secondStep:角度旋转时的最小步长
  48. int numLevels = 0:图像金字塔缩放次数
  49. */
  50. MatchResult rotateMatch(cv::Mat src, cv::Mat model, double startAngle, double endAngle, double firstStep, double secondStep, int numLevels = 0) {
  51. //对模板图像和待检测图像分别进行图像金字塔下采样
  52. for (int i = 0; i < numLevels; i++) {
  53. cv::pyrDown(src, src, cv::Size(src.cols / 2, src.rows / 2));
  54. cv::pyrDown(model, model, cv::Size(model.cols / 2, model.rows / 2));
  55. }
  56. cv::Mat rotatedImg, result;
  57. double score = -1;
  58. cv::Point location;
  59. double angle;
  60. bool isSecond = false;
  61. while (true) {
  62. for (double curAngle = startAngle; curAngle <= endAngle; curAngle += firstStep) {
  63. rotatedImg = ImageRotate(model, curAngle);
  64. //imshow("rotated", rotatedImg);
  65. //imshow("src-pyrDown", src);
  66. //waitKey();
  67. matchTemplate(src, rotatedImg, result, cv::TM_CCOEFF_NORMED);
  68. double minval, maxval;
  69. cv::Point minloc, maxloc;
  70. cv::minMaxLoc(result, &minval, &maxval, &minloc, &maxloc);
  71. if (maxval > score)
  72. {
  73. location = maxloc;
  74. score = maxval;
  75. angle = curAngle;
  76. }
  77. }
  78. if (isSecond && firstStep<= secondStep) break;
  79. startAngle = angle - firstStep;
  80. endAngle = angle + firstStep;
  81. if ((endAngle - startAngle) / 5 > secondStep) {
  82. firstStep = (endAngle - startAngle) / 5;
  83. }
  84. else {
  85. firstStep = secondStep;
  86. isSecond = true;
  87. }
  88. }
  89. cv::Point finalPoint = cv::Point(location.x * pow(2, numLevels), location.y * pow(2, numLevels));
  90. std::vector<cv::Point> points = GetRotatePoints(cv::Size(model.cols * pow(2, numLevels), model.rows * pow(2, numLevels)), angle);
  91. for (int j = 0; j < points.size(); j++)
  92. {
  93. points[j].x += finalPoint.x;
  94. points[j].y += finalPoint.y;
  95. }
  96. return MatchResult(points, angle, score);
  97. }
  98. int main() {
  99. //读取所有图像
  100. std::vector<cv::Mat> imgs;
  101. std::string imageName;
  102. std::string path = "E:\\prj\\shape_based_matching-master\\test\\board\\test";
  103. std::vector<std::string> img_paths;
  104. cv::glob(path, img_paths);
  105. for (auto& p : img_paths)
  106. {
  107. cv::Mat img = cv::imread(p);
  108. imgs.push_back(img);
  109. }
  110. cv::Mat templateImg = cv::imread("E:\\prj\\shape_based_matching-master\\test\\board\\train.png");
  111. cv::Rect box(cv::Point(135, 120), cv::Point(470, 365));
  112. //cv::rectangle(drawFrame, box, cv::Scalar(0, 255, 0), 2);
  113. templateImg = templateImg(box).clone();
  114. int i = 0;
  115. for (cv::Mat img : imgs)
  116. {
  117. i += 1;
  118. MatchResult matchResult = rotateMatch(img, templateImg, 0, 360, 30, 0.1, 0);
  119. std::vector<cv::Point> points = matchResult.points;
  120. std::cout << i << "- 角度:" << matchResult.angle << std::endl;
  121. std::cout << i << "- 得分:" << matchResult.score << std::endl;
  122. cv::line(img, points[0], points[1], cv::Scalar(255, 0, 0), 2);
  123. cv::line(img, points[1], points[2], cv::Scalar(255, 0, 0), 2);
  124. cv::line(img, points[2], points[3], cv::Scalar(255, 0, 0), 2);
  125. cv::line(img, points[3], points[0], cv::Scalar(255, 0, 0), 2);
  126. cv::Point pt1 = cv::Point((points[0].x + points[3].x) / 2, (points[0].y + points[3].y) / 2);
  127. cv::Point pt2 = cv::Point((points[1].x + points[2].x) / 2, (points[1].y + points[2].y) / 2);
  128. cv::arrowedLine(img, pt2, pt1, cv::Scalar(0, 0, 255), 2);
  129. cv::imshow("img_" + std::to_string(i), img);
  130. cv::waitKey(0);
  131. }
  132. return 0;
  133. }

结果如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/955527
推荐阅读
相关标签
  

闽ICP备14008679号