当前位置:   article > 正文

Qt-OpenCV学习笔记--识别图形轮廓并计算图形坐标_qt输出std::vector中的坐标

qt输出std::vector中的坐标

概述

思路:将获得的图像进行修正,然后识别图形轮廓,最后计算图形坐标。

整体方案是基本函数和基本操作的综合应用。

此方案可以用于标签位置检测。

代码没有经过实际验证,此处仅是做个记录。

测试代码

myCV.pro

  1. QT += core gui
  2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  3. CONFIG += c++11
  4. # You can make your code fail to compile if it uses deprecated APIs.
  5. # In order to do so, uncomment the following line.
  6. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
  7. SOURCES += \
  8. main.cpp \
  9. sm.cpp \
  10. widget.cpp
  11. HEADERS += \
  12. sm.h \
  13. widget.h
  14. FORMS += \
  15. widget.ui
  16. # Default rules for deployment.
  17. qnx: target.path = /tmp/$${TARGET}/bin
  18. else: unix:!android: target.path = /opt/$${TARGET}/bin
  19. !isEmpty(target.path): INSTALLS += target
  20. unix|win32: LIBS += -L$$PWD/../../../../../opencv/install/x64/mingw/lib/ -llibopencv_world454.dll
  21. INCLUDEPATH += $$PWD/../../../../../opencv/install/include
  22. DEPENDPATH += $$PWD/../../../../../opencv/install/include

sm.h

  1. #ifndef SM_H
  2. #define SM_H
  3. #include <opencv2/core/core.hpp>
  4. #include <opencv2/highgui/highgui.hpp>
  5. #include <opencv2/imgproc/imgproc.hpp>
  6. #include <iostream>
  7. class sm
  8. {
  9. public:
  10. sm();
  11. public:
  12. //预处理
  13. static cv::Mat pretreatment(cv::Mat src, int width, int height);
  14. //后处理
  15. static std::vector<cv::RotatedRect> postTreatment (cv::Mat src);
  16. //坐标排序
  17. static void sortPoints(cv::RotatedRect rect,cv::Point2f pts[]);
  18. //获取轮廓
  19. static std::vector<std::vector<cv::Point> > getContour(cv::Mat src, int threshold1, int threshold2);
  20. //裁切
  21. static cv::Mat cutBorder (cv::Mat src,int number);
  22. };
  23. #endif // SM_H

widget.h

  1. #ifndef WIDGET_H
  2. #define WIDGET_H
  3. #include <QWidget>
  4. QT_BEGIN_NAMESPACE
  5. namespace Ui { class Widget; }
  6. QT_END_NAMESPACE
  7. class Widget : public QWidget
  8. {
  9. Q_OBJECT
  10. public:
  11. Widget(QWidget *parent = nullptr);
  12. ~Widget();
  13. private slots:
  14. void on_pushButton_clicked();
  15. void on_pushButton_2_clicked();
  16. private:
  17. Ui::Widget *ui;
  18. };
  19. #endif // WIDGET_H

main.cpp

  1. #include "widget.h"
  2. #include <QApplication>
  3. int main(int argc, char *argv[])
  4. {
  5. QApplication a(argc, argv);
  6. Widget w;
  7. w.show();
  8. return a.exec();
  9. }

sm.cpp

  1. #include "sm.h"
  2. #include <opencv2/core/core.hpp>
  3. #include <opencv2/highgui/highgui.hpp>
  4. #include <opencv2/imgproc/imgproc.hpp>
  5. #include <QDebug>
  6. sm::sm()
  7. {
  8. }
  9. cv::Mat sm::pretreatment(cv::Mat src,int width, int height)
  10. {
  11. //定义输出对象
  12. cv::Mat dst;
  13. //获得轮廓
  14. std::vector<std::vector<cv::Point>> contours;
  15. contours = sm::getContour(src,100,200);
  16. //先要判断所有图形是否全部内嵌
  17. if (contours.size()!=1)
  18. {
  19. qDebug()<<"图像加载错误,请重新加载!";
  20. return dst;
  21. }
  22. //获得矩形
  23. cv::RotatedRect box;
  24. box = cv::minAreaRect(contours[0]);
  25. qDebug()<<"矩形的角度:"<<box.angle;
  26. //获得矩形的顶点数组
  27. cv::Point2f pts[4];
  28. sm::sortPoints(box,pts);
  29. //校正
  30. double x = 2;
  31. double y = 1.5;
  32. pts[0].x = pts[0].x+x;
  33. pts[0].y = pts[0].y+y;
  34. pts[1].x = pts[1].x-x;
  35. pts[1].y = pts[1].y+y;
  36. pts[2].x = pts[2].x-x;
  37. pts[2].y = pts[2].y-y;
  38. pts[3].x = pts[3].x+x;
  39. pts[3].y = pts[3].y-y;
  40. //变换数组
  41. cv::Point2f pts_src[4];
  42. pts_src[0]=pts[0];
  43. pts_src[1]=pts[1];
  44. pts_src[2]=pts[2];
  45. pts_src[3]=pts[3];
  46. //对应数组
  47. cv::Point2f ps_dst[4];
  48. ps_dst[0] = cv::Point2f(0,0);
  49. ps_dst[1] = cv::Point2f(width,0);
  50. ps_dst[2] = cv::Point2f(width,height);
  51. ps_dst[3] = cv::Point2f(0,height);
  52. //变换矩阵
  53. cv::Mat M = getPerspectiveTransform(pts_src,ps_dst);
  54. //输出图像的大小
  55. cv::Size size(width,height);
  56. //透视变换
  57. warpPerspective(src,dst,M,size);
  58. //打印
  59. qDebug()<<"矩形的宽度:"<<dst.size().width;
  60. qDebug()<<"矩形的高度:"<<dst.size().height;
  61. qDebug()<<"图像预处理完成";
  62. //返回结果
  63. return dst;
  64. }
  65. std::vector<cv::RotatedRect> sm::postTreatment(cv::Mat src)
  66. {
  67. //获得轮廓
  68. std::vector<std::vector<cv::Point>> contours;
  69. contours = sm::getContour(src,100,200);
  70. //定义输出对象
  71. std::vector<cv::RotatedRect> RotatedRect(contours.size());
  72. //获得矩形
  73. for (uint i=0;i<contours.size();i++)
  74. {
  75. RotatedRect[i] = minAreaRect(contours[i]);
  76. }
  77. qDebug()<<"后处理完成";
  78. //返回结果
  79. return RotatedRect;
  80. }
  81. void sm::sortPoints(cv::RotatedRect rect, cv::Point2f pts[])
  82. {
  83. //获得中心点
  84. cv::Point2f p0;
  85. p0=rect.center;
  86. //获得顶点
  87. cv::Point2f p[4];
  88. rect.points(p);
  89. //排序
  90. for (int i= 0;i<4;i++)
  91. {
  92. if( p[i].x<p0.x && p[i].y<p0.y )
  93. pts[0]=p[i];
  94. else if( p[i].x>p0.x && p[i].y<p0.y )
  95. pts[1]=p[i];
  96. else if( p[i].x>p0.x && p[i].y>p0.y )
  97. pts[2]=p[i];
  98. else
  99. pts[3]=p[i];
  100. }
  101. //打印
  102. qDebug()<<"中心点:"<<p0.x<<"-"<<p0.y;
  103. qDebug()<<"第1个点:"<<pts[0].x<<"-"<<pts[0].y;
  104. qDebug()<<"第2个点:"<<pts[1].x<<"-"<<pts[1].y;
  105. qDebug()<<"第3个点:"<<pts[2].x<<"-"<<pts[2].y;
  106. qDebug()<<"第4个点:"<<pts[3].x<<"-"<<pts[3].y;
  107. qDebug()<<"点的排序完成";
  108. }
  109. std::vector<std::vector<cv::Point>> sm::getContour(cv::Mat src,int threshold1,int threshold2)
  110. {
  111. //初步处理
  112. cv::Mat dst_gray,
  113. dst_blur,
  114. dst_canny,
  115. dst_dilate;
  116. //灰度处理
  117. cv::cvtColor(src,dst_gray,cv::COLOR_BGR2GRAY);
  118. //cv::imshow("dst_gray",dst_gray);
  119. //高斯模糊
  120. cv::GaussianBlur(dst_gray,dst_blur,cv::Size(3,3),0,0);
  121. //cv::imshow("dst_blur",dst_blur);
  122. //边缘检测
  123. cv::Canny(dst_blur,dst_canny,threshold1,threshold2);
  124. //cv::imshow("dst_canny",dst_canny);
  125. //膨胀
  126. cv::dilate(dst_canny,dst_dilate,cv::Mat());
  127. //cv::imshow("dst_dilate",dst_dilate);
  128. //检测轮廓
  129. std::vector<std::vector<cv::Point>> contours;
  130. findContours(dst_dilate,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_NONE);
  131. //drawContours(src,contours,-1,cv::Scalar(255,0,255),cv::FILLED);
  132. //cv::imshow("src",src);
  133. //打印轮廓数量
  134. qDebug()<<"轮廓数量:"<<contours.size();
  135. //打印轮廓坐标
  136. for (uint i=0;i<contours.size();i++)
  137. {
  138. for(uint j=0;j<contours[i].size();j++)
  139. {
  140. qDebug()<<"轮廓坐标:"<<contours[i][j].x<<"--"<<contours[i][j].y;
  141. }
  142. }
  143. qDebug()<<"获取轮廓完成";
  144. //返回结果
  145. return contours;
  146. }
  147. cv::Mat sm::cutBorder(cv::Mat src, int number)
  148. {
  149. //定义输出对象
  150. cv::Mat dst;
  151. cv::Mat dst_temp;
  152. //定义裁切矩形
  153. cv::Point p_start(number,number);
  154. cv::Point p_end(src.size().width-number,src.size().height-number);
  155. cv::Rect rect(p_start,p_end);
  156. //裁切
  157. dst_temp=src(rect).clone();//这个地方是个坑!若不克隆,仅仅是局部显示,不进行真正的裁切!!!
  158. //缝补
  159. cv::copyMakeBorder(dst_temp,dst,number,number,number,number,cv::BORDER_REPLICATE);
  160. qDebug()<<"裁切完成";
  161. //返回结果
  162. return dst;
  163. }

widget.cpp

  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QFileDialog>
  4. #include <iostream>
  5. #include <QDebug>
  6. #include "sm.h"
  7. Widget::Widget(QWidget *parent)
  8. : QWidget(parent)
  9. , ui(new Ui::Widget)
  10. {
  11. ui->setupUi(this);
  12. }
  13. Widget::~Widget()
  14. {
  15. delete ui;
  16. }
  17. void Widget::on_pushButton_clicked()
  18. {
  19. //获取路径
  20. QString qstr = ui->lineEdit->text();
  21. //转换
  22. std::string str = qstr.toStdString();
  23. //加载图像
  24. std::string path =str;
  25. cv::Mat src = cv::imread(path);
  26. //判断是否加载成功
  27. if(src.empty())
  28. {
  29. qDebug()<<"加载图片失败!";
  30. return;
  31. }
  32. //图像预处理
  33. cv::Mat dst_p;
  34. //获取数据
  35. QString width = ui->lineEdit_2->text();
  36. QString height = ui->lineEdit_3->text();
  37. //qstring转int
  38. int width_i = width.toInt();
  39. int height_i = height.toInt();
  40. //预处理
  41. dst_p = sm::pretreatment(src,width_i,height_i);
  42. //判断预处理是否成功
  43. if(dst_p.empty())
  44. {
  45. qDebug()<<"图像预处理失败!";
  46. return;
  47. }
  48. //裁切
  49. cv::Mat dst_c;
  50. dst_c = sm::cutBorder(dst_p,20);
  51. //后处理
  52. std::vector<cv::RotatedRect> rects;
  53. rects = sm::postTreatment(dst_c);
  54. //打印结果
  55. std::vector<std::vector<cv::Point>> box(rects.size());
  56. for (uint i=0;i<rects.size();i++)
  57. {
  58. //打印坐标
  59. qDebug()<<"矩形"<<i<<":"<<rects[i].center.x;
  60. qDebug()<<"矩形"<<i<<":"<<rects[i].center.y;
  61. double a = rects[i].center.x;
  62. double b = rects[i].center.y;
  63. QString str1 = QString::number(a,'f',2);
  64. QString str2 = QString::number(b,'f',2);
  65. QString str3 = QString::number(i);
  66. QString str = "矩形"+str3+"的坐标是:"+str1+"--"+str2;
  67. ui->textBrowser->append(str);
  68. //获得矩形顶点
  69. cv::Point2f ps[4];
  70. rects[i].points(ps);
  71. box[i].push_back(ps[0]);
  72. box[i].push_back(ps[1]);
  73. box[i].push_back(ps[2]);
  74. box[i].push_back(ps[3]);
  75. //绘制矩形
  76. polylines(dst_c,box[i],1,cv::Scalar(0,255,0),2,8,0);
  77. }
  78. //打印空行
  79. ui->textBrowser->append(" ");
  80. //显示
  81. cv::imshow("dst_c",dst_c);
  82. }
  83. void Widget::on_pushButton_2_clicked()
  84. {
  85. QString fileName = QFileDialog::getOpenFileName(this,"选择一个图片",".","*.jpg *.png *.bmp");
  86. if(!fileName.isEmpty())
  87. {
  88. ui->lineEdit->setText(fileName);
  89. ui->label_6->setPixmap(fileName);
  90. }
  91. }

widget.ui

测试结果

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号