OpenCV 【二十三】Remapping 重映射¶

目錄

1.1目標

1.2 理論

1.3 代碼

1.4 運行結果


1.1目標

展示如何使用OpenCV函數 remap 來實現簡單重映射.

1.2 理論

  • 把一個圖像中一個位置的像素放置到另一個圖片指定位置的過程.

  • 爲了完成映射過程, 有必要獲得一些插值爲非整數像素座標,因爲源圖像與目標圖像的像素座標不是一一對應的.

  • 我們通過重映射來表達每個像素的位置 (x,y) :

    g(x,y) = f ( h(x,y) )

    這裏 g() 是目標圖像, f() 是源圖像, h(x,y) 是作用於 (x,y) 的映射方法函數.

  • 讓我們來思考一個快速的例子. 想象一下我們有一個圖像 I , 我們想滿足下面的條件作重映射:

    h(x,y) = (I.cols - x, y )

    會發生什麼? 圖像會按照 x 軸方向發生翻轉. 例如, 源圖像如下:

    Original test image

    看到紅色圈關於 x 的位置改變( x 軸水平翻轉):

    Original test image

  • 通過 OpenCV 的函數 remap 提供一個簡單的重映射實現.

 

1.3 代碼

  1. 本程序做什麼?

    • 裝載一幅圖像.

    • 程序按秒循環, 在一個窗口中順序出現4種重映射過程對相同的圖像.

    • 等待用戶按 ‘ESC’ 鍵退出程序。

  2. 下面是本教程代碼. 你也可以從 這裏 下載。

#include "opencv2/highgui/highgui.hpp"
 #include "opencv2/imgproc/imgproc.hpp"
 #include <iostream>
 #include <stdio.h>
​
 using namespace cv;
​
 /// Global variables
 Mat src, dst;
 Mat map_x, map_y;
 char* remap_window = "Remap demo";
 int ind = 0;
​
 /// Function Headers
 void update_map( void );
​
 /**
 * @function main
 */
 int main( int argc, char** argv )
 {
   /// Load the image
   src = imread( argv[1], 1 );
​
  /// Create dst, map_x and map_y with the same size as src:
  dst.create( src.size(), src.type() );
  map_x.create( src.size(), CV_32FC1 );
  map_y.create( src.size(), CV_32FC1 );
​
  /// Create window
  namedWindow( remap_window, CV_WINDOW_AUTOSIZE );
​
  /// Loop
  while( true )
  {
    /// Each 1 sec. Press ESC to exit the program
    int c = waitKey( 1000 );
​
    if( (char)c == 27 )
      { break; }
​
    /// Update map_x & map_y. Then apply remap
    update_map();
    remap( src, dst, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) );
​
    /// Display results
    imshow( remap_window, dst );
  }
  return 0;
 }
​
 /**
 * @function update_map
 * @brief Fill the map_x and map_y matrices with 4 types of mappings
 */
 void update_map( void )
 {
   ind = ind%4;
​
   for( int j = 0; j < src.rows; j++ )
   { for( int i = 0; i < src.cols; i++ )
       {
         switch( ind )
         {
           case 0:
             if( i > src.cols*0.25 && i < src.cols*0.75 && j > src.rows*0.25 && j < src.rows*0.75 )
               {
                 map_x.at<float>(j,i) = 2*( i - src.cols*0.25 ) + 0.5 ;
                 map_y.at<float>(j,i) = 2*( j - src.rows*0.25 ) + 0.5 ;
                }
             else
               { map_x.at<float>(j,i) = 0 ;
                 map_y.at<float>(j,i) = 0 ;
               }
                 break;
           case 1:
                 map_x.at<float>(j,i) = i ;
                 map_y.at<float>(j,i) = src.rows - j ;
                 break;
           case 2:
                 map_x.at<float>(j,i) = src.cols - i ;
                 map_y.at<float>(j,i) = j ;
                 break;
           case 3:
                 map_x.at<float>(j,i) = src.cols - i ;
                 map_y.at<float>(j,i) = src.rows - j ;
                 break;
         } // end of switch
       }
    }
  ind++;
}

 

1.4 運行結果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章