赞
踩
思路:将获得的图像进行修正,然后识别图形轮廓,最后计算图形坐标。
整体方案是基本函数和基本操作的综合应用。
此方案可以用于标签位置检测。
代码没有经过实际验证,此处仅是做个记录。
- QT += core gui
-
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++11
-
- # You can make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp \
- sm.cpp \
- widget.cpp
-
- HEADERS += \
- sm.h \
- widget.h
-
- FORMS += \
- widget.ui
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
-
- unix|win32: LIBS += -L$$PWD/../../../../../opencv/install/x64/mingw/lib/ -llibopencv_world454.dll
-
- INCLUDEPATH += $$PWD/../../../../../opencv/install/include
- DEPENDPATH += $$PWD/../../../../../opencv/install/include
- #ifndef SM_H
- #define SM_H
-
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
-
- #include <iostream>
-
- class sm
- {
- public:
- sm();
-
- public:
-
- //预处理
- static cv::Mat pretreatment(cv::Mat src, int width, int height);
- //后处理
- static std::vector<cv::RotatedRect> postTreatment (cv::Mat src);
- //坐标排序
- static void sortPoints(cv::RotatedRect rect,cv::Point2f pts[]);
- //获取轮廓
- static std::vector<std::vector<cv::Point> > getContour(cv::Mat src, int threshold1, int threshold2);
- //裁切
- static cv::Mat cutBorder (cv::Mat src,int number);
- };
-
- #endif // SM_H
- #ifndef WIDGET_H
- #define WIDGET_H
-
- #include <QWidget>
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class Widget; }
- QT_END_NAMESPACE
-
- class Widget : public QWidget
- {
- Q_OBJECT
-
- public:
- Widget(QWidget *parent = nullptr);
- ~Widget();
-
- private slots:
- void on_pushButton_clicked();
-
- void on_pushButton_2_clicked();
-
- private:
- Ui::Widget *ui;
- };
- #endif // WIDGET_H
- #include "widget.h"
-
- #include <QApplication>
-
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- Widget w;
- w.show();
- return a.exec();
- }
- #include "sm.h"
-
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/imgproc/imgproc.hpp>
-
- #include <QDebug>
-
- sm::sm()
- {
-
- }
-
- cv::Mat sm::pretreatment(cv::Mat src,int width, int height)
- {
- //定义输出对象
- cv::Mat dst;
-
- //获得轮廓
- std::vector<std::vector<cv::Point>> contours;
- contours = sm::getContour(src,100,200);
-
- //先要判断所有图形是否全部内嵌
- if (contours.size()!=1)
- {
- qDebug()<<"图像加载错误,请重新加载!";
- return dst;
- }
-
- //获得矩形
- cv::RotatedRect box;
- box = cv::minAreaRect(contours[0]);
- qDebug()<<"矩形的角度:"<<box.angle;
-
- //获得矩形的顶点数组
- cv::Point2f pts[4];
- sm::sortPoints(box,pts);
-
- //校正
- double x = 2;
- double y = 1.5;
-
- pts[0].x = pts[0].x+x;
- pts[0].y = pts[0].y+y;
- pts[1].x = pts[1].x-x;
- pts[1].y = pts[1].y+y;
- pts[2].x = pts[2].x-x;
- pts[2].y = pts[2].y-y;
- pts[3].x = pts[3].x+x;
- pts[3].y = pts[3].y-y;
-
- //变换数组
- cv::Point2f pts_src[4];
- pts_src[0]=pts[0];
- pts_src[1]=pts[1];
- pts_src[2]=pts[2];
- pts_src[3]=pts[3];
- //对应数组
- cv::Point2f ps_dst[4];
- ps_dst[0] = cv::Point2f(0,0);
- ps_dst[1] = cv::Point2f(width,0);
- ps_dst[2] = cv::Point2f(width,height);
- ps_dst[3] = cv::Point2f(0,height);
- //变换矩阵
- cv::Mat M = getPerspectiveTransform(pts_src,ps_dst);
- //输出图像的大小
- cv::Size size(width,height);
- //透视变换
- warpPerspective(src,dst,M,size);
- //打印
- qDebug()<<"矩形的宽度:"<<dst.size().width;
- qDebug()<<"矩形的高度:"<<dst.size().height;
-
- qDebug()<<"图像预处理完成";
-
- //返回结果
- return dst;
- }
-
- std::vector<cv::RotatedRect> sm::postTreatment(cv::Mat src)
- {
- //获得轮廓
- std::vector<std::vector<cv::Point>> contours;
- contours = sm::getContour(src,100,200);
-
- //定义输出对象
- std::vector<cv::RotatedRect> RotatedRect(contours.size());
-
- //获得矩形
- for (uint i=0;i<contours.size();i++)
- {
- RotatedRect[i] = minAreaRect(contours[i]);
- }
-
- qDebug()<<"后处理完成";
-
- //返回结果
- return RotatedRect;
- }
-
- void sm::sortPoints(cv::RotatedRect rect, cv::Point2f pts[])
- {
- //获得中心点
- cv::Point2f p0;
- p0=rect.center;
-
- //获得顶点
- cv::Point2f p[4];
- rect.points(p);
-
- //排序
- for (int i= 0;i<4;i++)
- {
- if( p[i].x<p0.x && p[i].y<p0.y )
- pts[0]=p[i];
- else if( p[i].x>p0.x && p[i].y<p0.y )
- pts[1]=p[i];
- else if( p[i].x>p0.x && p[i].y>p0.y )
- pts[2]=p[i];
- else
- pts[3]=p[i];
- }
-
- //打印
- qDebug()<<"中心点:"<<p0.x<<"-"<<p0.y;
- qDebug()<<"第1个点:"<<pts[0].x<<"-"<<pts[0].y;
- qDebug()<<"第2个点:"<<pts[1].x<<"-"<<pts[1].y;
- qDebug()<<"第3个点:"<<pts[2].x<<"-"<<pts[2].y;
- qDebug()<<"第4个点:"<<pts[3].x<<"-"<<pts[3].y;
-
- qDebug()<<"点的排序完成";
-
- }
-
- std::vector<std::vector<cv::Point>> sm::getContour(cv::Mat src,int threshold1,int threshold2)
- {
- //初步处理
- cv::Mat dst_gray,
- dst_blur,
- dst_canny,
- dst_dilate;
- //灰度处理
- cv::cvtColor(src,dst_gray,cv::COLOR_BGR2GRAY);
- //cv::imshow("dst_gray",dst_gray);
- //高斯模糊
- cv::GaussianBlur(dst_gray,dst_blur,cv::Size(3,3),0,0);
- //cv::imshow("dst_blur",dst_blur);
- //边缘检测
- cv::Canny(dst_blur,dst_canny,threshold1,threshold2);
- //cv::imshow("dst_canny",dst_canny);
- //膨胀
- cv::dilate(dst_canny,dst_dilate,cv::Mat());
- //cv::imshow("dst_dilate",dst_dilate);
-
- //检测轮廓
- std::vector<std::vector<cv::Point>> contours;
- findContours(dst_dilate,contours,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_NONE);
- //drawContours(src,contours,-1,cv::Scalar(255,0,255),cv::FILLED);
- //cv::imshow("src",src);
-
- //打印轮廓数量
- qDebug()<<"轮廓数量:"<<contours.size();
- //打印轮廓坐标
- for (uint i=0;i<contours.size();i++)
- {
- for(uint j=0;j<contours[i].size();j++)
- {
- qDebug()<<"轮廓坐标:"<<contours[i][j].x<<"--"<<contours[i][j].y;
- }
- }
-
- qDebug()<<"获取轮廓完成";
-
- //返回结果
- return contours;
- }
-
- cv::Mat sm::cutBorder(cv::Mat src, int number)
- {
- //定义输出对象
- cv::Mat dst;
- cv::Mat dst_temp;
-
- //定义裁切矩形
- cv::Point p_start(number,number);
- cv::Point p_end(src.size().width-number,src.size().height-number);
- cv::Rect rect(p_start,p_end);
-
- //裁切
- dst_temp=src(rect).clone();//这个地方是个坑!若不克隆,仅仅是局部显示,不进行真正的裁切!!!
-
- //缝补
- cv::copyMakeBorder(dst_temp,dst,number,number,number,number,cv::BORDER_REPLICATE);
-
- qDebug()<<"裁切完成";
-
- //返回结果
- return dst;
- }
-
-
- #include "widget.h"
- #include "ui_widget.h"
-
- #include <QFileDialog>
-
- #include <iostream>
- #include <QDebug>
-
- #include "sm.h"
-
- Widget::Widget(QWidget *parent)
- : QWidget(parent)
- , ui(new Ui::Widget)
- {
- ui->setupUi(this);
- }
-
- Widget::~Widget()
- {
- delete ui;
- }
-
-
- void Widget::on_pushButton_clicked()
- {
- //获取路径
- QString qstr = ui->lineEdit->text();
- //转换
- std::string str = qstr.toStdString();
-
- //加载图像
- std::string path =str;
- cv::Mat src = cv::imread(path);
- //判断是否加载成功
- if(src.empty())
- {
- qDebug()<<"加载图片失败!";
- return;
- }
-
- //图像预处理
- cv::Mat dst_p;
- //获取数据
- QString width = ui->lineEdit_2->text();
- QString height = ui->lineEdit_3->text();
- //qstring转int
- int width_i = width.toInt();
- int height_i = height.toInt();
- //预处理
- dst_p = sm::pretreatment(src,width_i,height_i);
- //判断预处理是否成功
- if(dst_p.empty())
- {
- qDebug()<<"图像预处理失败!";
- return;
- }
-
- //裁切
- cv::Mat dst_c;
- dst_c = sm::cutBorder(dst_p,20);
-
- //后处理
- std::vector<cv::RotatedRect> rects;
- rects = sm::postTreatment(dst_c);
-
- //打印结果
- std::vector<std::vector<cv::Point>> box(rects.size());
- for (uint i=0;i<rects.size();i++)
- {
- //打印坐标
- qDebug()<<"矩形"<<i<<":"<<rects[i].center.x;
- qDebug()<<"矩形"<<i<<":"<<rects[i].center.y;
-
- double a = rects[i].center.x;
- double b = rects[i].center.y;
-
- QString str1 = QString::number(a,'f',2);
- QString str2 = QString::number(b,'f',2);
- QString str3 = QString::number(i);
-
- QString str = "矩形"+str3+"的坐标是:"+str1+"--"+str2;
-
- ui->textBrowser->append(str);
-
- //获得矩形顶点
- cv::Point2f ps[4];
- rects[i].points(ps);
- box[i].push_back(ps[0]);
- box[i].push_back(ps[1]);
- box[i].push_back(ps[2]);
- box[i].push_back(ps[3]);
-
- //绘制矩形
- polylines(dst_c,box[i],1,cv::Scalar(0,255,0),2,8,0);
-
- }
- //打印空行
- ui->textBrowser->append(" ");
- //显示
- cv::imshow("dst_c",dst_c);
- }
-
- void Widget::on_pushButton_2_clicked()
- {
- QString fileName = QFileDialog::getOpenFileName(this,"选择一个图片",".","*.jpg *.png *.bmp");
- if(!fileName.isEmpty())
- {
- ui->lineEdit->setText(fileName);
- ui->label_6->setPixmap(fileName);
- }
-
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。