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

news2024/11/15 17:36:04

思路如下:
先用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();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1483946.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

测试需求平台8-Arco组件实现产品增改需求

✍此系列为整理分享已完结入门搭建《TPM提测平台》系列的迭代版&#xff0c;拥抱Vue3.0将前端框架替换成字节最新开源的arco.design&#xff0c;其中约60%重构和20%新增内容&#xff0c;定位为从 0-1手把手实现简单的测试平台开发教程&#xff0c;内容将囊括基础、扩展和实战&a…

栈(顺序栈)实现Language C

###王道考研的学习领悟&#xff0c;个人喜好讲解清晰 何为栈&#xff1f; 定义:栈&#xff08;stack&#xff09;是只允许在一端进行插入或删除的线性表。 其重要术语&#xff1a;栈顶&#xff0c;栈底&#xff0c;空栈。 我们只需要把这个图看明白了&#xff0c;理解起来就…

nest.js使用nest-winston日志一

nest-winston文档 nest-winston - npm 参考&#xff1a;nestjs中winston日志模块使用 - 浮的blog - SegmentFault 思否 安装 cnpm install --save nest-winston winstoncnpm install winston-daily-rotate-file 在main.ts中 import { NestFactory } from nestjs/core; im…

JVM类加载机制以及双亲委派模型的介绍

目录 1.类加载介绍 2.具体步骤 2.1加载 2.2验证 2.3准备 2.4解析 2.5初始化 3.加载过程中的策略-双亲委派模型 1.类加载介绍 类加载,指的是Java进程在运行的时候,把.class文件从硬盘读取到内存,并进行一系列校验解析的过程. .class文件>类对象.硬盘>内村 类加载…

技术栈选型的时候,ruby、go、java、vue、react应该怎么选择?

选择适合项目需求、团队技术背景和偏好、开发速度、性能要求以及可扩展性的技术栈和框架是一个综合考虑的过程&#xff0c;没有一种通用的最佳选择&#xff0c;取决于具体情况。 选择Vue.js或React应该综合考虑项目的需求、团队的技术背景和偏好、生态系统的支持和发展趋势等因…

【Java】面向对象之多态超级详解!!

文章目录 前言一、多态1.1 多态的概念1.2 多态的实现条件1.3 重写1.3.1方法重写的规则1.3.2重写和重载的区别 1.4 向上转型和向下转型1.4.1向上转型1.4.2向下转型 1.5 多态的优缺点1.5.1 使用多态的好处1.5.2 使用多态的缺陷 结语 前言 为了深入了解JAVA的面向对象的特性&…

web开发:如何用Echarts来自动给网页设计各种统计图

很多时候web开发也会需要用到统计图&#xff0c;如果单纯靠我们自己那点拙劣的css和js水平设计的话&#xff0c;又耗时间又做得跟史一样&#xff0c;这时候就需要引入别人设计师为我们设计好的动态统计图——echarts Echarts的官网是&#xff1a;Apache ECharts 1、第一步&…

一个脚本两步计算材料Raman谱(附数据处理和绘图脚本)

在以往推送中已经介绍了相当多的计算材料Raman的方法&#xff0c;使用的软件主要为Phonopy-Spectroscopy&#xff0c;相关软件还有vasp&#xff0c;phonopy&#xff0c;phono3py等。 Phonopy-Spectroscopy计算材料红外和Raman光谱 Phonopy-Spectroscopy 计算红外和拉曼光谱 也…

重学Springboot3-@ConditionalOnXxx条件注解

重学Springboot3-ConditionalOnXxx条件注解 引言常见的条件注解常见的条件注解示例扩展条件注解1. ConditionalOnJndi2. ConditionalOnJava3. ConditionalOnCloudPlatform4. ConditionalOnEnabledResourceChain5. 自定义条件注解 总结 引言 Spring Boot 提供了一组强大的条件注…

2.1 mov、add和sub加减指令实操体验

汇编语言 1. mov操作 1.1 mov移动值 mov指令把右边的值移动到左边 mount c d:masm c: debug r ax 0034 r 073f:0100 mov ax,7t1.2 mov移动寄存器的值 把右边寄存器的值赋值给左边的寄存器 a 073f:0105 mov bx,axt1.3 mov高八位&#xff08;high&#xff09;和低八位&am…

cetos7 Docker 安装 gitlab

一、gitlab 简单介绍和安装要求 官方文档&#xff1a;https://docs.gitlab.cn/jh/install/docker.html 1.1、gitlab 介绍 gitLab 是一个用于代码仓库管理系统的开源项目&#xff0c;使用git作为代码管理工具&#xff0c;并在此基础上搭建起来的Web服务平台&#xff0c;通过该平…

C++_数据类型_布尔类型

作用 布尔数据类型代表真或假的值 bool类型只有两个值&#xff1a; ture 真&#xff08;本质是1&#xff09;false 假 &#xff08;本质是0&#xff09; bool类型占1个字节大小 示例 注意 bool类型&#xff0c;只要是非0的值都代表真

【谈一谈】我们所用的三种工厂模式优缺点

【谈一谈】我们所用的三种工厂模式优缺点 Hello!!大家好啊,好久也没有进行文章的更新了,原因嘛,最近的工作任务量有点大,导致摸鱼充电的时间大量减少,哈哈哈(你别说,这是借口嘛!) 不过,今天是星期六,难的能够在这里分享下最近在工作中,我用到的三种工厂模式(简工抽),有啥区别呢…

国内哪个工具可以平替chatgpt?国内有哪些比较好用的大模型gpt?

我自己试用了很多的平台&#xff0c;发现三个比较好的大模型平台&#xff0c;对普通用户也比较的友好的&#xff0c;而且返回内容相对来说&#xff0c;正确率更高的&#xff0c;并且相关场景插件比较丰富的国内厂商。 本文说的&#xff0c;是我自己觉得的&#xff0c;比较有主观…

linux之进程理解(1)

目录 1. 冯诺依曼体系结构 2. 操作系统(OS) 2.1 概念 2.2 设计OS的目的 2.3 定位 2.4 理解管理 3. 系统调用和库函数概念 4. 补充 1. 冯诺依曼体系结构 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体…

HCIA-Datacom实验指导手册:8 网络编程与自动化基础

HCIA-Datacom实验指导手册&#xff1a;8 网络编程与自动化基础 一、实验介绍&#xff1a;二、实验拓扑&#xff1a;三、实验目的&#xff1a;四、配置步骤&#xff1a;步骤 1 完成交换机的 Telnet 预配置步骤 2 Python 代码编写 五、结果验证六、windows 计划任务程序配置七、 …

全部都有的子序列

思路&#xff08;双指针&#xff09; 先使用Set来存储总共有多少不同的数字&#xff0c;然后我们使用快慢指针去遍历数组&#xff0c;快指针每次遍历到一个数&#xff0c;将其加入到哈希表&#xff0c;哈希表使用pair存储&#xff0c;第一个元素存数字&#xff0c;第二个元素存…

2024最新算法:鳑鲏鱼优化算法(Bitterling Fish Optimization,BFO)求解23个基准函数(提供MATLAB代码)

一、鳑鲏鱼优化算法 鳑鲏鱼优化算法&#xff08;Bitterling Fish Optimization&#xff0c;BFO&#xff09;由Lida Zareian 等人于2024年提出。鳑鲏鱼在交配中&#xff0c;雄性和雌性物种相互接近&#xff0c;然后将精子和卵子释放到水中&#xff0c;但这种方法有一个很大的缺…

javaweb请求与响应

前言 前面介绍了对应的服务器端的相关代码。这里开始学习服务器端与客户端的数据请求与响应 这里的仅仅是一个简单的调用&#xff0c;并没有经过servelert接口来进行调用&#xff0c;同前面的一样&#xff0c;我们介绍对应的本地服务器进行的部署项目。 代码 //属于简单的不…

【Memory协议栈】Memory Abstraction Interface模块介绍

目录 前言 正文 1.功能简介 2.关键概念 3.关键类型定义 3.1 MemIf_StatusType 3.2 MemIf_JobResultType 3.3 MemIf_ModeType 4.关键API定义 4.1 MemIf_SetMode 4.2 MemIf_Read 4.3 MemIf_Write 4.4 MemIf_Cancel 4.5 MemIf_GetStatus 4.6 MemIf_GetJobResult 4…