Initial autostretch
This commit is contained in:
+4
-2
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)));
|
||||
|
||||
+57
-8
@@ -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,14 +62,28 @@ 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)
|
||||
{
|
||||
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);
|
||||
@@ -73,14 +91,27 @@ RawImage::RawImage(const QImage &img)
|
||||
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++)
|
||||
{
|
||||
medianSum += hist.at<float>(0, i);
|
||||
if(medianSum >= halfImageSize)
|
||||
{
|
||||
*median = i;
|
||||
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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user