Qt作品(一): 框选图片任意数量Roi(感兴趣区域)工具


前言

在图像处理中,有时候我们只想对图像的某部分区域执行处理,即所谓的Roi(感兴趣区域)。例如在做模板匹配之前,通常都需要人工在图像上框选一个Mask区域,以此建立基准模板。下面记录一下自己基于Qt实现的一个框选图片矩形区域的工具。

功能演示:

鼠标左键点击,该位置坐标位矩形的左上顶点,滑动鼠标即可实时看到自己所框选的矩形框,释放左键。矩形款选完成,左键释放时。这是界面会提示,右键点击鼠标,代表确认矩形框选完成。右窗口显示框选矩形区域之后的图像。底部窗口输出所有框选的矩形的左顶点,矩形的高还有宽。

在这里插入图片描述若想重新框选,左键双击将全部清楚。

在这里插入图片描述

主要思路

1.继承QWidget类,重写鼠标双击,鼠标移动,鼠标单击和鼠标释放函数,

virtual void mouseDoubleClickEvent(QMouseEvent *event)
virtual void mouseMoveEvent(QMouseEvent *event)
virtual void mousePressEvent(QMouseEvent *event)
virtual void mouseReleaseEvent(QMouseEvent *event)

在这四个函数中,实现人机交互的逻辑。
2.矩形数据结构采用的是opencv提供的cv::Rect数据结构。右键点击确认完成,将所有的cv::Rect矩形存储在std::vector容器中。在文章opencv cv::Rect详解中,我们解析了该数据类型。
3.右窗口的实现是采用了opencv提供的rectangle函数,将所有框选的矩形以填充的形式画在一张画布上,再将画布与原图做与的操作,可以用“ | ”操作符,也可以调用opencv的bitwise_and()函数。

核心代码:

void Widget::mousePressEvent(QMouseEvent *event)
{
    
    
    if(event->button() == Qt::LeftButton && event->pos().x() < srcOri.cols)
    {
    
    
        bIsDrawing = true;
        cacheRect = cv::Rect(event->pos().x()-m_fRatioWidth, event->pos().y()-m_fRatioHeigh, 0, 0);
    }
    else if(event->button() == Qt::RightButton)
    {
    
    
        cropImage(result);
    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    
    
    if(event->button() == Qt::LeftButton)
    {
    
    
        bIsDrawing = false;
        if (cacheRect.width < 0) {
    
    

            cacheRect.x += cacheRect.width;
            cacheRect.width *= -1;
        }
        if (cacheRect.height < 0) {
    
    
            cacheRect.y += cacheRect.height;
            cacheRect.height *= -1;
        }
        if(cacheRect.height&&cacheRect.width)
        {
    
    
            drawRect(image, cacheRect);
            vecRects.push_back(cacheRect);
            bIsClickRButton = true;
        }

    }
}

void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
    
    
    if(event->button() == Qt::LeftButton)
    {
    
    
        bIsClickRButton = false;
        vecRects.clear();
        srcOri.copyTo(image);
        srcOri.copyTo(result);
        ui->textEdit->clear();
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    
    
    if (bIsDrawing) {
    
    
        if(event->pos().x() - cacheRect.x>2 ||event->pos().y() - cacheRect.y>2)
        {
    
    
            cacheRect.width = event->pos().x() - m_fRatioWidth - cacheRect.x;
            cacheRect.height = event->pos().y()- m_fRatioHeigh - cacheRect.y;
        }
    }
}
//抠图
void Widget::cropImage(cv::Mat &img)
{
    
    
    if(vecRects.empty())
    {
    
    
        srcOri.copyTo(img);
        return;
    }
    cv::Mat roi = cv::Mat::zeros(img.size(),img.type());
    ui->textEdit->clear();
    for(int i = 0; i < vecRects.size(); i++)
    {
    
    
        qDebug()<<"rect"<<vecRects[i].width<<vecRects[i].height;
        int x = vecRects[i].x;
        int y = vecRects[i].y;
        int h = vecRects[i].height;
        int w = vecRects[i].width;
        QString info = QString(QStringLiteral("左顶点坐标x:%1 左顶点坐标y:%2 高:%3 宽:%4")).arg(x).arg(y).arg(h).arg(w);
        info = QString("%1.").arg(i+1) + info;
        ui->textEdit->append(info);
        cv::rectangle(roi, vecRects[i], cv::Scalar(255,255,255), -1);
    }
    cv::bitwise_and(srcOri, roi, img);
}

猜你喜欢

转载自blog.csdn.net/weixin_44901043/article/details/123358725#comments_21185258
今日推荐