Commits

David Lin committed 70153e4

Add Warping

Comments (0)

Files changed (7)

project2/photomerge/source-1/Makefile

 all: photomerge
 
 photomerge: photomerge.o Image.o jpgd.o jpge.o GaussianFilter.o \
-            feature.o alignment.o
+            feature.o alignment.o \
+            warping.o
 	$(CXX) -o $@ $^ $(LIBS)
 
 photomerge.o: main.cpp Image.h

project2/photomerge/source-1/alignment.cpp

       float dx = 0.0f;
       float dy = 0.0f;
       bool found = false;
-    
+      
       for(int k = 0; k < matches.size(); ++k)
         if(matches[k].first == i-1 && matches[k].second == i)
         {
           found = true;
           break;
         }
-    
+      
       if(found)
       {
         tx[i] = tx[i-1] + dx;
   }
   
   ColorImage produceResult(int numImages, const ColorImage* sourceImages,
-                           const std::vector<ImageMatchingPair>& matches)
+                           const std::vector<ImageMatchingPair>& matches,
+                           bool useICP)
   {
     std::vector<float> tx(numImages, 0.0f);
     std::vector<float> ty(numImages, 0.0f);
     std::vector<float> th(numImages, 0.0f);
-
-
-	for(int i=0; i<numImages-1; i++){
-		for(int j=0; j<matches.size(); j++){
-			if((matches[j].first == i) && (matches[j].second == i+1)){
-				float** _s = new float*[matches[j].count];
-				float** _d = new float*[matches[j].count];
-
-				for(int k = 0; k< matches[j].count; k++){
-					_s[k] = new float[2];
-					_d[k] = new float[2];
-					_s[k][0] = matches[j].x2[k];
-					_s[k][1] = matches[j].y2[k];
-					_d[k][0] = matches[j].x1[k];
-					_d[k][1] = matches[j].y1[k];
-				}
-				transition(matches[j].count, _s, _d, &th[i+1], &tx[i+1], &ty[i+1]);
-			}
-		}
-	}
-
-	float _t, _x, _y;
-	for(int i=0; i<numImages-1; i++){
-		_t = th[i] + th[i+1];
-		_x = tx[i] + tx[i+1]*cos(th[i]) - ty[i+1]*sin(th[i]);
-		_y = ty[i] + tx[i+1]*sin(th[i]) + ty[i+1]*cos(th[i]);
-		th[i+1] = _t;
-		tx[i+1] = _x;
-		ty[i+1] = _y;
-	}
-	
-	return alignment(numImages, sourceImages, ty, tx, th);/*usiing diffrent coordinate x<->i, y<->j*/
-
-	//pre_alignment(numImages, sourceImages, tx, ty, th, matches);
-
-    //return alignment(numImages, sourceImages, tx, ty, th);
+    
+    if(useICP)
+    {
+      for(int i=0; i<numImages-1; i++){
+        for(int j=0; j<matches.size(); j++){
+          if((matches[j].first == i) && (matches[j].second == i+1)){
+            float** _s = new float*[matches[j].count];
+            float** _d = new float*[matches[j].count];
+            
+            for(int k = 0; k< matches[j].count; k++){
+              _s[k] = new float[2];
+              _d[k] = new float[2];
+              _s[k][0] = matches[j].x2[k];
+              _s[k][1] = matches[j].y2[k];
+              _d[k][0] = matches[j].x1[k];
+              _d[k][1] = matches[j].y1[k];
+            }
+            transition(matches[j].count, _s, _d, &th[i+1], &tx[i+1], &ty[i+1]);
+          }
+        }
+      }
+      
+      float _t, _x, _y;
+      for(int i=0; i<numImages-1; i++){
+        _t = th[i] + th[i+1];
+        _x = tx[i] + tx[i+1]*cos(th[i]) - ty[i+1]*sin(th[i]);
+        _y = ty[i] + tx[i+1]*sin(th[i]) + ty[i+1]*cos(th[i]);
+        th[i+1] = _t;
+        tx[i+1] = _x;
+        ty[i+1] = _y;
+      }
+      
+      return alignment(numImages, sourceImages, ty, tx, th);
+      /*usiing diffrent coordinate x<->i, y<->j*/
+    }
+    
+    pre_alignment(numImages, sourceImages, tx, ty, th, matches);
+    
+    return alignment(numImages, sourceImages, tx, ty, th);
   }
-
+  
 }

project2/photomerge/source-1/alignment.h

 namespace vfx
 {
   ColorImage produceResult(int numImages, const ColorImage* sourceImages,
-                           const std::vector<ImageMatchingPair>& matches);
+                           const std::vector<ImageMatchingPair>& matches,
+                           bool useICP);
 
   
 }

project2/photomerge/source-1/feature.cpp

 {
   
   enum{ 
-    FEATURE_DESC_WIDTH = 8,
-    FEATURE_DESC_SIZE = 64,
+    FEATURE_DESC_WIDTH = 20,
+    FEATURE_DESC_SIZE = 400,
     FEATURE_DESC_WINDOW_SIZE = 40
   };
   

project2/photomerge/source-1/main.cpp

 #include "Image.h"
 #include "feature.h"
 #include "alignment.h"
+#include "warping.h"
 
 #include <cstdio>
 #include <cstdlib>
 int main(int argc, char* argv[])
 {
   
-  
-#if 0
+#if 0 // SUCCESS
   ColorImage imgs[] = {
-    ImageCreator::loadFromJpeg("../images/_denny/input/1.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/2.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/3.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/4.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/5.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/6.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/7.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/8.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/9.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/10.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/11.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/12.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/13.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/14.jpg"),
-    ImageCreator::loadFromJpeg("../images/_denny/input/15.jpg")
+    ImageCreator::loadFromJpeg("../images/_parrington/input/1.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/2.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/3.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/4.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/5.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/6.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/7.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/8.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/9.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/10.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/11.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/12.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/13.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/14.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/15.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/16.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/17.jpg"),
+    ImageCreator::loadFromJpeg("../images/_parrington/input/18.jpg")
+  };
+  const float f_lengthes[18] = {
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f
   };
+  const int h_offsets[18] = {0};
+  const bool useICP = true;
 #endif
   
-#if 0
+#if 1 // SUCCESS
   ColorImage imgs[] = {
     ImageCreator::loadFromJpeg("../images/_grail/input/grail00.jpg"),
     ImageCreator::loadFromJpeg("../images/_grail/input/grail01.jpg"),
     ImageCreator::loadFromJpeg("../images/_grail/input/grail16.jpg"),
     ImageCreator::loadFromJpeg("../images/_grail/input/grail17.jpg")
   };
-#endif
-  
-#if 0
-  ColorImage imgs[] = {
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8709.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8710.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8711.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8712.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8713.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8714.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8715.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8716.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8717.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8718.JPG"),
-    ImageCreator::loadFromJpeg("../images/_csie/input/IMG_8719.JPG")
+  const float f_lengthes[] = {
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f,
+    70.0f
   };
+  const int h_offsets[18] = {0};
+  const bool useICP = true;
 #endif
 
-#if 0
+#if 0 // SO SO
   ColorImage imgs[] = {
-    ImageCreator::loadFromJpeg("../images/dk_1/DSCN1557.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_1/DSCN1558.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_1/DSCN1559.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_1/DSCN1560.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_1/DSCN1561.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_1/DSCN1562.JPG")
+    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1566-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1567-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1568-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1569-a.JPG")
   };
-#endif
-
-#if 0
-  ColorImage imgs[] = {
-    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1566.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1567.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1568.JPG"),
-    ImageCreator::loadFromJpeg("../images/dk_2/DSCN1569.JPG")
+  const float f_lengthes[] = {
+    27.0f,
+    27.0f,
+    27.0f,
+    27.0f
+  };
+  const int h_offsets[] = {
+    20,
+    20,
+    20,
+    20
   };
 #endif
 
   };
 #endif
 
-#if 1
+#if 0
   ColorImage imgs[] = {
     ImageCreator::loadFromJpeg("../images/dk_3/DSCN1571.JPG"),
     ImageCreator::loadFromJpeg("../images/dk_3/DSCN1572.JPG"),
   
 #if 0
   ColorImage imgs[] = {
+    ImageCreator::loadFromJpeg("../images/dk_4/DSCN1581.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_4/DSCN1582.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_4/DSCN1583.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_4/DSCN1584.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_4/DSCN1585.JPG")
+  };
+#endif
+  
+#if 0
+  ColorImage imgs[] = {
+    ImageCreator::loadFromJpeg("../images/dk_5/DSCN1615-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_5/DSCN1616-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_5/DSCN1617-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_5/DSCN1618-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_5/DSCN1619-a.JPG")
+  };
+  const float f_lengthes[] = {
+    //30.5f,
+    24.0f,
+    24.0f,
+    24.0f,
+    24.0f,
+    24.0f
+  };
+  const int h_offsets[] = {
+    100,
+    100,
+    100,
+    100,
+    100
+  };
+  
+#endif
+  
+#if 0
+  ColorImage imgs[] = {
+    ImageCreator::loadFromJpeg("../images/dk_6/DSCN1623-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_6/DSCN1624-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_6/DSCN1626-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_6/DSCN1628-a.JPG"),
+    ImageCreator::loadFromJpeg("../images/dk_6/DSCN1629-a.JPG")
+  };
+  const float f_lengthes[] = {
+    32.0f,
+    32.0f,
+    32.0f,
+    32.0f,
+    32.0f
+  };
+#endif
+  
+#if 0
+  ColorImage imgs[] = {
     ImageCreator::loadFromJpeg("../images/_lake/input/P1030467.JPG"),
     ImageCreator::loadFromJpeg("../images/_lake/input/P1030468.JPG"),
     ImageCreator::loadFromJpeg("../images/_lake/input/P1030469.JPG"),
 #endif
 
   int num = sizeof(imgs)/sizeof(imgs[0]);
-  auto matches = featureDetectionAndMatching(num, imgs);
   
-  featureRANSAC(matches);
-
-  auto result = produceResult(num, imgs, matches);
+  cylindrical_warp(num, imgs, h_offsets, f_lengthes);
+  
+  if(true)
+  {
+    auto matches = featureDetectionAndMatching(num, imgs);
+    
+    //cylindrical_warp(num, imgs, matches, f_lengthes);
+    
+    if(!useICP)
+      featureRANSAC(matches);
+    
+    auto result = produceResult(num, imgs, matches, useICP);
+    
+    ImageCreator::saveToJpeg("result.jpg", result);
+  }
   
-  ImageCreator::saveToJpeg("result.jpg", result);
+  if(false)
+  {
+    char buf[128];
+    for(int i = 0; i < num; ++i)
+    {
+      std::sprintf(buf, "warp-%d.jpg", i);
+      ImageCreator::saveToJpeg(buf, imgs[i]);
+    }
+  }
   
   return 0;
 }

project2/photomerge/source-1/warping.cpp

   
   const float FILM_WIDTH = 36.0f; // mm
 
-  void cylindrical_warp(int numImages, 
-                        ColorImage* images, 
-                        const std::vector<float>& focalLengthes)
+  void cylindrical_warp(int numImages, ColorImage* images, 
+                        const int* h_offsets, 
+                        const float* focalLengthes)
   {
-    //std::vector<float> theta0(numImages);
-    //for(int i = 0; i < numImages; ++i)
-    //  theta0[i] = std::atan2(FILM_WIDTH * 0.5f, focalLengthes[i]);
-    
     for(int i = 0; i < numImages; ++i)
     {
       const int w = images[i].width(), h = images[i].height();
-      float f = focalLengthes[i] * images[i].width() / FILM_WIDTH;
-      float xc1 = images[i].width() * 0.5f;
-      float yc1 = images[i].height() * 0.5f;
+      float f = focalLengthes[i] * w / FILM_WIDTH;
+      
+      float xc = w * 0.5f, yc = h * 0.5f + h_offsets[i];
       
       ColorImage dst = ImageCreator::createColorImage(w, h);
-
+      
+      const int rs = images[i].row(), rd = dst.row();
+      const PixARGB* pSrc = images[i].data();
+      PixARGB* pDst = dst.data();
+      
+      for(int dy = 0; dy < h; ++dy)
+      {
+        PixARGB* d = pDst + dy * rd;
+        
+        for(int dx = 0; dx < w; ++dx)
+        {
+          float xb = dx - xc, yb = dy - yc;
+          float xb_f = xb / f;
+          
+          float x = f * std::tan(xb_f);
+          float y = yb / std::fabs(std::cos(xb_f));
+          
+          int ix = (int)x + xc;
+          int iy = (int)y + yc;
+          
+          if(ix >= 0 && iy >= 0 && ix < w && iy < h)
+            d[dx] = pSrc[ ix + iy * rs ];
+          else
+            d[dx] = makePixel<PixARGB>(0,0,0,0);
+        }
+      }
+      
+      images[i] = dst; // replace
+    }
+  }
+  
+  /*
+  void cylindrical_warp(int numImages, ColorImage* images, 
+                        std::vector<ImageMatchingPair>& matches, 
+                        const float* focalLengthes)
+  {
+    // Warp Images
+    cylindrical_warp(numImages, images, focalLengthes);
+    
+    // Warp Keypoints
+    
+    int n = (int) matches.size();
+    for(int i = 0; i < n; ++i)
+    {
+      ImageMatchingPair& mat = matches[i];
+      
+      { // First
+        const int imgId = mat.first;
+        const ColorImage& img = images[imgId];
+        
+        const int w = img.width(), h = img.height();
+        float f = focalLengthes[imgId] * w / FILM_WIDTH;
+        float xc = w * 0.5f, yc = h * 0.5f;
+        
+        for(int k = 0; k < mat.count; ++k)
+        {
+          float x = mat.x1[k] - xc, y = mat.y1[k] - yc;
+          float x_f = x / f;
+          float xb = f * std::atan( x_f );
+          float yb = y / std::sqrt( x_f * x_f + 1 );
+          mat.x1[k] = xb + xc, mat.y1[k] = yb + yc;
+        }
+      }
+      
+      { // Second
+        const int imgId = mat.second;
+        const ColorImage& img = images[imgId];
+        
+        const int w = img.width(), h = img.height();
+        float f = focalLengthes[imgId] * w / FILM_WIDTH;
+        float xc = w * 0.5f, yc = h * 0.5f;
+        
+        for(int k = 0; k < mat.count; ++k)
+        {
+          float x = mat.x2[k] - xc, y = mat.y2[k] - yc;
+          float x_f = x / f;
+          float xb = f * std::atan( x_f );
+          float yb = y / std::sqrt( x_f * x_f + 1 );
+          mat.x2[k] = xb + xc, mat.y2[k] = yb + yc;
+        }
+      }
     }
-
   }
+  */
 
 }

project2/photomerge/source-1/warping.h

 
 namespace vfx
 {
-
+  
+  void cylindrical_warp(int numImages, ColorImage* images, 
+                        const int* h_offsets, 
+                        const float* focalLengthes);
+  
+  void cylindrical_warp(int numImages, ColorImage* images, 
+                        std::vector<ImageMatchingPair>& matches, 
+                        const float* focalLengthes);
+  
 }