diff --git a/rtengine/dfmanager.cc b/rtengine/dfmanager.cc
index 34215e58c..e920e7bf6 100644
--- a/rtengine/dfmanager.cc
+++ b/rtengine/dfmanager.cc
@@ -53,27 +53,28 @@ public:
     std::list<Glib::ustring> pathNames; // other similar dark frames, used for average
     std::string maker; // manufacturer
     std::string model; // model
+    std::string sn; // serial number
     int iso; // ISO (gain)
     double shutter; // shutter or exposure time in sec
     time_t timestamp; // seconds since 1 Jan 1970
 
 
-    dfInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, int iso, double shut, time_t t)
-        : pathname(name), maker(mak), model(mod), iso(iso), shutter(shut), timestamp(t), ri(nullptr) {}
+    dfInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, const std::string &sn, int iso, double shut, time_t t)
+        : pathname(name), maker(mak), model(mod), sn(sn), iso(iso), shutter(shut), timestamp(t), ri(nullptr) {}
 
     dfInfo(const dfInfo &o)
-        : pathname(o.pathname), maker(o.maker), model(o.model), iso(o.iso), shutter(o.shutter), timestamp(o.timestamp), ri(nullptr) {}
+        : pathname(o.pathname), maker(o.maker), model(o.model), sn(o.sn), iso(o.iso), shutter(o.shutter), timestamp(o.timestamp), ri(nullptr) {}
     ~dfInfo();
 
     dfInfo &operator =(const dfInfo &o);
 
     // Calculate virtual distance between two shots; different model return infinite
-    double distance(const std::string &mak, const std::string &mod, int iso, double shutter) const;
+    double distance(const std::string &mak, const std::string &mod, const std::string &sn, int iso, double shutter) const;
 
-    static std::string key(const std::string &mak, const std::string &mod, int iso, double shut);
+    static std::string key(const std::string &mak, const std::string &mod, const std::string &sn, int iso, double shut);
     std::string key() const
     {
-        return key(maker, model, iso, shutter);
+        return key(maker, model, sn, iso, shutter);
     }
 
     const rtengine::RawImage* getRawImage();
@@ -98,6 +99,7 @@ inline dfInfo& dfInfo::operator = (const dfInfo &o)
         pathname = o.pathname;
         maker = o.maker;
         model = o.model;
+        sn = o.sn;
         iso = o.iso;
         shutter = o.shutter;
         timestamp = o.timestamp;
@@ -111,10 +113,10 @@ inline dfInfo& dfInfo::operator = (const dfInfo &o)
     return *this;
 }
 
-std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso, double shut)
+std::string dfInfo::key(const std::string &mak, const std::string &mod, const std::string &sn, int iso, double shut)
 {
     std::ostringstream s;
-    s << mak << " " << mod << " ";
+    s << mak << " " << mod << " " << sn << " ";
     s.width(5);
     s << iso << "ISO ";
     s.precision(2);
@@ -123,7 +125,7 @@ std::string dfInfo::key(const std::string &mak, const std::string &mod, int iso,
     return s.str();
 }
 
-double dfInfo::distance(const std::string &mak, const std::string &mod, int iso, double shutter) const
+double dfInfo::distance(const std::string &mak, const std::string &mod, const std::string &sn, int iso, double shutter) const
 {
     if (this->maker.compare(mak) != 0) {
         return INFINITY;
@@ -133,6 +135,10 @@ double dfInfo::distance(const std::string &mak, const std::string &mod, int iso,
         return INFINITY;
     }
 
+    if (this->sn.compare(sn) != 0) {
+        return INFINITY;
+    }
+
     const double dISO = (log(this->iso / 100.) - log(iso / 100.)) / log(2);
     const double dShutter = (log(this->shutter) - log(shutter)) / log(2);
     return std::sqrt(dISO * dISO +  dShutter * dShutter);
@@ -306,9 +312,9 @@ public:
         return currentPath;
     };
     void getStat(int& totFiles, int& totTemplates) const;
-    const RawImage* searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
+    const RawImage* searchDarkFrame(const std::string& mak, const std::string& mod, const std::string& sn, int iso, double shut, time_t t);
     const RawImage* searchDarkFrame(const Glib::ustring& filename);
-    const std::vector<badPix>* getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
+    const std::vector<badPix>* getHotPixels(const std::string& mak, const std::string& mod, const std::string& sn, int iso, double shut, time_t t);
     const std::vector<badPix>* getHotPixels(const Glib::ustring& filename);
     const std::vector<badPix>* getBadPixels(const std::string& mak, const std::string& mod, const std::string& serial) const;
 
@@ -320,7 +326,7 @@ private:
     bool initialized;
     Glib::ustring currentPath;
     dfInfo* addFileInfo(const Glib::ustring &filename, bool pool = true);
-    dfInfo* find(const std::string &mak, const std::string &mod, int isospeed, double shut, time_t t);
+    dfInfo* find(const std::string &mak, const std::string &mod, const std::string &sn, int isospeed, double shut, time_t t);
     int scanBadPixelsFile(const Glib::ustring &filename);
 };
 
@@ -417,9 +423,9 @@ void rtengine::DFManager::Implementation::getStat(int& totFiles, int& totTemplat
  *  if perfect matches for iso and shutter are found, then the list is scanned for lesser distance in time
  *  otherwise if no match is found, the whole list is searched for lesser distance in iso and shutter
  */
-const rtengine::RawImage* rtengine::DFManager::Implementation::searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
+const rtengine::RawImage* rtengine::DFManager::Implementation::searchDarkFrame(const std::string& mak, const std::string& mod, const std::string& sn, int iso, double shut, time_t t)
 {
-    dfInfo* df = find(toUppercase(mak), toUppercase(mod), iso, shut, t);
+    dfInfo* df = find(toUppercase(mak), toUppercase(mod), toUppercase(sn), iso, shut, t);
 
     if (df) {
         return df->getRawImage();
@@ -456,9 +462,9 @@ const std::vector<rtengine::badPix>* rtengine::DFManager::Implementation::getHot
     return nullptr;
 }
 
-const std::vector<rtengine::badPix>* rtengine::DFManager::Implementation::getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
+const std::vector<rtengine::badPix>* rtengine::DFManager::Implementation::getHotPixels(const std::string& mak, const std::string& mod, const std::string& sn, int iso, double shut, time_t t)
 {
-    dfInfo* df = find(toUppercase(mak), toUppercase(mod), iso, shut, t);
+    dfInfo* df = find(toUppercase(mak), toUppercase(mod), toUppercase(sn), iso, shut, t);
 
     if (df) {
         if (settings->verbose) {
@@ -564,18 +570,18 @@ dfInfo* rtengine::DFManager::Implementation::addFileInfo(const Glib::ustring& fi
         }
 
         if (!pool) {
-            const dfInfo n(filename, "", "", 0, 0, 0);
+            const dfInfo n(filename, "", "", "",  0, 0, 0);
             auto iter = dfList.emplace("", n);
             return &(iter->second);
         }
 
         FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
         /* Files are added in the map, divided by same maker/model,ISO and shutter*/
-        std::string key(dfInfo::key(toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed()));
+        std::string key(dfInfo::key(toUppercase(idata.getMake()), toUppercase(idata.getModel()), toUppercase(idata.getSerialNumber()), idata.getISOSpeed(), idata.getShutterSpeed()));
         auto iter = dfList.find(key);
 
         if (iter == dfList.end()) {
-            dfInfo n(filename, toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
+            dfInfo n(filename, toUppercase(idata.getMake()), toUppercase(idata.getModel()), toUppercase(idata.getSerialNumber()), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
             iter = dfList.emplace(key, n);
         } else {
             while(iter != dfList.end() && iter->second.key() == key && ABS(iter->second.timestamp - idata.getDateTimeAsTS()) > 60 * 60 * 6) { // 6 hour difference
@@ -585,7 +591,7 @@ dfInfo* rtengine::DFManager::Implementation::addFileInfo(const Glib::ustring& fi
             if (iter != dfList.end()) {
                 iter->second.pathNames.push_back(filename);
             } else {
-                dfInfo n(filename, toUppercase(idata.getMake()), toUppercase(idata.getModel()), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
+                dfInfo n(filename, toUppercase(idata.getMake()), toUppercase(idata.getModel()), toUppercase(idata.getSerialNumber()), idata.getISOSpeed(), idata.getShutterSpeed(), idata.getDateTimeAsTS());
                 iter = dfList.emplace(key, n);
             }
         }
@@ -597,13 +603,13 @@ dfInfo* rtengine::DFManager::Implementation::addFileInfo(const Glib::ustring& fi
     return nullptr;
 }
 
-dfInfo* rtengine::DFManager::Implementation::find(const std::string& mak, const std::string& mod, int isospeed, double shut, time_t t)
+dfInfo* rtengine::DFManager::Implementation::find(const std::string& mak, const std::string& mod, const std::string& sn, int isospeed, double shut, time_t t)
 {
     if (dfList.empty()) {
         return nullptr;
     }
 
-    const std::string key(dfInfo::key(mak, mod, isospeed, shut));
+    const std::string key(dfInfo::key(mak, mod, sn, isospeed, shut));
     dfList_t::iterator iter = dfList.find(key);
 
     if (iter != dfList.end()) {
@@ -623,10 +629,10 @@ dfInfo* rtengine::DFManager::Implementation::find(const std::string& mak, const
     } else {
         iter = dfList.begin();
         dfList_t::iterator bestMatch = iter;
-        double bestD = iter->second.distance(mak, mod, isospeed, shut);
+        double bestD = iter->second.distance(mak, mod, sn, isospeed, shut);
 
         for (++iter; iter != dfList.end(); ++iter) {
-            const double d = iter->second.distance(mak, mod, isospeed, shut);
+            const double d = iter->second.distance(mak, mod, sn, isospeed, shut);
 
             if (d < bestD) {
                 bestD = d;
@@ -711,9 +717,9 @@ void rtengine::DFManager::getStat(int& totFiles, int& totTemplates) const
     implementation->getStat(totFiles, totTemplates);
 }
 
-const rtengine::RawImage* rtengine::DFManager::searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
+const rtengine::RawImage* rtengine::DFManager::searchDarkFrame(const std::string& mak, const std::string& mod, const std::string& SN, int iso, double shut, time_t t)
 {
-    return implementation->searchDarkFrame(mak, mod, iso, shut, t);
+    return implementation->searchDarkFrame(mak, mod, SN, iso, shut, t);
 }
 
 const rtengine::RawImage* rtengine::DFManager::searchDarkFrame(const Glib::ustring& filename)
@@ -721,9 +727,9 @@ const rtengine::RawImage* rtengine::DFManager::searchDarkFrame(const Glib::ustri
     return implementation->searchDarkFrame(filename);
 }
 
-const std::vector<rtengine::badPix>* rtengine::DFManager::getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t)
+const std::vector<rtengine::badPix>* rtengine::DFManager::getHotPixels(const std::string& mak, const std::string& mod, const std::string& SN, int iso, double shut, time_t t)
 {
-    return implementation->getHotPixels(mak, mod, iso, shut, t);
+    return implementation->getHotPixels(mak, mod, SN, iso, shut, t);
 }
 
 const std::vector<rtengine::badPix>* rtengine::DFManager::getHotPixels(const Glib::ustring& filename)
diff --git a/rtengine/dfmanager.h b/rtengine/dfmanager.h
index 01ee7479a..8b53a09e6 100644
--- a/rtengine/dfmanager.h
+++ b/rtengine/dfmanager.h
@@ -39,9 +39,9 @@ public:
     void init(const Glib::ustring& pathname);
     Glib::ustring getPathname() const;
     void getStat(int& totFiles, int& totTemplates) const;
-    const RawImage* searchDarkFrame(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
+    const RawImage* searchDarkFrame(const std::string& mak, const std::string& mod, const std::string& sn, int iso, double shut, time_t t);
     const RawImage* searchDarkFrame(const Glib::ustring& filename);
-    const std::vector<badPix>* getHotPixels(const std::string& mak, const std::string& mod, int iso, double shut, time_t t);
+    const std::vector<badPix>* getHotPixels(const std::string& mak, const std::string& mod, const std::string& sn, int iso, double shut, time_t t);
     const std::vector<badPix>* getHotPixels(const Glib::ustring& filename);
     const std::vector<badPix>* getBadPixels(const std::string& mak, const std::string& mod, const std::string& serial) const;
 
diff --git a/rtengine/ffmanager.cc b/rtengine/ffmanager.cc
index c55bc5108..48180ce62 100644
--- a/rtengine/ffmanager.cc
+++ b/rtengine/ffmanager.cc
@@ -38,6 +38,7 @@ inline ffInfo& ffInfo::operator =(const ffInfo &o)
         pathname = o.pathname;
         maker = o.maker;
         model = o.model;
+        sn = o.sn;
         lens = o.lens;
         focallength = o.focallength;
         timestamp = o.timestamp;
@@ -67,6 +68,10 @@ bool ffInfo::operator <(const ffInfo &e2) const
         return false;
     }
 
+    if( this->sn.compare( e2.sn) >= 0 ) {
+        return false;
+    }
+
     if( this->lens.compare( e2.lens) >= 0 ) {
         return false;
     }
@@ -82,10 +87,10 @@ bool ffInfo::operator <(const ffInfo &e2) const
     return true;
 }
 
-std::string ffInfo::key(const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert )
+std::string ffInfo::key(const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focal, double apert )
 {
     std::ostringstream s;
-    s << mak << " " << mod << " ";
+    s << mak << " " << mod << " " << sn << " ";
     s.width(5);
     s << len << " ";
     s.precision( 2 );
@@ -94,7 +99,7 @@ std::string ffInfo::key(const std::string &mak, const std::string &mod, const st
     return s.str();
 }
 
-double ffInfo::distance(const std::string &mak, const std::string &mod, const std::string &len, double focallength, double aperture) const
+double ffInfo::distance(const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focallength, double aperture) const
 {
     if( this->maker.compare( mak) != 0 ) {
         return INFINITY;
@@ -104,6 +109,10 @@ double ffInfo::distance(const std::string &mak, const std::string &mod, const st
         return INFINITY;
     }
 
+    if( this->sn.compare( sn) != 0 ) {
+        return INFINITY;
+    }
+
     if( this->lens.compare( len) != 0 ) {
         return INFINITY;
     }
@@ -337,18 +346,18 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool)
         ffList_t::iterator iter;
 
         if(!pool) {
-            ffInfo n(filename, "", "", "", 0, 0, 0);
+            ffInfo n(filename, "", "", "", "", 0, 0, 0);
             iter = ffList.emplace("", n);
             return &(iter->second);
         }
 
         FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
         /* Files are added in the map, divided by same maker/model,lens and aperture*/
-        std::string key(ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()));
+        std::string key(ffInfo::key(idata.getMake(), idata.getModel(), idata.getSerialNumber(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()));
         iter = ffList.find(key);
 
         if(iter == ffList.end()) {
-            ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS());
+            ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getSerialNumber(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS());
             iter = ffList.emplace(key, n);
         } else {
             while(iter != ffList.end() && iter->second.key() == key && ABS(iter->second.timestamp - ri.get_timestamp()) > 60 * 60 * 6) { // 6 hour difference
@@ -358,7 +367,7 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool)
             if(iter != ffList.end()) {
                 iter->second.pathNames.push_back(filename);
             } else {
-                ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS());
+                ffInfo n(filename, idata.getMake(), idata.getModel(), idata.getSerialNumber(),  idata.getLens(), idata.getFocalLen(), idata.getFNumber(), idata.getDateTimeAsTS());
                 iter = ffList.emplace(key, n);
             }
         }
@@ -391,13 +400,13 @@ void FFManager::getStat( int &totFiles, int &totTemplates)
  *  if perfect matches for make and model are found, then the list is scanned for lesser distance in time
  *  otherwise if no match is found, the whole list is searched for lesser distance in lens and aperture
  */
-ffInfo* FFManager::find( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t )
+ffInfo* FFManager::find( const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focal, double apert, time_t t )
 {
     if( ffList.empty() ) {
         return nullptr;
     }
 
-    std::string key( ffInfo::key(mak, mod, len, focal, apert) );
+    std::string key( ffInfo::key(mak, mod, sn, len, focal, apert) );
     ffList_t::iterator iter = ffList.find( key );
 
     if(  iter != ffList.end() ) {
@@ -417,10 +426,10 @@ ffInfo* FFManager::find( const std::string &mak, const std::string &mod, const s
     } else {
         iter = ffList.begin();
         ffList_t::iterator bestMatch = iter;
-        double bestD = iter->second.distance(  mak, mod, len, focal, apert );
+        double bestD = iter->second.distance(  mak, mod, sn, len, focal, apert );
 
         for( ++iter; iter != ffList.end(); ++iter ) {
-            double d = iter->second.distance(  mak, mod, len, focal, apert );
+            double d = iter->second.distance(  mak, mod, sn, len, focal, apert );
 
             if( d < bestD ) {
                 bestD = d;
@@ -432,9 +441,9 @@ ffInfo* FFManager::find( const std::string &mak, const std::string &mod, const s
     }
 }
 
-RawImage* FFManager::searchFlatField( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t )
+RawImage* FFManager::searchFlatField( const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focal, double apert, time_t t )
 {
-    ffInfo *ff = find( mak, mod, len, focal, apert, t );
+    ffInfo *ff = find( mak, mod, sn, len, focal, apert, t );
 
     if( ff ) {
         return ff->getRawImage();
diff --git a/rtengine/ffmanager.h b/rtengine/ffmanager.h
index f3303f12b..696130171 100644
--- a/rtengine/ffmanager.h
+++ b/rtengine/ffmanager.h
@@ -37,17 +37,18 @@ public:
     std::list<Glib::ustring> pathNames; // other similar dark frames, used for average
     std::string maker;  ///< manufacturer
     std::string model;  ///< model
+    std::string sn;  ///< serial number
     std::string lens;   ///< lens
     double aperture;    ///< aperture in stops
     double focallength; ///< focal length in mm
     time_t timestamp;   ///< seconds since 1 Jan 1970
 
 
-    ffInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod, const std::string & len, double focal, double apert, time_t t)
-        : pathname(name), maker(mak), model(mod), lens(len), aperture(apert), focallength(focal), timestamp(t), ri(nullptr) {}
+    ffInfo(const Glib::ustring &name, const std::string &mak, const std::string &mod,const std::string &sn, const std::string & len, double focal, double apert, time_t t)
+        : pathname(name), maker(mak), model(mod), sn(sn), lens(len), aperture(apert), focallength(focal), timestamp(t), ri(nullptr) {}
 
     ffInfo( const ffInfo &o)
-        : pathname(o.pathname), maker(o.maker), model(o.model), lens(o.lens), aperture(o.aperture), focallength(o.focallength), timestamp(o.timestamp), ri(nullptr) {}
+        : pathname(o.pathname), maker(o.maker), model(o.model), sn(o.sn), lens(o.lens), aperture(o.aperture), focallength(o.focallength), timestamp(o.timestamp), ri(nullptr) {}
 
     ~ffInfo();
 
@@ -55,12 +56,12 @@ public:
     bool operator <(const ffInfo &e2) const;
 
     // Calculate virtual distance between two shots; different model return infinite
-    double distance(const std::string &mak, const std::string &mod, const std::string &lens, double focallength, double aperture) const;
+    double distance(const std::string &mak, const std::string &mod, const std::string &sn, const std::string &lens, double focallength, double aperture) const;
 
-    static std::string key(const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert );
+    static std::string key(const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focal, double apert );
     std::string key()
     {
-        return key( maker, model, lens, focallength, aperture);
+        return key( maker, model, sn, lens, focallength, aperture);
     }
 
     RawImage *getRawImage();
@@ -80,7 +81,7 @@ public:
         return currentPath;
     };
     void getStat( int &totFiles, int &totTemplate);
-    RawImage *searchFlatField( const std::string &mak, const std::string &mod, const std::string &len, double focallength, double apert, time_t t );
+    RawImage *searchFlatField( const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focallength, double apert, time_t t );
     RawImage *searchFlatField( const Glib::ustring filename );
 
 protected:
@@ -89,7 +90,7 @@ protected:
     bool initialized;
     Glib::ustring currentPath;
     ffInfo *addFileInfo(const Glib::ustring &filename, bool pool = true );
-    ffInfo *find( const std::string &mak, const std::string &mod, const std::string &len, double focal, double apert, time_t t );
+    ffInfo *find( const std::string &mak, const std::string &mod, const std::string &sn, const std::string &len, double focal, double apert, time_t t );
 };
 
 extern FFManager ffm;
diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc
index 48d7b0904..93de4328a 100644
--- a/rtengine/rawimagesource.cc
+++ b/rtengine/rawimagesource.cc
@@ -1316,7 +1316,7 @@ void RawImageSource::preprocess  (const RAWParams &raw, const LensProfParams &le
             rid = DFManager::getInstance().searchDarkFrame(raw.dark_frame);
         }
     } else {
-        rid = DFManager::getInstance().searchDarkFrame(idata->getMake(), idata->getModel(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
+        rid = DFManager::getInstance().searchDarkFrame(idata->getMake(), idata->getModel(), idata->getSerialNumber(),  idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
     }
 
     if (rid && settings->verbose) {
@@ -1344,7 +1344,7 @@ void RawImageSource::preprocess  (const RAWParams &raw, const LensProfParams &le
             rif = ffm.searchFlatField(raw.ff_file);
         }
     } else {
-        rif = ffm.searchFlatField(idata->getMake(), idata->getModel(), idata->getLens(), idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS());
+        rif = ffm.searchFlatField(idata->getMake(), idata->getModel(), idata->getSerialNumber(), idata->getLens(), idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS());
     }
 
 
@@ -1407,7 +1407,7 @@ void RawImageSource::preprocess  (const RAWParams &raw, const LensProfParams &le
     bp = nullptr;
 
     if (raw.df_autoselect) {
-        bp = DFManager::getInstance().getHotPixels(idata->getMake(), idata->getModel(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
+        bp = DFManager::getInstance().getHotPixels(idata->getMake(), idata->getModel(), idata->getSerialNumber(), idata->getISOSpeed(), idata->getShutterSpeed(), idata->getDateTimeAsTS());
     } else if (!raw.dark_frame.empty()) {
         bp = DFManager::getInstance().getHotPixels(raw.dark_frame);
     }
diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h
index b9fc916f6..2d4f21137 100644
--- a/rtengine/rtengine.h
+++ b/rtengine/rtengine.h
@@ -141,6 +141,7 @@ public:
     virtual std::string getMake     (unsigned int frame = 0) const = 0;
     /** @return the model of the camera */
     virtual std::string getModel    (unsigned int frame = 0) const = 0;
+    virtual std::string getSerialNumber (unsigned int frame = 0) const = 0;
 
     std::string getCamera   (unsigned int frame = 0) const
     {
diff --git a/rtexif/rtexif.cc b/rtexif/rtexif.cc
index a7125fb9a..3045e330f 100644
--- a/rtexif/rtexif.cc
+++ b/rtexif/rtexif.cc
@@ -305,6 +305,7 @@ bool TagDirectory::CPBDump (const Glib::ustring &commFName, const Glib::ustring
             kf->set_integer ("Common Data", "ISO", cfs->iso);
             kf->set_string ("Common Data", "Lens", cfs->lens);
             kf->set_string ("Common Data", "Make", cfs->camMake);
+            kf->set_string ("Common Data", "SN", cfs->camSN);
             kf->set_string ("Common Data", "Model", cfs->camModel);
 
         } catch (Glib::KeyFileError&) {}
diff --git a/rtgui/cacheimagedata.cc b/rtgui/cacheimagedata.cc
index d44ca28ec..20126035f 100644
--- a/rtgui/cacheimagedata.cc
+++ b/rtgui/cacheimagedata.cc
@@ -193,6 +193,10 @@ int CacheImageData::load (const Glib::ustring& fname)
                     camMake     = keyFile.get_string ("ExifInfo", "CameraMake");
                 }
 
+                if (keyFile.has_key ("ExifInfo", "SerialNumber")) {
+                    camSN     = keyFile.get_string ("ExifInfo", "SerialNumber");
+                }
+
                 if (keyFile.has_key ("ExifInfo", "CameraModel")) {
                     camModel    = keyFile.get_string ("ExifInfo", "CameraModel");
                 }
diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h
index caab1de5b..0995f8816 100644
--- a/rtgui/cacheimagedata.h
+++ b/rtgui/cacheimagedata.h
@@ -62,6 +62,7 @@ public:
     rtengine::IIO_Sample_Format sampleFormat;
     Glib::ustring lens;
     Glib::ustring camMake;
+    Glib::ustring camSN;
     Glib::ustring camModel;
     Glib::ustring filetype;
     Glib::ustring expcomp;
@@ -107,6 +108,7 @@ public:
     double getShutterSpeed (unsigned int frame = 0) const override { return shutter; }
     double getExpComp (unsigned int frame = 0) const override { return atof(expcomp.c_str()); }
     std::string getMake     (unsigned int frame = 0) const override { return camMake; }
+    std::string getSerialNumber     (unsigned int frame = 0) const override { return camSN; }
     std::string getModel    (unsigned int frame = 0) const override { return camModel; }
     std::string getLens     (unsigned int frame = 0) const override { return lens; }
     std::string getOrientation (unsigned int frame = 0) const override { return ""; } // TODO
diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc
index cc8e9ad81..3aece137f 100644
--- a/rtgui/thumbnail.cc
+++ b/rtgui/thumbnail.cc
@@ -824,6 +824,7 @@ int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptr<rtengi
         cfs.exifValid    = true;
         cfs.lens         = idata->getLens();
         cfs.camMake      = idata->getMake();
+        cfs.camSN        = idata->getSerialNumber();
         cfs.camModel     = idata->getModel();
         cfs.rating       = idata->getRating();
 
diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc
index 9c14aeb6e..f093f58a9 100644
--- a/rtgui/toolpanelcoord.cc
+++ b/rtgui/toolpanelcoord.cc
@@ -957,9 +957,10 @@ const rtengine::RawImage* ToolPanelCoordinator::getDF()
         double shutter = imd->getShutterSpeed();
         std::string maker(imd->getMake());
         std::string model(imd->getModel());
+        std::string sn(imd->getSerialNumber());
         time_t timestamp = imd->getDateTimeAsTS();
 
-        return rtengine::DFManager::getInstance().searchDarkFrame(maker, model, iso, shutter, timestamp);
+        return rtengine::DFManager::getInstance().searchDarkFrame(maker, model, sn, iso, shutter, timestamp);
     }
 
     return nullptr;
@@ -980,10 +981,11 @@ rtengine::RawImage* ToolPanelCoordinator::getFF()
         double focallength = imd->getFocalLen();
         std::string maker(imd->getMake());
         std::string model(imd->getModel());
+        std::string sn;
         std::string lens(imd->getLens());
         time_t timestamp = imd->getDateTimeAsTS();
 
-        return rtengine::ffm.searchFlatField(maker, model, lens, focallength, aperture, timestamp);
+        return rtengine::ffm.searchFlatField(maker, model, sn, lens, focallength, aperture, timestamp);
     }
 
     return nullptr;
