Finished prototype
This commit is contained in:
@@ -1,38 +1,38 @@
|
|||||||
#include "clahe.h"
|
#include "clahe.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <opencv2/highgui.hpp>
|
||||||
|
|
||||||
CLAHE::CLAHE()
|
CLAHE::CLAHE()
|
||||||
{
|
{
|
||||||
_clahe = cv::createCLAHE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLAHE::loadFile(const QString &path)
|
void CLAHE::loadFile(const QString &path)
|
||||||
{
|
{
|
||||||
cv::Mat tmp;
|
cv::Mat tmp;
|
||||||
tmp = cv::imread(path.toStdString(), cv::IMREAD_COLOR | cv::IMREAD_ANYDEPTH);
|
tmp = cv::imread(path.toStdString(), cv::IMREAD_COLOR | cv::IMREAD_ANYDEPTH);
|
||||||
double scale = tmp.depth()==CV_8U ? 1.0/255 : 1.0/65535;
|
int type = tmp.depth();
|
||||||
tmp.convertTo(tmp, CV_32F, scale);
|
_scale = type==CV_8U ? 1.0/255 : 1.0/65535;
|
||||||
|
tmp.convertTo(tmp, CV_32F, _scale);
|
||||||
cv::cvtColor(tmp, tmp, cv::COLOR_BGR2Lab);
|
cv::cvtColor(tmp, tmp, cv::COLOR_BGR2Lab);
|
||||||
cv::split(tmp, _image);
|
cv::split(tmp, _image);
|
||||||
_image[0].convertTo(_lumImage, CV_16U, 655.35);
|
_image[0].convertTo(_lumImage, type, 0.01/_scale);
|
||||||
double min, max;
|
|
||||||
cv::minMaxLoc(_image[0], &min, &max);
|
|
||||||
qDebug() << scale << min << max;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLAHE::saveFile(const QString &path)
|
void CLAHE::saveFile(const QString &path)
|
||||||
{
|
{
|
||||||
|
cv::Mat tmp;
|
||||||
|
cv::merge(_image, 3, tmp);
|
||||||
|
cv::cvtColor(tmp, tmp, cv::COLOR_Lab2BGR);
|
||||||
|
tmp.convertTo(tmp, _lumImage.depth(), 1/_scale);
|
||||||
|
cv::imwrite(path.toStdString(), tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLAHE::apply(float clipLimit, int kernelSize)
|
void CLAHE::apply(float clipLimit, int kernelSize)
|
||||||
{
|
{
|
||||||
cv::Mat lum;
|
cv::Mat lum;
|
||||||
_clahe->setClipLimit(clipLimit);
|
cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(clipLimit, cv::Size(kernelSize, kernelSize));
|
||||||
_clahe->setTilesGridSize(cv::Size(kernelSize, kernelSize));
|
clahe->apply(_lumImage, lum);
|
||||||
_clahe->apply(_lumImage, lum);
|
lum.convertTo(_image[0], CV_32F, 100*_scale);
|
||||||
//lum = _lumImage;
|
|
||||||
lum.convertTo(_image[0], CV_32F, 1.0/655.35);
|
|
||||||
double min, max;
|
double min, max;
|
||||||
cv::minMaxLoc(_image[0], &min, &max);
|
cv::minMaxLoc(_image[0], &min, &max);
|
||||||
qDebug() << min << max;
|
qDebug() << min << max;
|
||||||
@@ -44,7 +44,15 @@ QPixmap CLAHE::getImage() const
|
|||||||
cv::merge(_image, 3, tmp);
|
cv::merge(_image, 3, tmp);
|
||||||
cv::cvtColor(tmp, tmp, cv::COLOR_Lab2RGB);
|
cv::cvtColor(tmp, tmp, cv::COLOR_Lab2RGB);
|
||||||
tmp.convertTo(tmp, CV_8U, 255);
|
tmp.convertTo(tmp, CV_8U, 255);
|
||||||
QImage ret(tmp.data, tmp.cols, tmp.rows, tmp.step, QImage::Format_RGB888);
|
QImage ret(tmp.data, tmp.cols, tmp.rows, tmp.step1(), QImage::Format_RGB888);
|
||||||
//ret.bits();//perform deep copy of tmp.data pointer
|
//ret.bits();//perform deep copy of tmp.data pointer
|
||||||
return QPixmap::fromImage(ret);
|
return QPixmap::fromImage(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPixmap CLAHE::getLumImage() const
|
||||||
|
{
|
||||||
|
cv::Mat tmp;
|
||||||
|
_image[0].convertTo(tmp, CV_8U, 2.55);
|
||||||
|
QImage ret(tmp.data, tmp.cols, tmp.rows, tmp.step1(), QImage::Format_Grayscale8);
|
||||||
|
return QPixmap::fromImage(ret);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ class CLAHE
|
|||||||
{
|
{
|
||||||
cv::Mat _lumImage;
|
cv::Mat _lumImage;
|
||||||
cv::Mat _image[3];
|
cv::Mat _image[3];
|
||||||
cv::Ptr<cv::CLAHE> _clahe;
|
double _scale;
|
||||||
public:
|
public:
|
||||||
CLAHE();
|
CLAHE();
|
||||||
void loadFile(const QString &path);
|
void loadFile(const QString &path);
|
||||||
void saveFile(const QString &path);
|
void saveFile(const QString &path);
|
||||||
void apply(float clipLimit, int kernelSize);
|
void apply(float clipLimit, int kernelSize);
|
||||||
QPixmap getImage() const;
|
QPixmap getImage() const;
|
||||||
|
QPixmap getLumImage() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLAHE_H
|
#endif // CLAHE_H
|
||||||
|
|||||||
@@ -29,11 +29,13 @@ PKGCONFIG += opencv
|
|||||||
SOURCES += \
|
SOURCES += \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp \
|
mainwindow.cpp \
|
||||||
clahe.cpp
|
clahe.cpp \
|
||||||
|
imagescrollarea.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
mainwindow.h \
|
mainwindow.h \
|
||||||
clahe.h
|
clahe.h \
|
||||||
|
imagescrollarea.h
|
||||||
|
|
||||||
# Default rules for deployment.
|
# Default rules for deployment.
|
||||||
qnx: target.path = /tmp/$${TARGET}/bin
|
qnx: target.path = /tmp/$${TARGET}/bin
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
#include "imagescrollarea.h"
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QScrollBar>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QPalette>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
ImageScrollArea::ImageScrollArea(QWidget *parent) : QScrollArea(parent),
|
||||||
|
m_scale(-1)
|
||||||
|
{
|
||||||
|
m_label = new QLabel(this);
|
||||||
|
setWidget(m_label);
|
||||||
|
setAlignment(Qt::AlignCenter);
|
||||||
|
setBackgroundRole(QPalette::Dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::setImage(const QPixmap &img)
|
||||||
|
{
|
||||||
|
m_pixmap = img;
|
||||||
|
QPixmap pix;
|
||||||
|
if(m_scale < 0)
|
||||||
|
pix = img.scaled(size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
else
|
||||||
|
pix = img.scaled(img.size() * m_scale, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
|
||||||
|
m_label->setPixmap(pix);
|
||||||
|
m_label->resize(pix.size());
|
||||||
|
|
||||||
|
horizontalScrollBar()->setValue(horizontalScrollBar()->maximum() / 2);
|
||||||
|
verticalScrollBar()->setValue(verticalScrollBar()->maximum() / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::setScale(float scale)
|
||||||
|
{
|
||||||
|
if(scale > 4 || (scale < 0.2 && scale > 0) || m_pixmap.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_scale = scale;
|
||||||
|
QSize newSize = m_scale < 0 ? size() : m_pixmap.size()*scale;
|
||||||
|
m_label->setPixmap(m_pixmap.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
|
m_label->resize(newSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::zoomIn()
|
||||||
|
{
|
||||||
|
if(m_scale < 0)
|
||||||
|
m_scale = (float)size().width()/m_pixmap.size().width();
|
||||||
|
|
||||||
|
setScale(m_scale + 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::zoomOut()
|
||||||
|
{
|
||||||
|
if(m_scale < 0)
|
||||||
|
m_scale = (float)size().width()/m_pixmap.size().width();
|
||||||
|
|
||||||
|
setScale(m_scale - 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::bestFit()
|
||||||
|
{
|
||||||
|
setScale(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::oneToOne()
|
||||||
|
{
|
||||||
|
setScale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::keyPressEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::keyReleaseEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QPoint delta = m_lastPos - event->pos();
|
||||||
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + delta.x());
|
||||||
|
verticalScrollBar()->setValue(verticalScrollBar()->value() + delta.y());
|
||||||
|
m_lastPos = event->pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
m_lastPos = event->pos();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
if(m_scale < 0 && !m_pixmap.isNull())
|
||||||
|
{
|
||||||
|
m_label->setPixmap(m_pixmap.scaled(event->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||||
|
m_label->resize(event->size());
|
||||||
|
}
|
||||||
|
QScrollArea::resizeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageScrollArea::wheelEvent(QWheelEvent *event)
|
||||||
|
{
|
||||||
|
if(m_scale < 0)
|
||||||
|
m_scale = (float)size().width()/m_pixmap.size().width();
|
||||||
|
|
||||||
|
QPointF top(horizontalScrollBar()->value(), verticalScrollBar()->value());
|
||||||
|
QPointF mousePos = (top + event->posF()) / m_scale;
|
||||||
|
|
||||||
|
QPoint delta = event->angleDelta();
|
||||||
|
if(delta.y() > 0)
|
||||||
|
setScale(m_scale + 0.1);
|
||||||
|
else
|
||||||
|
setScale(m_scale - 0.1);
|
||||||
|
|
||||||
|
mousePos *= m_scale;
|
||||||
|
top = mousePos - event->posF();
|
||||||
|
horizontalScrollBar()->setValue(top.x());
|
||||||
|
verticalScrollBar()->setValue(top.y());
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef IMAGESCROLLAREA_H
|
||||||
|
#define IMAGESCROLLAREA_H
|
||||||
|
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
class ImageScrollArea : public QScrollArea
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
QPoint m_lastPos;
|
||||||
|
QLabel *m_label;
|
||||||
|
QPixmap m_pixmap;
|
||||||
|
float m_scale;
|
||||||
|
public:
|
||||||
|
explicit ImageScrollArea(QWidget *parent = 0);
|
||||||
|
void setImage(const QPixmap &img);
|
||||||
|
void setScale(float scale);
|
||||||
|
public slots:
|
||||||
|
void zoomIn();
|
||||||
|
void zoomOut();
|
||||||
|
void bestFit();
|
||||||
|
void oneToOne();
|
||||||
|
protected:
|
||||||
|
void keyPressEvent(QKeyEvent *event);
|
||||||
|
void keyReleaseEvent(QKeyEvent *event);
|
||||||
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
void mousePressEvent(QMouseEvent *event);
|
||||||
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
void wheelEvent(QWheelEvent *event);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMAGESCROLLAREA_H
|
||||||
+59
-9
@@ -2,36 +2,53 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include "clahe.h"
|
#include "clahe.h"
|
||||||
|
|
||||||
|
const QString imageFilter = "Images (*.png *.jpg *.jpeg);;All files (*)";
|
||||||
|
|
||||||
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
|
||||||
{
|
{
|
||||||
setupUI();
|
setupUI();
|
||||||
|
_clahe = new CLAHE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
|
delete _clahe;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::openFile()
|
void MainWindow::openFile()
|
||||||
{
|
{
|
||||||
QStringList list = QStandardPaths::standardLocations(QStandardPaths::StandardLocation::PicturesLocation);
|
QStringList list = QStandardPaths::standardLocations(QStandardPaths::StandardLocation::PicturesLocation);
|
||||||
list.append("");
|
list.append("");
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Open image"), list.first(), tr("Images (*.png *.jpg *.jpeg);;All files (*)"));
|
QString path = QFileDialog::getOpenFileName(this, tr("Open image"), list.first(), imageFilter);
|
||||||
if(!path.isEmpty())
|
if(!path.isEmpty())
|
||||||
{
|
{
|
||||||
CLAHE cl;
|
_clahe->loadFile(path);
|
||||||
cl.loadFile(path);
|
applyClahe();
|
||||||
cl.apply(5, 64);
|
|
||||||
QPixmap pixmap;
|
|
||||||
pixmap = cl.getImage();
|
|
||||||
_image->setPixmap(pixmap);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::saveFile()
|
void MainWindow::saveFile()
|
||||||
{
|
{
|
||||||
|
QStringList list = QStandardPaths::standardLocations(QStandardPaths::StandardLocation::PicturesLocation);
|
||||||
|
QString path = QFileDialog::getSaveFileName(this, tr("Save image"), list.first(), imageFilter);
|
||||||
|
if(!path.isEmpty())
|
||||||
|
{
|
||||||
|
_clahe->saveFile(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::applyClahe()
|
||||||
|
{
|
||||||
|
QPixmap pixmap;
|
||||||
|
_clahe->apply(_clipLimitSlider->value()/100.0f, _kernelSizeSelect->currentText().toInt());
|
||||||
|
pixmap = _clahe->getImage();
|
||||||
|
_imageScrollArea->setImage(pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setupUI()
|
void MainWindow::setupUI()
|
||||||
@@ -43,6 +60,39 @@ void MainWindow::setupUI()
|
|||||||
fileMenu->addAction(tr("Save file"), this, SLOT(saveFile()), QKeySequence("Ctrl+S"));
|
fileMenu->addAction(tr("Save file"), this, SLOT(saveFile()), QKeySequence("Ctrl+S"));
|
||||||
fileMenu->addAction(tr("Quit"), this, SLOT(close()), QKeySequence("Ctrl+Q"));
|
fileMenu->addAction(tr("Quit"), this, SLOT(close()), QKeySequence("Ctrl+Q"));
|
||||||
|
|
||||||
_image = new QLabel(this);
|
_clipLimitEdit = new QLineEdit;
|
||||||
setCentralWidget(_image);
|
_clipLimitEdit->setInputMask("000.00");
|
||||||
|
_clipLimitEdit->setText("1.00");
|
||||||
|
_clipLimitEdit->setMaximumWidth(100);
|
||||||
|
|
||||||
|
_clipLimitSlider = new QSlider(Qt::Horizontal);
|
||||||
|
_clipLimitSlider->setRange(0, 10000);
|
||||||
|
_clipLimitSlider->setValue(100);
|
||||||
|
connect(_clipLimitSlider, SIGNAL(valueChanged(int)), this, SLOT(clipSliderValueChanged(int)));
|
||||||
|
|
||||||
|
QPushButton *applyButton = new QPushButton(tr("Apply"));
|
||||||
|
connect(applyButton, SIGNAL(clicked()), this, SLOT(applyClahe()));
|
||||||
|
|
||||||
|
_kernelSizeSelect = new QComboBox;
|
||||||
|
_kernelSizeSelect->addItems({"8", "16", "32", "64", "128", "256"});
|
||||||
|
|
||||||
|
QHBoxLayout *claheLayout = new QHBoxLayout;
|
||||||
|
claheLayout->addWidget(_clipLimitEdit);
|
||||||
|
claheLayout->addWidget(_clipLimitSlider);
|
||||||
|
claheLayout->addWidget(_kernelSizeSelect);
|
||||||
|
claheLayout->addWidget(applyButton);
|
||||||
|
|
||||||
|
QDockWidget *claheDock = new QDockWidget(tr("CLAHE"), this);
|
||||||
|
QWidget *claheWidget = new QWidget(claheDock);
|
||||||
|
claheDock->setWidget(claheWidget);
|
||||||
|
claheWidget->setLayout(claheLayout);
|
||||||
|
addDockWidget(Qt::TopDockWidgetArea, claheDock);
|
||||||
|
|
||||||
|
_imageScrollArea = new ImageScrollArea(this);
|
||||||
|
setCentralWidget(_imageScrollArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::clipSliderValueChanged(int value)
|
||||||
|
{
|
||||||
|
_clipLimitEdit->setText(QString::number(value/100.0));
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -3,19 +3,29 @@
|
|||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include "clahe.h"
|
||||||
|
#include "imagescrollarea.h"
|
||||||
|
|
||||||
class MainWindow : public QMainWindow
|
class MainWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
QLabel *_image;
|
QComboBox *_kernelSizeSelect;
|
||||||
|
QSlider *_clipLimitSlider;
|
||||||
|
QLineEdit *_clipLimitEdit;
|
||||||
|
CLAHE *_clahe;
|
||||||
|
ImageScrollArea *_imageScrollArea;
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QWidget *parent = nullptr);
|
explicit MainWindow(QWidget *parent = nullptr);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
public slots:
|
public slots:
|
||||||
void openFile();
|
void openFile();
|
||||||
void saveFile();
|
void saveFile();
|
||||||
|
void applyClahe();
|
||||||
private:
|
private:
|
||||||
void setupUI();
|
void setupUI();
|
||||||
|
private slots:
|
||||||
|
void clipSliderValueChanged(int value);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINWINDOW_H
|
#endif // MAINWINDOW_H
|
||||||
|
|||||||
Reference in New Issue
Block a user