思路如下:
先用opencv方法打开并以灰度图像的方式读取一张图片,然后获取整张图所有像素点的灰度值,将这些值存入容器中。然后因为图像为8192*4096的尺寸,像素点灰度值数据量较大。因此采用QTableView加自定义QAbstractTableModel的方式去展示数据。每个单元格的文本值和背景色为对应像素点的灰度值。
效果如图:
相关代码如下:
cpp
// 读取图片
QString path;
cv::Mat img;
img = cv::imread(path.toStdString(), CV_8UC1);
if (img.empty()) {
cout << "读取不到加载的图片数据";
return;
}
cpp
//获取图像像素点灰度值
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();
}
cpp
//自定义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; //显示的数据
};
cpp
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();
}