qt+opencv 获取图像灰度值并以QTableView展现

思路如下:
先用opencv方法打开并以灰度图像的方式读取一张图片,然后获取整张图所有像素点的灰度值,将这些值存入容器中。然后因为图像为8192*4096的尺寸,像素点灰度值数据量较大。因此采用QTableView加自定义QAbstractTableModel的方式去展示数据。每个单元格的文本值和背景色为对应像素点的灰度值。


效果如图:
在这里插入图片描述
在这里插入图片描述


相关代码如下:

// 读取图片
 QString path;
 cv::Mat img;
 
 img = cv::imread(path.toStdString(), CV_8UC1);
 if (img.empty()) {
     cout << "读取不到加载的图片数据";
     return;
 }
//获取图像像素点灰度值
void GetImgPixelGrayVal()
{
    //图像不为空且为单通道(即灰度图)
    if(img.empty() || img.channels()!=1){
        return;
    }
    
    QMap<int,QVector<uchar>> m_pixel;               // 像素点灰度值容器(行,列集合)
    QSize curImgSize;                   			// 当前图像尺寸

#if 1
    //获取像素点灰度值方法一(比方法二快)
    m_pixel.clear();
    for (int r = 0; r < curImgSize.height(); ++r) {
        uchar* data = img.ptr<uchar>(r); // 获取第r行像素数组的指针

        QVector<uchar> tmpVec;
        for (int c = 0; c < curImgSize.width(); ++c) {
            uchar pixelValue = data[c]; // 获取第r行第c列像素点的灰度值
            tmpVec.append(pixelValue);
        }
        m_pixel.insert(r,tmpVec);
    }
#else
    //获取像素点灰度值方法二
    for(int i=0; i<curImgSize.height(); i++){
        for(int j=0; j<curImgSize.width(); j++){
             int grayVal = (int)img.at<uchar>(i,j);
        }
    }
#endif

    QStringList list1, list2;
    for(int i=1; i<=curImgSize.width(); i++){
        list1 << QString("Column %1").arg(i);
    }
    for(int i=1; i<=curImgSize.height(); i++){
        list2 << QString("Row %1").arg(i);
    }

    m_tableModel->SetHorizontalHeadData(list1);
    m_tableModel->SetVerticalHeadData(list2);
    m_tableModel->SetData(m_pixel);
    m_tableView = new PixelTableView(this);    
    connect(m_tableView, &PixelTableView::sig_view_table_close, this, [=](){delete m_tableView; m_tableView=nullptr;}, Qt::QueuedConnection);
    m_tableView->setModel(m_tableModel);
    m_tableView->show();
}
//自定义QTableView和QAbstractTableModel
#include <QObject>
#include <QAbstractTableModel>
#include <QTableView>
#include <QHeaderView>
#include <QStandardItemModel>

class PixelTableView : public QTableView
{
    Q_OBJECT

public:
    PixelTableView(QWidget *parent=nullptr);
    ~PixelTableView();

protected:
    void mousePressEvent(QMouseEvent *event);

    void closeEvent(QCloseEvent *event);

signals:
    void sig_view_table_close();
};



class PixelTableModel : public QAbstractTableModel
{
    Q_OBJECT

public:
    PixelTableModel(QObject *parent = nullptr);
    ~PixelTableModel();
    void SetHorizontalHeadData(const QStringList& list);  //设置表头数据
    void SetVerticalHeadData(const QStringList& list);
    void SetData(const QMap<int, QVector<uchar>>& map);   //设置表格数据
public:
    int rowCount(const QModelIndex& parent) const;  //返回行数
    int columnCount(const QModelIndex& parent) const;   //返回列数
    QVariant data(const QModelIndex& index, int role) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const;  //返回指定表头数据


private:
    QStringList m_headData_h; //表头数据
    QStringList m_headData_v;
    QMap<int, QVector<uchar>> m_datas;    //显示的数据
};
PixelTableView::PixelTableView(QWidget *parent)
    : QTableView(parent)
{

    //this->setStyleSheet("QTableView::item { background-color: #FFFFC9; }");
    this->setWindowTitle(tr("Pixel Viewer"));
    this->resize(1000,500);
    this->horizontalHeader()->setStyleSheet("QHeaderView::section { background-color: #FFFFC9; }");//#E1DAD9
    this->verticalHeader()->setStyleSheet("QHeaderView::section { background-color: #FFFFC9; }");
    this->horizontalHeader()->setSectionsClickable(false);
    this->verticalHeader()->setSectionsClickable(false);
    this->setCornerButtonEnabled(false);
    this->setWindowFlag(Qt::Window);
    this->setWindowModality(Qt::ApplicationModal);
    this->setAttribute(Qt::WA_QuitOnClose, false);
}


PixelTableView::~PixelTableView()
{

}


void PixelTableView::mousePressEvent(QMouseEvent *event)
{

}

void PixelTableView::closeEvent(QCloseEvent *event)
{
    emit sig_view_table_close();
    QTableView::closeEvent(event);
}



PixelTableModel::PixelTableModel(QObject *parent)
    : QAbstractTableModel(parent)
{
}

PixelTableModel::~PixelTableModel()
{
}

int PixelTableModel::rowCount(const QModelIndex& parent) const
{
    if (parent.isValid()) {
        return 0;
    } else {
        return m_headData_v.size();  //显示数据的大小
    }
}

int PixelTableModel::columnCount(const QModelIndex& parent) const
{
    if (parent.isValid()) {
        return 0;
    } else {
        return m_headData_h.size();   //表头的大小
    }
}

QVariant PixelTableModel::data(const QModelIndex& index, int role) const
{
    if (!index.isValid()) {
        return QVariant();
    }
    if (role == Qt::DisplayRole) {
        return (m_datas.begin() + index.row())->at(index.column()); //单元格中数据
    }
    if (role == Qt::TextAlignmentRole) {    //对其方式
        return Qt::AlignCenter; //对齐格式为居中
    }
    if (role == Qt::BackgroundColorRole) {  //单元格背景颜色和灰度值相同
        return QColor((m_datas.begin() + index.row())->at(index.column()),(m_datas.begin() + index.row())->at(index.column()),(m_datas.begin() + index.row())->at(index.column()));
    }
    if (role == Qt::TextColorRole) {
        return (m_datas.begin() + index.row())->at(index.column()) > 128 ? QColor(Qt::black) : QColor(Qt::white);
    }
    return QVariant();
}

QVariant PixelTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Horizontal) {    //水平表头
        if (role == Qt::DisplayRole) {  //角色为显示
            return m_headData_h.at(section);  //返回指定位置表头
        }
    }else{
        if(role == Qt::DisplayRole) {
            return m_headData_v.at(section);
        }
    }
    return QAbstractTableModel::headerData(section, orientation, role);
}

void PixelTableModel::SetHorizontalHeadData(const QStringList& list)
{
    m_headData_h = list;
}

void PixelTableModel::SetVerticalHeadData(const QStringList& list)
{
    m_headData_v = list;
}

void PixelTableModel::SetData(const QMap<int, QVector<uchar>>& map)
{
    beginResetModel();  //刷新表格
    m_datas = map;
    endResetModel();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值