[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    koffice/krita/plugins/viewplugins/bracketing2hdr
From:       Cyrille Berger <cyb () lepi ! org>
Date:       2007-01-08 12:33:42
Message-ID: 1168259622.289440.19563.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 621154 by berger:

implement auto-optimization of the response curves


 M  +183 -64   bracketing2hdr.cc  
 M  +4 -1      bracketing2hdr.h  


--- trunk/koffice/krita/plugins/viewplugins/bracketing2hdr/bracketing2hdr.cc \
#621153:621154 @@ -46,6 +46,8 @@
 
 #include "ui_wdgbracketing2hdr.h"
 
+const double epsilon = 1e-3;
+
 typedef KGenericFactory<Bracketing2HDRPlugin> Bracketing2HDRPluginFactory;
 K_EXPORT_COMPONENT_FACTORY( kritabracketing2hdr, Bracketing2HDRPluginFactory( \
"krita" ) )  
@@ -171,53 +173,164 @@
         above = parent->firstChild();
         img->addLayer(layer, parent, above);
         
-        KisPaintDeviceSP dstdev = layer->paintDevice();
-        int width = m_images[0].image->width();
-        int height = m_images[0].image->height();
+        createHDRPaintDevice( layer->paintDevice() );
+        m_view->canvas()->update();
+    }
+    delete dialog;
+}
+
+void Bracketing2HDRPlugin::createHDRPaintDevice( KisPaintDeviceSP device )
+{
+    int width = m_images[0].image->width();
+    int height = m_images[0].image->height();
+    // Create iterators
+    for(int k = 0; k < m_images.size(); k++)
+    {
+        m_images[k].it = new KisHLineConstIteratorPixel( \
m_images[k].device->createHLineConstIterator(0, 0, width) ); +    }
+    KisHLineIteratorPixel dstIt = device->createHLineIterator(0, 0, width);
+    QColor c;
+    struct { double rsum, rdiv, gsum, gdiv, bsum, bdiv;  } v;
+    // Loop over pixels
+    for(int j = 0; j < height; j++)
+    {
+        while(!dstIt.isDone())
+        {
+            // compute the sum and normalization coefficient for rgb values from the \
bracketing ldr images +            v.rsum = v.rdiv = v.gsum = v.gdiv = v.bsum = \
v.bdiv = 0.0; +            for(int k = 0; k < m_images.size(); k++)
+            {
+                double coef = m_images[k].apexBrightness;
+                m_images[k].device->colorSpace()->toQColor(m_images[k].it->rawData(), \
&c); +                v.rsum += m_intensityR[ c.red() ] * m_weights[ c.red() ] * coef \
; +                v.rdiv += m_weights[ c.red() ] * coef * coef ;
+                v.gsum += m_intensityG[ c.green() ] * m_weights[ c.green() ] * coef \
; +                v.gdiv += m_weights[ c.green() ] * coef * coef ;
+                v.bsum += m_intensityB[ c.blue() ] * m_weights[ c.blue() ] * coef ;
+                v.bdiv += m_weights[ c.blue() ] * coef * coef ;
+                ++(*m_images[k].it);
+            }
+            float* pixelData = reinterpret_cast<float*>(dstIt.rawData());
+            if( v.rdiv != 0.0)
+            {
+                pixelData[2] = v.rsum / v.rdiv;
+            } else {
+                pixelData[2] = 0.0;
+            }
+            if( v.gdiv != 0.0)
+            {
+                pixelData[1] = v.gsum / v.gdiv;
+            } else {
+                pixelData[1] = 0.0;
+            }
+            if( v.bdiv != 0.0)
+            {
+                pixelData[0] = v.bsum / v.bdiv;
+            } else {
+                pixelData[0] = 0.0;
+            }
+            device->colorSpace()->setAlpha(dstIt.rawData(), 255, 1);
+            ++dstIt;
+        }
+        dstIt.nextRow();
         for(int k = 0; k < m_images.size(); k++)
         {
+            m_images[k].it->nextRow();
+        }
+    }
+    // Delete iterators
+    for(int k = 0; k < m_images.size(); k++)
+    {
+        delete m_images[k].it;
+    }
+}
+
+void Bracketing2HDRPlugin::normalize(QVector<double>& intensity)
+{
+    double norm = intensity[numberOfInputLevels()/2];
+    for(int i = 0; i < numberOfInputLevels(); i++)
+    {
+        intensity[i] /= norm;
+    }
+}
+
+void Bracketing2HDRPlugin::computeCameraResponse()
+{
+    kDebug() << "computeCameraResponse()" << endl;
+    loadImagesInMemory();
+    switch(responseType())
+    {
+        case RESPONSE_LINEAR:
+            computeLinearResponse(m_intensityR);
+            computeLinearResponse(m_intensityG);
+            computeLinearResponse(m_intensityB);
+            computePseudoGaussianWeights();
+            break;
+        default:
+            kError() << "NOT IMPLEMENTED YET !" << endl;
+            Q_ASSERT(false);
+    }
+    // Now optimize the camera response
+    // Create a temporary paint device and fill it with the current value
+    KoColorSpace* cs = \
KisMetaRegistry::instance()->csRegistry()->colorSpace("RGBAF32", 0); +    \
KisPaintDeviceSP device = new KisPaintDevice(cs, i18n("HDR Layer")); +    // \
Normalize the intensity responses +    normalize(m_intensityR);
+    normalize(m_intensityG);
+    normalize(m_intensityB);
+    // Initialize some variables used for computation
+    QVector<qint64> counts[3];
+    QVector<double> sums[3];
+    for(int k = 0; k < 3; k++)
+    {
+        counts[k].resize(numberOfInputLevels());
+        sums[k].resize(numberOfInputLevels());
+    }
+    QVector<double> iROld, iGOld, iBOld;
+    int width = m_images[0].image->width();
+    int height = m_images[0].image->height();
+    while(true)
+    {
+        kDebug() << "New loop" << endl;
+        // Compute answer
+        createHDRPaintDevice( device );
+        // Copy the old responses
+        iROld = m_intensityR;
+        iGOld = m_intensityG;
+        iBOld = m_intensityB;
+        // Compute new response curve
+        for(int k = 0; k < 3; k++)
+        {
+            counts[k].fill(0);
+            sums[k].fill(0.0);
+        }
+        // Create iterators
+        for(int k = 0; k < m_images.size(); k++)
+        {
             m_images[k].it = new KisHLineConstIteratorPixel( \
m_images[k].device->createHLineConstIterator(0, 0, width) );  }
-        KisHLineIteratorPixel dstIt = dstdev->createHLineIterator(0, 0, width);
+        KisHLineIteratorPixel dstIt = device->createHLineIterator(0, 0, width);
         QColor c;
-        struct { double rsum, rdiv, gsum, gdiv, bsum, bdiv;  } v;
+        // Loop over pixels
         for(int j = 0; j < height; j++)
         {
             while(!dstIt.isDone())
             {
-                v.rsum = v.rdiv = v.gsum = v.gdiv = v.bsum = v.bdiv = 0.0;
+                float* pixelData = reinterpret_cast<float*>(dstIt.rawData());
+                // compute the sum and normalization coefficient for rgb values from \
the bracketing ldr images  for(int k = 0; k < m_images.size(); k++)
                 {
                     double coef = m_images[k].apexBrightness;
                     \
                m_images[k].device->colorSpace()->toQColor(m_images[k].it->rawData(), \
                &c);
-                    v.rsum += m_intensityR[ c.red() ] * m_weights[ c.red() ] * coef \
                ;
-                    v.rdiv += m_weights[ c.red() ] * coef * coef ;
-                    v.gsum += m_intensityG[ c.green() ] * m_weights[ c.green() ] * \
                coef ;
-                    v.gdiv += m_weights[ c.green() ] * coef * coef ;
-                    v.bsum += m_intensityB[ c.blue() ] * m_weights[ c.blue() ] * \
                coef ;
-                    v.bdiv += m_weights[ c.blue() ] * coef * coef ;
+                    sums[2][c.red()] += pixelData[2] * coef ;
+                    counts[2][c.red()] ++;
+                    sums[1][c.green()] += pixelData[1] * coef ;
+                    counts[1][c.green()] ++;
+                    sums[0][c.blue()] += pixelData[0] * coef ;
+                    counts[0][c.blue()] ++;
                     ++(*m_images[k].it);
                 }
-                float* pixelData = reinterpret_cast<float*>(dstIt.rawData());
-                if( v.rdiv != 0.0)
-                {
-                    pixelData[2] = v.rsum / v.rdiv;
-                } else {
-                    pixelData[2] = 0.0;
-                }
-                if( v.gdiv != 0.0)
-                {
-                    pixelData[1] = v.gsum / v.gdiv;
-                } else {
-                    pixelData[1] = 0.0;
-                }
-                if( v.bdiv != 0.0)
-                {
-                    pixelData[0] = v.bsum / v.bdiv;
-                } else {
-                    pixelData[0] = 0.0;
-                }
-                dstdev->colorSpace()->setAlpha(dstIt.rawData(), 255, 1);
+                device->colorSpace()->setAlpha(dstIt.rawData(), 255, 1);
                 ++dstIt;
             }
             dstIt.nextRow();
@@ -226,34 +339,48 @@
                 m_images[k].it->nextRow();
             }
         }
-        
+        // Delete iterators
         for(int k = 0; k < m_images.size(); k++)
         {
             delete m_images[k].it;
         }
-        m_view->canvas()->update();
+        // Update intensity responses
+        #define UPDATEINTENSITY(n,vec) \
+            for(int i = 0; i < numberOfInputLevels(); i++) \
+            { \
+                if(sums[n][i] != 0.0) \
+                    vec[i] = counts[n][i] / sums[n][i]; \
+                else \
+                    vec[i] = 0.0; \
+            } \
+            normalize(vec);
+        UPDATEINTENSITY(2, m_intensityR);
+        UPDATEINTENSITY(1, m_intensityG);
+        UPDATEINTENSITY(0, m_intensityB);
+        #undef UPDATEINTENSITY
+        // Compute the convergence
+        int count = 0;
+        double sumdiff = 0.0;
+        #define DIFF(vec1, vec2) \
+            if(vec1[i] != 0.0) \
+            { \
+                double diff = vec1[i] - vec2[i]; \
+                sumdiff += diff * diff; \
+                count++; \
+            }
+        for(int i = 0; i < numberOfInputLevels(); i++)
+        {
+            DIFF(m_intensityR, iROld);
+            DIFF(m_intensityG, iGOld);
+            DIFF(m_intensityB, iBOld);
+        }
+        #undef DIFF
+        kDebug() << "Optimization delta = " << (sumdiff/count) << endl;
+        if( sumdiff/count < epsilon)
+            return;
     }
-    delete dialog;
 }
 
-void Bracketing2HDRPlugin::computeCameraResponse()
-{
-    kDebug() << "computeCameraResponse()" << endl;
-    loadImagesInMemory();
-    switch(responseType())
-    {
-        case RESPONSE_LINEAR:
-            computeLinearResponse(m_intensityR);
-            computeLinearResponse(m_intensityG);
-            computeLinearResponse(m_intensityB);
-            computePseudoGaussianWeights();
-            break;
-        default:
-            kError() << "NOT IMPLEMENTED YET !" << endl;
-            Q_ASSERT(false);
-    }
-}
-
 bool Bracketing2HDRPlugin::loadImagesInMemory()
 {
     m_images.clear();
@@ -261,23 +388,15 @@
     {
         // read the info about the frame in the table
         QString fileName = \
                m_wdgBracketing2HDR->tableWidgetImages->item(i,0)->text();
-    
-//     $Av = 2 * log($aperture) / log(2);
-//     $Tv = log($inv_exposure_time) / log(2);
-//     $Sv = log( $iso_speed / 3.125 ) / log(2);
-// 
-//     ## Brightness value
-//     $Bv = $Av+$Tv-$Sv;
 
         BracketingFrame f;
         f.exposure = \
                m_wdgBracketing2HDR->tableWidgetImages->item(i,1)->text().toDouble();
         f.aperture = \
                m_wdgBracketing2HDR->tableWidgetImages->item(i,2)->text().toDouble();
         f.sensitivity = \
                m_wdgBracketing2HDR->tableWidgetImages->item(i,3)->text().toInt();
-        
+        // Compute the apex brightness, more info at \
                http://en.wikipedia.org/wiki/APEX_system
         f.apexBrightness = 2.0 * log(f.aperture ) + log( 1.0 / f.exposure) - log( \
f.sensitivity / 3.125 );  f.apexBrightness /= log(2.0);
-        kDebug() << f.apexBrightness << endl;
-        f.apexBrightness = 1.0 / ( powf(2.0, f.apexBrightness) * ( 1.0592f * 11.4f / \
3.125f ) ); // TODO: the magic number is apparrently dependent of the camera, this \
value is taken from pfscalibrate, this need to be configurable +        \
f.apexBrightness = 1.0 / ( powf(2.0, f.apexBrightness) * ( 1.0592f * 11.4f / 3.125f ) \
); // TODO: the magic number is apparrently dependent of the camera, this value is \
taken from pfscalibrate, this need to be configurable (it is the reflected-light \
meter calibration constant)  
         kDebug() << "Loading fileName " << fileName << " Exposure = " << f.exposure \
<< " Adjusted exposure = " << f.apexBrightness << " Aperture " << f.aperture << " \
Sensitivity = " << f.sensitivity << endl;  // import the image
@@ -318,7 +437,7 @@
     {
         double v = (i - 127.5) * ( 1. / 127.5);
         m_weights[i] = exp( -8.0 * v * v );
-        if( m_weights[i] < 1e-3)
+        if( m_weights[i] < epsilon)
             m_weights[i] = 0.;
     }
 }
--- trunk/koffice/krita/plugins/viewplugins/bracketing2hdr/bracketing2hdr.h \
#621153:621154 @@ -37,7 +37,6 @@
     Q_OBJECT
     public:
         enum ResponseType {
-            RESPONSE_AUTO,
             RESPONSE_LINEAR,
             RESPONSE_GAMMA,
             RESPONSE_LOG10
@@ -80,6 +79,10 @@
         
         void computeCameraResponse();
     private:
+        /// Create the HDR paintdevice
+        void createHDRPaintDevice( KisPaintDeviceSP device );
+        /// Normalize the intensity vector such as \
intensity[numberOfInputLevels()/2] = 1.0 +        void normalize(QVector<double>& \
intensity);  /// Initialize a linear response table
         void computeLinearResponse(QVector<double>& intensity);
         void computePseudoGaussianWeights();


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic