Qt+opencv 鼠标画线实现几何图形识别并动态创建

这篇具有很好参考价值的文章主要介绍了Qt+opencv 鼠标画线实现几何图形识别并动态创建。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

使用Qt + OpenCV实现,通过鼠标画线绘制几何图形,然后通过opencv进行图形轮廓识别,返回图形顶点,然后创建对应的几何图形添加到场景中。绘制使用QGraphics体系完成。

看效果图:
Qt+opencv 鼠标画线实现几何图形识别并动态创建


本文demo在这里
点击下载

环境: Qt5.15.2 + vs2019 64bit文章来源地址https://www.toymoban.com/news/detail-496834.html


支持图形:直线、圆、椭圆、矩形、三角形。
快捷键:数字3 清屏

正文

demo的功能实现流程如下:

在临时画线层绘制,然后将绘制的图形保存成一张临时图片,再将其传给opencv进行轮廓检测,返回轮廓点后再计算出轮廓顶点坐标,将坐标交给Qt层动态创建几何图形,添加到scene中。

opencv下载

本文中需要用到opencv的轮廓识别,所以先要准备好opencv的库,本文下载的是当前最新版本V4.6.0
opencv下载地址

Qt+opencv 鼠标画线实现几何图形识别并动态创建安装后,将其头文件和动态库拷贝到自己的工程项目中,并创建一个pri文件进行管理,也方便其他项目使用。

Qt+opencv 鼠标画线实现几何图形识别并动态创建
这里用到的动态库是opencv_world460.dll

opencv.pri

INCLUDEPATH += $$PWD/include

win32 {
CONFIG(release, debug|release) {
LIBS += -L$$PWD/lib/ -lopencv_world460
}

CONFIG(debug, debug|release) {
LIBS += -L$$PWD/lib/ -lopencv_world460d
}
}

OpenCV轮廓提取算法使用findContours()接口,详情可参考这里

绘制

本文使用QGraphics体系进行鼠标画线,是在之前的博客文章代码基础上复用的
详情参考:

Qt 鼠标/触屏绘制平滑曲线,支持矢量/非矢量方式
Qt实现桌面画线、标记,流畅绘制,支持鼠标和多点触控绘制

检测

调用opencv的接口进行检测

void ShapeDetecter::shapeDetect(string path_to_image)
{
    RNG rng(123);
    // Read image
    Mat3b src = imread(path_to_image);
    // Convert to grayscale
    Mat1b gray;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    // Binarize
    Mat1b bin;
    threshold(gray, bin, 175, 255, THRESH_OTSU|THRESH_BINARY_INV);
    // Perform thinning
    _thinning(bin, bin);
    // Create result image
//    Mat3b res = src.clone();
    // Find contours
    vector<vector<Point>> contours;
    findContours(bin.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
    // For each contour

    if(contours.size() <=0)
        return;
    vector<Point> contour = contours[0];
    for (vector<Point>& contour : contours)
    {
        // Compute convex hull
        vector<Point> hull;
        convexHull(contour, hull);

        // Compute circularity, used for shape classification
        double area = contourArea(hull);
        double perimeter = arcLength(hull, true);
        double circularity = (4 * CV_PI * area) / (perimeter * perimeter);
        // Shape classification
        qDebug() << __FUNCTION__ << "circularity" << circularity;

        if(circularity > 0.85)
        {
            // circle
              RotatedRect rect = fitEllipse(contour);
             _drawCircle(rect.boundingRect());

        }
        else if(circularity > 0.68)
        {
            // Minimum oriented bounding box ...
            RotatedRect rect = minAreaRect(contour);
            Point2f pts[4];
            rect.points(pts);

            QVector<QPoint> points;
            for (int i = 0; i < 4; ++i)
            {
               points.push_back(QPoint( pts[i].x,pts[i].y));
            }

            emit sigDrawPolygon(points);

        }
        else if (circularity > 0.5)
        {
            // TRIANGLE
            // Select the portion of the image containing only the wanted contour
            Rect roi = boundingRect(contour);
            Mat1b maskRoi(bin.rows, bin.cols, uchar(0));
            rectangle(maskRoi, roi, Scalar(255), FILLED);
            Mat1b triangle(roi.height, roi.height, uchar(0));
            bin.copyTo(triangle, maskRoi);

            // Find min encolsing circle on the contour
            Point2f center;
            float radius;
            minEnclosingCircle(contour, center, radius);

            // decrease the size of the enclosing circle until it intersects the contour
            // in at least 3 different points (i.e. the 3 vertices)
            vector<vector<Point>> vertices;
            do
            {
                vertices.clear();
                radius--;

                Mat1b maskCirc(bin.rows, bin.cols, uchar(0));
                circle(maskCirc, center, radius, Scalar(255), 5);

                maskCirc &= triangle;
                findContours(maskCirc.clone(), vertices, RETR_LIST, CHAIN_APPROX_NONE);

            } while (vertices.size() < 3);

            qDebug() << __FUNCTION__ <<"TRIANGLE "<< "vertices_size = " <<vertices.size();
            // Just get the first point in each vertex blob.
            // You could get the centroid for a little better accuracy
            QVector<QPoint> points;
            points.push_back(QPoint(vertices[0][0].x,vertices[0][0].y));
            points.push_back(QPoint(vertices[1][0].x,vertices[1][0].y));
            points.push_back(QPoint(vertices[2][0].x,vertices[2][0].y));
//            emit sigDrawTriangle(points);
            emit sigDrawPolygon(points);
        }
        else
        {
           _drawLine(contours.at(0), boundingRect(contours.at(0)));
        }
    }
}

动态创建图形

从opencv返回顶点接口后,这里直接快捷创建QGraphicsLineItemQGraphicsEllipseItemQGraphicsPolygonItem,也可以自定义QGraphicsItem 然后在paint中进行绘制,自由度更高,比如设置平滑及其他参数等。
可以参考之前的博客
Qt鼠标拖动绘制基本几何图形

void WbCanvasItem::onDrawLine(const QPoint &point1, const QPoint &point2)
{
    auto item = new QGraphicsLineItem(QLineF(point1,point2),this);
    item->setPen(QPen(Qt::red,5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    m_pChildItems.append(item);
}

void WbCanvasItem::onDrawCircle(const QRect &rect)
{
    auto item = new QGraphicsEllipseItem(rect,this);
    item->setPen(QPen(Qt::red,5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    m_pChildItems.append(item);
}

void WbCanvasItem::onDrawPolygon(const QVector<QPoint> &pointVec)
{
    auto item = new QGraphicsPolygonItem(QPolygonF(pointVec),this);
    item->setPen(QPen(Qt::red,5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    m_pChildItems.append(item);
}

本示例通过简单演示整个流程,若运用到实际项目中需要进一步优化。


本文demo在这里
点击下载

环境: Qt5.15.2 + vs2019 64bit


到了这里,关于Qt+opencv 鼠标画线实现几何图形识别并动态创建的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【matplotlib基础】--几何图形

    除了绘制各类分析图形(比如柱状图,折线图,饼图等等)以外, matplotlib 也可以在画布上任意绘制各类几何图形。 这对于计算机图形学、几何算法和计算机辅助设计等领域非常重要。 matplitlib 中的 patches 类提供了丰富的几何对象, 本篇抛砖引玉,介绍其中几种常用的几何

    2024年02月08日
    浏览(46)
  • 图形几何学——圆形:圆弧与曲率

    A、B、C分别是参考线的某三个连续的离散点,abc分别是其对边。根据三角形外接圆相关性质,通过作三条边的中垂线的交点可以求得三角形的外接圆心。连接CO并延长交圆周于点D,由于 近似认为 ∣ P 1 ⃗ ∣ = ∣ P 2 P 3 ⃗ ∣ = d s |vec{P_1}| = |vec{P_2P_3}| = ds ∣ P 1 ​ ​ ∣ = ∣

    2024年04月27日
    浏览(70)
  • Procedural Mesh: 创建复杂的3D几何图形

    Procedural Mesh 是一个用于创建复杂3D几何图形的开源库,由 Morten Nobel 开发并维护。它允许开发者通过程序化的方式生成各种形状和结构,无需手动设计每个顶点和面。 Procedural Mesh 提供了一系列函数和工具,可以帮助开发者轻松地生成自定义的3D网格。这些功能包括: 基础形状

    2024年03月15日
    浏览(40)
  • 几何引擎 & 约束求解器 & 3D仿真物理引擎 & 图形引擎

    四大技术图谱就像四座护法金刚,形成了深不可测的技术鸿沟。这对于任何一个工业软件企业,十年发展的沉淀,那还只是开始。这条路,太漫长了。 Software Vendor Domain 3D-kernel 4MCAD IntelliCAD 4M S.A., Greece CAD, AEC Open CASCADE Technology Adams MSC Software, USA CAE Parasolid ADEM ADEM, Russia-Israel

    2024年02月08日
    浏览(36)
  • 计算机视觉 图像形成 几何图形和变换 3D到2D投影

            现在我们知道如何表示2D和3D几何图元以及如何在空间上转换它们,我们需要指定如何将 3D图元投影到图像平面上。 我们可以使用线性3D到2D投影矩阵来做到这一点。最简单的模型是正交法,它不需要除法就可以得到最终的(不均匀的)结果。更常用的模型是透视,

    2023年04月08日
    浏览(56)
  • CG3-v2.0-图形几何变换

    (1) 理解几何变换基本原理, 掌握平移、旋转、缩放变换的方法; (2) 根据平移算法原理补全translation、scale、rotation_x、rotation_y和rotation_z函数; (3) 根据几何变换基本原理,将main函数中的translation、scale、rotation_z参数补充完整。

    2024年02月08日
    浏览(48)
  • 图形编辑器开发:一些会用到的简单几何算法

    大家好,我是前端西瓜哥。 开发图形编辑器,你会经常要解决一些算法问题。本文盘点一些我开发图形编辑器时遇到的简单几何算法问题。 判断两个矩形是否发生碰撞(或者说相交),即两个矩形有重合的区域。 常见使用场景: 使用选择工具 框选 图形(框选策略除了相交

    2024年02月16日
    浏览(49)
  • 基于EasyX学习图形学中的三维几何变换【全】

    本文开始学习几何变换中的三维变换,对于各种变换的定义方法基本和二维变换一样,在此我就不过多赘述了。 三维变换矩阵 由于二维变换矩阵为三阶矩阵,所以三维变换矩阵为四阶矩阵 以下例子均在此正方体基础上 坐标表示 矩阵表示 变换矩阵 核心代码 效果展示 坐标表

    2024年02月09日
    浏览(39)
  • 【干货分享】如何一键打造理想露营地?春日露营,即刻出发!Python | 建模 | 3D | 图形引擎| 几何引擎

    在这个快节奏的时代,我们都渴望找到一片属于自己的宁静角落。 你是否曾畅想在星空下,与大自然亲密接触,享受露营的乐趣🌌 但是,想到搭建帐篷、生火、布置灯光等一系列繁琐的准备工作,又望而却步😖 想象一下 大包小包,拖家带口 ,还要为应对各种突发情况准备

    2024年03月23日
    浏览(37)
  • SVG的一些基础知识,包括SVG坐标系统、支持的几何图形和样式,动画的基础知识,包括基本动画和路径动画

    SVG(可缩放矢量图形)是一种使用XML格式定义的图像格式,它可以将二维图像呈现为任意大小的图像,而不会产生像素化。由于它的矢量设计,SVG成为了实现各种图形和动画的理想平台。在本文中,我们将探讨如何使用SVG实现图形和动画。 在开始之前,让我们首先了解一下

    2024年02月03日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包