Initial autostretch

This commit is contained in:
2021-09-11 11:37:54 +02:00
parent f173e48a26
commit 206e1dd393
8 changed files with 117 additions and 24 deletions
+4 -2
View File
@@ -12,7 +12,7 @@ void main(void)
vec4 color = texture2D(qt_Texture0, qt_TexCoord0);
if(bw)color = color.rrra;
color = color*scale.x + scale.y;
max(color, vec4(0.0f));
color = max(color, vec4(0.0f));
switch(stretch)
{
@@ -30,7 +30,7 @@ void main(void)
case 4:
{
//float l = color.r*0.2126f + color.g*0.7152f + color.b*0.0722f;
float l = (color.r+color.g+color.b)*0.33333f;
float l = (color.r+color.g+color.b)*0.33333;
float k = asinh(l*a)/(l*asinh(a));
color *= k;
}
@@ -39,5 +39,7 @@ void main(void)
//color = color*scale.x + scale.y;
//float color = pow(c, 0.4545);
if(any(lessThan(qt_TexCoord0, vec2(0.0))) || any(greaterThan(qt_TexCoord0, vec2(1.0))))
color = vec4(0.0);
gl_FragColor = color;
}
+3 -1
View File
@@ -20,6 +20,7 @@ const RawImageType rawImageTypes[] = {
{QOpenGLTexture::Red, QOpenGLTexture::R16_UNorm, QOpenGLTexture::UInt16, true},
{QOpenGLTexture::Red, QOpenGLTexture::R32F, QOpenGLTexture::Float32, true},
{QOpenGLTexture::RGB, QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, false},
{QOpenGLTexture::BGRA,QOpenGLTexture::RGB8_UNorm, QOpenGLTexture::UInt8, false},
{QOpenGLTexture::RGB, QOpenGLTexture::RGB16_UNorm, QOpenGLTexture::UInt16, false},
{QOpenGLTexture::RGB, QOpenGLTexture::RGB32F, QOpenGLTexture::Float32, false}
};
@@ -68,7 +69,7 @@ void ImageWidget::setImage(RawImage *image)
m_image->setSize(image->width(), image->height());
m_image->allocateStorage();
m_image->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear, QOpenGLTexture::Linear);
m_image->setWrapMode(QOpenGLTexture::ClampToBorder);
m_image->setWrapMode(QOpenGLTexture::ClampToEdge);
m_image->setBorderColor(0, 0, 0, 0);
m_image->setData(0, rawImageType.pixelFormat, rawImageType.dataType, image->data(), m_transferOptions.get());
m_image->generateMipMaps();
@@ -241,6 +242,7 @@ void ImageWidget::initializeGL()
m_program->setUniformValue("scale", 1.0f, 0.0f);
m_image = std::unique_ptr<QOpenGLTexture>(new QOpenGLTexture(QOpenGLTexture::Target2D));
m_image->setFormat(QOpenGLTexture::RGB8U);
m_image->allocateStorage();
m_image->bind(0);
m_image->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
+3
View File
@@ -257,6 +257,9 @@ void LoadRunable::run()
rawImage = new RawImage(img);
}
if(rawImage)
rawImage->calcStats();
if(rawImage && m_analyzeLevel >= Statistics)
{
double mean, median, min, max;
+1
View File
@@ -65,6 +65,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
setWindowTitle(tr("Tenmon"));
connect(m_ringList, SIGNAL(pixmapLoaded(Image*)), this, SLOT(pixmapLoaded(Image*)));
connect(m_ringList, SIGNAL(pixmapLoaded(Image*)), stretchPanel, SLOT(imageLoaded(Image*)));
connect(m_ringList, SIGNAL(currentImageChanged(int)), this, SLOT(updateWindowTitle()));
connect(m_ringList, SIGNAL(infoLoaded(ImageInfoData)), m_info, SLOT(setInfo(ImageInfoData)));
connect(m_ringList, SIGNAL(currentImageChanged(int)), m_filesystem, SLOT(selectFile(int)));
+67 -18
View File
@@ -14,6 +14,8 @@ RawImage::ImgType CV2Type(int cvtype)
return RawImage::FLOAT32;
case CV_8UC3:
return RawImage::UINT8C3;
case CV_8UC4:
return RawImage::UINT8C4;
case CV_16UC3:
return RawImage::UINT16C3;
case CV_32FC3:
@@ -35,6 +37,8 @@ int Type2CV(RawImage::ImgType type)
return CV_32F;
case RawImage::UINT8C3:
return CV_8UC3;
case RawImage::UINT8C4:
return CV_8UC4;
case RawImage::UINT16C3:
return CV_16UC3;
case RawImage::FLOAT32C3:
@@ -58,29 +62,56 @@ RawImage::RawImage(int w, int h, ImgType type)
RawImage::RawImage(cv::Mat &img)
{
m_img = img;
calcStats();
}
RawImage::RawImage(const RawImage &d)
{
d.m_img.copyTo(m_img);
m_mean = d.m_mean;
m_stdDev = d.m_stdDev;
m_median = d.m_median;
m_min = d.m_min;
m_max = d.m_max;
}
RawImage::RawImage(const QImage &img)
{
QImage tmp = img.convertToFormat(QImage::Format_RGB888);
m_img.create(img.height(), img.width(), CV_8UC3);
if(img.format() == QImage::Format_RGB32)
{
m_img.create(img.height(), img.width(), CV_8UC4);
for(int i=0; i<img.height(); i++)
std::memcpy(m_img.ptr(i), img.scanLine(i), img.width()*4);
}
else
{
QImage tmp = img.convertToFormat(QImage::Format_RGB888);
m_img.create(img.height(), img.width(), CV_8UC3);
for(int i=0; i<tmp.height(); i++)
std::memcpy(m_img.ptr(i), tmp.scanLine(i), tmp.width()*3);
for(int i=0; i<tmp.height(); i++)
std::memcpy(m_img.ptr(i), tmp.scanLine(i), tmp.width()*3);
}
calcStats();
}
bool RawImage::imageStats(double *mean, double *stdDev, double *median, double *min, double *max) const
{
if(mean)*mean = m_mean;
if(stdDev)*stdDev = m_stdDev;
if(median)*median = m_median;
if(min)*min = m_min;
if(max)*max = m_max;
return true;
}
void RawImage::calcStats()
{
cv::Scalar meanS, stdDevS;
qDebug() << m_img.type();
cv::meanStdDev(m_img, meanS, stdDevS);
if(min && max)cv::minMaxIdx(m_img, min, max);
cv::minMaxIdx(m_img, &m_min, &m_max);
int histSize = 256;
if(m_img.type() == CV_16U || m_img.type() == CV_32F)histSize = 65536;
@@ -89,24 +120,32 @@ bool RawImage::imageStats(double *mean, double *stdDev, double *median, double *
cv::Mat hist;
cv::calcHist(&m_img, 1, nullptr, cv::Mat(), hist, 1, &histSize, ranges);
if(mean)*mean = meanS[0];
if(stdDev)*stdDev = stdDevS[0];
m_mean = meanS[0];
m_stdDev = stdDevS[0];
size_t halfImageSize = size()/2;
if(median)
size_t medianSum = 0;
for(int i=0; i < histSize; i++)
{
size_t medianSum = 0;
for(int i=0; i < histSize; i++)
medianSum += hist.at<float>(0, i);
if(medianSum >= halfImageSize)
{
medianSum += hist.at<float>(0, i);
if(medianSum >= halfImageSize)
{
*median = i;
break;
}
m_median = i;
break;
}
}
cv::Mat absDev = cv::abs(m_img-m_median);
cv::Mat madHist;
medianSum = 0;
cv::calcHist(&absDev, 1, nullptr, cv::Mat(), madHist, 1, &histSize, ranges);
for(int i=0; i < histSize; i++)
{
medianSum += madHist.at<float>(0, i);
if(medianSum >= halfImageSize)
{
m_mad = i;
break;
}
}
return true;
}
void RawImage::rect(int &x, int &y, int w, int h, std::vector<double> &r) const
@@ -187,3 +226,13 @@ const void *RawImage::data() const
{
return m_img.ptr();
}
float RawImage::stretchFactor() const
{
}
double RawImage::MAD() const
{
return m_mad;
}
+10
View File
@@ -35,6 +35,12 @@ class RawImage
{
protected:
cv::Mat m_img;
double m_mean;
double m_stdDev;
double m_median;
double m_min;
double m_max;
double m_mad;
public:
enum ImgType
{
@@ -42,6 +48,7 @@ public:
UINT16,
FLOAT32,
UINT8C3,
UINT8C4,
UINT16C3,
FLOAT32C3,
UNKNOWN,
@@ -52,6 +59,7 @@ public:
RawImage(const RawImage &d);
RawImage(const QImage &img);
bool imageStats(double *mean, double *stdDev, double *median, double *min, double *max) const;
void calcStats();
void rect(int &x, int &y, int w, int h, std::vector<double> &r) const;
int findPeaks(double background, double distance, std::vector<Peak> &peaks) const;
RawImage* medianFilter() const;
@@ -62,6 +70,8 @@ public:
ImgType type() const;
void* data();
const void* data() const;
float stretchFactor() const;
double MAD() const;
};
#endif // RAWIMAGE_H
+25 -3
View File
@@ -1,5 +1,7 @@
#include "stretchpanel.h"
#include <QVBoxLayout>
#include "imageringlist.h"
#include <QDebug>
StretchPanel::StretchPanel(QWidget *parent) : QWidget(parent)
{
@@ -33,6 +35,24 @@ StretchPanel::StretchPanel(QWidget *parent) : QWidget(parent)
connect(m_stretchSelect, SIGNAL(activated(int)), this, SLOT(calculateParam()));
}
void StretchPanel::imageLoaded(Image *img)
{
if(img)
{
if(img->rawImage())
{
double mean, stdDev, median;
img->rawImage()->imageStats(&mean, &stdDev, &median, nullptr, nullptr);
double mad = img->rawImage()->MAD();
float l = median - mad;
m_lowSlider->setValue(l);
float p = std::log(0.25)/std::log(mean/UINT16_MAX);
m_paramSlider->setValue(p * UINT16_MAX);
qDebug() << "Low" << l << p;
}
}
}
void StretchPanel::calculateParam()
{
float val = m_paramSlider->value();
@@ -40,14 +60,16 @@ void StretchPanel::calculateParam()
switch(m_stretchSelect->currentIndex())
{
case 2:
param = val*100/UINT16_MAX;
param = val/UINT16_MAX;
param = 1.0f / (param * 5.0f + 1);
break;
case 3:
param = val;
break;
case 4:
val += 100;
param = val/100.0f;
param = 1.0f/std::max(0.00001f, 1.0f-(val/UINT16_MAX));
//val += 100;
//param = val/100.0f;
break;
default:
return;
+4
View File
@@ -5,6 +5,8 @@
#include <QSlider>
#include <QComboBox>
class Image;
class StretchPanel : public QWidget
{
Q_OBJECT
@@ -14,6 +16,8 @@ class StretchPanel : public QWidget
QComboBox *m_stretchSelect;
public:
explicit StretchPanel(QWidget *parent = nullptr);
public slots:
void imageLoaded(Image *img);
signals:
void lowChanged(int low);
void highChanged(int high);