• 25、opencv的仿射变换


    基本思想:opencv仿射变换不是太准,存在于嵌套仿射的情况,存在这样的问题,在角点的四个外围坐标仿射为正向坐标之后,通过仿射矩阵M去计算内部存在的嵌套矩形框,计算存在偏差,同时以截图为遮挡,仿射的外围四个角点还是存在误差的,需要添加平移参数调整

    代码存在问题,我将大框画在了第一个,需要调整代码,先假设数组的第一个框为大框

    情况一:

    测试图片

    测试代码

    1. #include<iostream>
    2. #include<opencv2/opencv.hpp>
    3. using namespace std;
    4. using namespace cv;
    5. double EuDis(Point pt1, Point pt2) {
    6. return sqrt((pt2.x - pt1.x) * (pt2.x - pt1.x) + (pt2.y - pt1.y) * (pt2.y - pt1.y));
    7. }
    8. int main() {
    9. Mat src = imread("../demo.jpg");
    10. Mat src_clone=src.clone();
    11. vector<vector<Point>> contours;
    12. std::vector<Point> item;
    13. item.emplace_back(cv::Point(363, 62));
    14. item.emplace_back(cv::Point(765, 199));
    15. item.emplace_back(cv::Point(505, 659));
    16. item.emplace_back(cv::Point(62, 507));
    17. contours.emplace_back(item);
    18. item.clear();
    19. item.emplace_back(cv::Point(378, 290));
    20. item.emplace_back(cv::Point(456, 252));
    21. item.emplace_back(cv::Point(491, 295));
    22. item.emplace_back(cv::Point(417, 332));
    23. contours.emplace_back(item);
    24. item.clear();
    25. for(int i=0;i<contours.size();i++){
    26. for(int j=0;j<contours[i].size();j++){
    27. circle(src, cv::Point(contours[i][j].x, contours[i][j].y), 10, Scalar(255, 0, 0), -1);
    28. if(j!=contours[i].size()-1){
    29. line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][j+1].x, contours[i][j+1].y), Scalar(255, 0, 0),2, LINE_8);
    30. }else {
    31. line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][0].x, contours[i][0].y), Scalar(255, 0, 0),2, LINE_8);
    32. }
    33. }
    34. }
    35. vector<Point> srcPts;
    36. double new_area = 0;
    37. for (int i = 0; i < contours.size(); i++) {
    38. double area = contourArea(contours[i]);
    39. if (area > new_area) {
    40. srcPts = {contours[i][0], contours[i][1], contours[i][2], contours[i][3]};
    41. new_area = area;
    42. }
    43. }
    44. double LeftHeight = EuDis(srcPts[0], srcPts[3]);
    45. double RightHeight = EuDis(srcPts[1], srcPts[2]);
    46. double MaxHeight = max(LeftHeight, RightHeight);
    47. double UpWidth = EuDis(srcPts[0], srcPts[1]);
    48. double DownWidth = EuDis(srcPts[2], srcPts[3]);
    49. double MaxWidth = max(UpWidth, DownWidth);
    50. Point2f SrcAffinePts[4] = {Point2f(srcPts[0]), Point2f(srcPts[1]), Point2f(srcPts[2]), Point2f(srcPts[3])};
    51. Point2f DstAffinePts[4] = {Point2f(0, 0), Point2f(MaxWidth, 0), Point2f(MaxWidth, MaxHeight),
    52. Point2f(0, MaxHeight)};
    53. Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);
    54. Mat DstImg;
    55. warpPerspective(src_clone, DstImg, M, Point(MaxWidth,MaxHeight));
    56. std::cout << M << std::endl;
    57. float a00 = M.at<cv::Vec3d>(0, 0)[0];
    58. float a01 = M.at<cv::Vec3d>(0, 0)[1];
    59. float a02 = M.at<cv::Vec3d>(0, 0)[2];
    60. float a10 = M.at<cv::Vec3d>(1, 0)[0];
    61. float a11 = M.at<cv::Vec3d>(1, 0)[1];
    62. float a12 = M.at<cv::Vec3d>(1, 0)[2];
    63. float a20 = M.at<cv::Vec3d>(2, 0)[0];
    64. float a21 = M.at<cv::Vec3d>(2, 0)[1];
    65. float a22 = M.at<cv::Vec3d>(2, 0)[2];
    66. //cosx siny tx a00 a01 a02
    67. //-sinx cosy ty a10 a11 a12
    68. //0 0 1 a20 a21 a22
    69. //矫正畸变不准 需要调整包含物体的坐标
    70. int cof=5;
    71. std::vector<std::vector<cv::Point>> new_contours;
    72. for (int i = 0; i < contours.size(); i++) {
    73. std::vector<cv::Point> item;
    74. double new_x=0;
    75. double new_y=0;
    76. for (int j = 0; j < contours[i].size(); j++) {
    77. if(i==0){
    78. new_x=DstAffinePts[j].x;
    79. new_y=DstAffinePts[j].y;
    80. }else {
    81. new_x = contours[i][j].x * a00+ contours[i][j].y * a01 + a02-cof;
    82. new_y = contours[i][j].x * a10 + contours[i][j].y * a11 + a12-4;
    83. }
    84. item.emplace_back(cv::Point(new_x, new_y));
    85. }
    86. new_contours.emplace_back(item);
    87. }
    88. for(int i=0;i<new_contours.size();i++){
    89. for(int j=0;j<new_contours[i].size();j++){
    90. circle(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), 10, Scalar(0, 0, 255), -1);
    91. if(j!=new_contours[i].size()-1){
    92. line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][j+1].x, new_contours[i][j+1].y), Scalar(0, 0, 255),2, LINE_8);
    93. }else {
    94. line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][0].x, new_contours[i][0].y), Scalar(0, 0, 255),2, LINE_8);
    95. }
    96. }
    97. }
    98. imshow("Dst", DstImg);
    99. imshow("src", src);
    100. waitKey(0);
    101. destroyAllWindows();
    102. return 0;
    103. }

    测试结果

    情况二:测试图片

     测试代码

    1. #include<iostream>
    2. #include<opencv2/opencv.hpp>
    3. using namespace std;
    4. using namespace cv;
    5. double EuDis(Point pt1, Point pt2) {
    6. return sqrt((pt2.x - pt1.x) * (pt2.x - pt1.x) + (pt2.y - pt1.y) * (pt2.y - pt1.y));
    7. }
    8. int main() {
    9. Mat src = imread("../Selection_017.png");
    10. Mat src_clone=src.clone();
    11. vector<vector<Point>> contours;
    12. std::vector<Point> item;
    13. item.emplace_back(cv::Point(87, 143));
    14. item.emplace_back(cv::Point(548, 147));
    15. item.emplace_back(cv::Point(601, 364));
    16. item.emplace_back(cv::Point(54, 362));
    17. contours.emplace_back(item);
    18. item.clear();
    19. item.emplace_back(cv::Point(252, 247));
    20. item.emplace_back(cv::Point(398, 246));
    21. item.emplace_back(cv::Point(402, 269));
    22. item.emplace_back(cv::Point(249, 269));
    23. contours.emplace_back(item);
    24. item.clear();
    25. item.emplace_back(cv::Point(441, 208));
    26. item.emplace_back(cv::Point(441, 233));
    27. item.emplace_back(cv::Point(478, 232));
    28. item.emplace_back(cv::Point(474, 208));
    29. contours.emplace_back(item);
    30. item.clear();
    31. item.emplace_back(cv::Point(155, 223));
    32. item.emplace_back(cv::Point(155, 246));
    33. item.emplace_back(cv::Point(192, 245));
    34. item.emplace_back(cv::Point(193, 222));
    35. contours.emplace_back(item);
    36. item.clear();
    37. for(int i=0;i<contours.size();i++){
    38. for(int j=0;j<contours[i].size();j++){
    39. circle(src, cv::Point(contours[i][j].x, contours[i][j].y), 10, Scalar(255, 0, 0), -1);
    40. if(j!=contours[i].size()-1){
    41. line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][j+1].x, contours[i][j+1].y), Scalar(255, 0, 0),2, LINE_8);
    42. }else {
    43. line(src, cv::Point(contours[i][j].x, contours[i][j].y), cv::Point(contours[i][0].x, contours[i][0].y), Scalar(255, 0, 0),2, LINE_8);
    44. }
    45. }
    46. }
    47. vector<Point> srcPts;
    48. double new_area = 0;
    49. for (int i = 0; i < contours.size(); i++) {
    50. double area = contourArea(contours[i]);
    51. if (area > new_area) {
    52. srcPts = {contours[i][0], contours[i][1], contours[i][2], contours[i][3]};
    53. new_area = area;
    54. }
    55. }
    56. double LeftHeight = EuDis(srcPts[0], srcPts[3]);
    57. double RightHeight = EuDis(srcPts[1], srcPts[2]);
    58. double MaxHeight = max(LeftHeight, RightHeight);
    59. double UpWidth = EuDis(srcPts[0], srcPts[1]);
    60. double DownWidth = EuDis(srcPts[2], srcPts[3]);
    61. double MaxWidth = max(UpWidth, DownWidth);
    62. Point2f SrcAffinePts[4] = {Point2f(srcPts[0]), Point2f(srcPts[1]), Point2f(srcPts[2]), Point2f(srcPts[3])};
    63. Point2f DstAffinePts[4] = {Point2f(0, 0), Point2f(MaxWidth, 0), Point2f(MaxWidth, MaxHeight),
    64. Point2f(0, MaxHeight)};
    65. Mat M = getPerspectiveTransform(SrcAffinePts, DstAffinePts);
    66. Mat DstImg;
    67. warpPerspective(src_clone, DstImg, M, Point(MaxWidth,MaxHeight));
    68. std::cout << M << std::endl;
    69. float a00 = M.at<cv::Vec3d>(0, 0)[0];
    70. float a01 = M.at<cv::Vec3d>(0, 0)[1];
    71. float a02 = M.at<cv::Vec3d>(0, 0)[2];
    72. float a10 = M.at<cv::Vec3d>(1, 0)[0];
    73. float a11 = M.at<cv::Vec3d>(1, 0)[1];
    74. float a12 = M.at<cv::Vec3d>(1, 0)[2];
    75. float a20 = M.at<cv::Vec3d>(2, 0)[0];
    76. float a21 = M.at<cv::Vec3d>(2, 0)[1];
    77. float a22 = M.at<cv::Vec3d>(2, 0)[2];
    78. //cosx siny tx a00 a01 a02
    79. //-sinx cosy ty a10 a11 a12
    80. //0 0 1 a20 a21 a22
    81. //矫正畸变不准 需要调整包含物体的坐标
    82. int cof=25;
    83. std::vector<std::vector<cv::Point>> new_contours;
    84. for (int i = 0; i < contours.size(); i++) {
    85. std::vector<cv::Point> item;
    86. double new_x=0;
    87. double new_y=0;
    88. for (int j = 0; j < contours[i].size(); j++) {
    89. if(i==0){
    90. new_x=DstAffinePts[j].x;
    91. new_y=DstAffinePts[j].y;
    92. }else {
    93. new_x = contours[i][j].x * a00+ contours[i][j].y * a01 + a02-cof;
    94. new_y = contours[i][j].x * a10 + contours[i][j].y * a11 + a12-cof;
    95. }
    96. item.emplace_back(cv::Point(new_x, new_y));
    97. }
    98. new_contours.emplace_back(item);
    99. }
    100. for(int i=0;i<new_contours.size();i++){
    101. for(int j=0;j<new_contours[i].size();j++){
    102. circle(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), 10, Scalar(0, 0, 255), -1);
    103. if(j!=new_contours[i].size()-1){
    104. line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][j+1].x, new_contours[i][j+1].y), Scalar(0, 0, 255),2, LINE_8);
    105. }else {
    106. line(DstImg, cv::Point(new_contours[i][j].x, new_contours[i][j].y), cv::Point(new_contours[i][0].x, new_contours[i][0].y), Scalar(0, 0, 255),2, LINE_8);
    107. }
    108. }
    109. }
    110. cv::imwrite("dst.jpg",DstImg);
    111. imshow("Dst", DstImg);
    112. cv::imwrite("src.jpg",src);
    113. imshow("src", src);
    114. waitKey(0);
    115. destroyAllWindows();
    116. return 0;
    117. }

    测试结果

    原图

    仿射之后

  • 相关阅读:
    线上一次JVM FullGC搞得整晚都没睡,彻底崩溃
    nginx安装(离线安装,新增--with-http_ssl_module、--with-stream模块,离线升级)
    怎么能让页面加载完在执行js
    Yii 知识点总结
    Linux使用ifconfig命令没有显示ens33或者没有ip地址
    【Java网络原理】 四
    python 爬虫与协同过滤的新闻推荐系统 计算机竞赛
    Vue项目中 vantUI中tab标签栏下划线位置异常,指定下标但是显示还是默认下标。解决方案
    论文阅读-CheckFreq:频繁、精细的DNN检查点操作。
    GitHub的下载超时问题
  • 原文地址:https://blog.csdn.net/sxj731533730/article/details/127668836