Qt设计一个给图像打掩膜的界面

0、需求

需求:找到符合要求的像素点,并且在将该像素点打上红色的掩膜

注意:
1.符号要求的像素点是一个区间,因此需要有Slinder(滑块槽)和SpinBox(旋钮)组件。Slinder组件用于进行粗调,SpinBox组件用于微调,因此还需要一个联动装置。
2.Slinder-SpinBox联动的范围为(-1)-(255)。这和RGB三通道的取值范围有一些不一样,由于RGB三通道的取值范围为0-255,设置一个-1是为了多一个选择,当输入出现-1是认为输出的是原始图像,不打掩膜。
3.Qt的格式和OPencv的格式不一样,因此在编写代码是要注意。

1、界面设计

Qt设计师设计界面如下:
在这里插入图片描述
编译以后界面如下:
在这里插入图片描述

2.实现

代码文件格式如下:
在这里插入图片描述

2.1 界面代码:
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFile> // 文件
#include <QFileDialog> // 文件对话框

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void imshow(QString filepath);

private slots:
    void on_openImage_clicked();

    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
    QString filepath; // 读取的图片路径
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "addrgb.h"

#include <opencv2/opencv.hpp>
#include <QFile> // 文件
#include <QFileDialog> // 文件对话框
#include <QGraphicsView> // 读取图片
#include <QGraphicsScene>
#include <QPixmap>
#include <QGraphicsPixmapItem>
#include <QDebug>
#include <QtWidgets>
#include <QString>
#include <string>

using namespace cv;

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // textLabel绘制边框
    ui->inputLabel->setFrameShape(QFrame::Box);
    ui->outputLabel->setFrameShape(QFrame::Box);

    // SpinBox和Slider联动
    // Rmin 滑块和选值框对应的改变
    QObject::connect(ui->RMinSlider,SIGNAL(valueChanged(int)),
                     ui->RMinBox,SLOT(setValue(int)));
    QObject::connect(ui->RMinBox,SIGNAL(valueChanged(int)),
                     ui->RMinSlider,SLOT(setValue(int)));

    // Rmax
    QObject::connect(ui->RMaxSlider,SIGNAL(valueChanged(int)),
                     ui->RMaxBox,SLOT(setValue(int)));
    QObject::connect(ui->RMaxBox,SIGNAL(valueChanged(int)),
                     ui->RMaxSlider,SLOT(setValue(int)));

    // Gmin
    QObject::connect(ui->GMinSlider,SIGNAL(valueChanged(int)),
                     ui->GMinBox,SLOT(setValue(int)));
    QObject::connect(ui->GMinBox,SIGNAL(valueChanged(int)),
                     ui->GMinSlider,SLOT(setValue(int)));

    // Gmax
    QObject::connect(ui->GMaxSlider,SIGNAL(valueChanged(int)),
                     ui->GMaxBox,SLOT(setValue(int)));
    QObject::connect(ui->GMaxBox,SIGNAL(valueChanged(int)),
                     ui->GMaxSlider,SLOT(setValue(int)));

    // Bmin
    QObject::connect(ui->BMinSlider,SIGNAL(valueChanged(int)),
                     ui->BMinBox,SLOT(setValue(int)));
    QObject::connect(ui->BMinBox,SIGNAL(valueChanged(int)),
                     ui->BMinSlider,SLOT(setValue(int)));

    // Bmax
    QObject::connect(ui->BMaxSlider,SIGNAL(valueChanged(int)),
                     ui->BMaxBox,SLOT(setValue(int)));
    QObject::connect(ui->BMaxBox,SIGNAL(valueChanged(int)),
                     ui->BMaxSlider,SLOT(setValue(int)));

}

MainWindow::~MainWindow()
{
    delete ui;
}

// 显示图片
void MainWindow::on_openImage_clicked()
{
    filepath = QFileDialog::getOpenFileName(this);
    QImage *img = new QImage;
    img->load(filepath);
    ui->inputLabel->setPixmap(QPixmap::fromImage(*img));
}


void MainWindow::on_pushButton_clicked()
{
    //qDebug()<<filepath<<endl;
    //qDebug()<<ui->BMaxBox->value()<<endl;

    //QImage *add_img = new QImage;
    //add_img->load(filepath);
    //ui->outputLabel->setPixmap(QPixmap::fromImage(*add_img));

    int Rmin=ui->RMinBox->value();
    int Rmax=ui->RMaxBox->value();

    int Gmin=ui->GMinBox->value();
    int Gmax=ui->GMaxBox->value();

    int Bmin=ui->BMinBox->value();
    int Bmax=ui->BMaxBox->value();

    String new_path = filepath.toStdString();
    Mat input_img = imread(new_path);
    //namedWindow("ori",WINDOW_FREERATIO);
    //cv::imshow("ori",test_img);
    Need N;
    Mat add_img = N.AddRBG(input_img,Rmin,Rmax,
                               Gmin,Gmax,Bmin,Bmax);

    // 注意:opencv下的图像通道是BGR,因此在转换过程中选择QImage::Format_BGR888
    QImage after_add_img=QImage((const unsigned char*)
     (add_img.data),add_img.cols,add_img.rows,add_img.step,QImage::Format_BGR888);

    ui->outputLabel->setPixmap(QPixmap::fromImage(after_add_img));
}

2.2 OpenCV代码
addrgb.h

#ifndef ADDRGB_H
#define ADDRGB_H

#endif // ADDRGB_H
#include <opencv2/opencv.hpp>

//using namespace cv;
using namespace std;

class Need
{
public:
    // 给图像打掩膜
    cv::Mat AddRBG(cv::Mat &img, int rmin, int rmax,
                int gmin, int gmax, int bmin, int bmax);
};

addrgb.cpp

#include <stdio.h>
#include <opencv2/opencv.hpp>

#include "addrgb.h"

using namespace cv;
using namespace std;

Mat Need::AddRBG(Mat &img, int rmin, int rmax,
            int gmin, int gmax, int bmin, int bmax)
{
    // img:输入图像
    // rmin:R通道符合要求的最小值
    // rmax:R通道符合要求的最大值
    // gmin:G通道符合要求的最小值
    // gmax:G通道符合要求的最大值
    // bmin:B通道符合要求的最小值
    // bmax:B通道符合要求的最大值
    // 输出:打掩膜以后的图像
    Mat add_img;
    img.copyTo(add_img);
    int h = img.rows;
    int w = img.cols;
    int dims = img.channels();
    if(rmin==-1 || rmax==-1 || gmin==-1 || gmax==-1 ||
            bmin==-1 || bmax==-1){
        // 如果最大值和最小值为-1,就认为传入参数错误,因此输出原图
        add_img = img;
    }
    else if(rmin>rmax || gmin>gmax || bmin>bmax)
    {
        // 如果min>max,就认为传入参数错误,因此输出原图
       add_img = img;
    }
    else if(dims==1)
    {
        // 如果输入通道为1,就认为传入参数错误,因此输出原图
        add_img = img;
    }
    else
    {
        for(int row=0;row<h;row++){
            for(int col=0;col<w;col++){
                // 输入图像正常
                if((img.at<Vec3b>(row,col)[0]>=bmin && img.at<Vec3b>(row,col)[0]<=bmax)
                && (img.at<Vec3b>(row,col)[1]>=gmin && img.at<Vec3b>(row,col)[1]<=gmax)
                && (img.at<Vec3b>(row,col)[2]>=rmin && img.at<Vec3b>(row,col)[2]<=rmax))
                {
                    add_img.at<Vec3b>(row,col)[0]=0;
                    add_img.at<Vec3b>(row,col)[1]=0;
                    add_img.at<Vec3b>(row,col)[2]=255;
                }
            }
        }
    }
    return add_img;
}

3、整体效果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值