Ask Your Question
0

pyrDown, pyrUp vs resize (blur operations)

asked 2016-06-19 09:03:23 -0600

VanGog gravatar image

updated 2016-06-19 09:11:17 -0600

What are pros and cons of pyrDown? What is quality and performance difference between pyrDown/pyrUp and resize? I have created this code to make tests. I am using 2557x3993 RGB image gained from scanner (the image contains mainly BW pixels, but few lines of small red text too).

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

using namespace cv;

int main( int argc, char** argv )
{

  /// General instructions
  printf( "\n Zoom In-Out demo  \n " );
  printf( "------------------ \n" );
  printf( " * [+] -> Zoom in  \n" );
  printf( " * [-] -> Zoom out \n" );
  printf( " * [ESC] -> Close program \n \n" );

  char* window_name_1 = "Pyramids Demo";
  char* window_name_2 = "Resize Demo";

  cv::Mat src, dst_pyr, tmp_pyr;
  cv::Mat dst_resize, tmp_resize;

  /// Test image - Make sure it s divisible by 2^{n}
  src = cv::imread( "../../data/strana210.jpg" );
  if( !src.data )
    { printf(" No data! -- Exiting the program \n");
      return -1; }

  tmp_pyr = src;
  dst_pyr = tmp_pyr;

  dst_resize = src;
  tmp_resize = dst_resize;

  /// Create window
  cv::namedWindow( window_name_1, CV_WINDOW_AUTOSIZE );
  cv::imshow( window_name_1, dst_pyr );

  cv::namedWindow( window_name_2, CV_WINDOW_AUTOSIZE );
  cv::imshow( window_name_2, dst_pyr );

  double t1, t2;

  /// Loop
  while( true )
  {
    int c;
    c = cv::waitKey(10);

    if( (char)c == 27 )
      { break; }
    if( (char)c == '+' )
      { 
      t1 = (double)getTickCount();
      cv::pyrUp( tmp_pyr, dst_pyr, Size( tmp_pyr.cols*2, tmp_pyr.rows*2 ) );
      t1 = 1000*((double)getTickCount()-t1) / getTickFrequency() ;
      t2 = (double)getTickCount();
      cv::resize( tmp_resize, dst_resize, Size( tmp_resize.cols*2, tmp_resize.rows*2 ) );
      t2 = 1000*((double)getTickCount()-t2) / getTickFrequency() ;
      printf( "** Zoom In: Image x 2 \n" );
      std::cout << "pyrUp: " << t1 << "ms" << std::endl;
      std::cout << "resize up: " << t2 << "ms" << std::endl;
       std::cout << std::endl;
      }
    else if( (char)c == '-' )
     { 
       t1 = (double)getTickCount();
       cv::pyrDown( tmp_pyr, dst_pyr, Size( tmp_pyr.cols/2, tmp_pyr.rows/2 ) );
       t1 = 1000*((double)getTickCount()-t1) / getTickFrequency() ;
       t2 = (double)getTickCount();
       cv::resize( tmp_resize, dst_resize, Size( tmp_resize.cols/2, tmp_resize.rows/2 ) );
       t2 = 1000*((double)getTickCount()-t2) / getTickFrequency() ;

       printf( "** Zoom Out: Image / 2 \n" );
       std::cout << "pyrDown: " << t1 << "ms" << std::endl;
       std::cout << "resize down: " << t2 << "ms" << std::endl;
       std::cout << std::endl;
     }

    cv::imshow( window_name_1, dst_pyr );
    cv::imshow( window_name_2, dst_resize );
    tmp_pyr = dst_pyr;
    tmp_resize = dst_resize;
  }
  return 0;
}

Now I press "-" few times and here are the results:

Debug version:

** Zoom Out: Image / 2 pyrDown: 113.24ms resize down: 56.1988ms

** Zoom Out: Image / 2 pyrDown: 41.836ms resize down: 8.95756ms

** Zoom Out: Image / 2 pyrDown: 18.0705ms resize down: 12.6991ms

** Zoom Out: Image / 2 pyrDown: 4.68942ms resize down: 6.21811ms

** Zoom Out: Image / 2 pyrDown: 1.23563ms resize down: 1.62395ms

Release version:

** Zoom Out: Image / 2 pyrDown: 119.267ms resize down: 59.2019ms

** Zoom Out: Image / 2 pyrDown: 29.2641ms resize down: 8.74413ms

** Zoom Out: Image / 2 pyrDown: 18.1238ms resize down: 12.7287ms

** Zoom Out: Image / 2 pyrDown: 4.63131ms resize down: 6.25275ms

** Zoom Out: Image / 2 pyrDown: 1.2686ms resize down: 1.6301ms

Zoom In with Release version: ** Zoom In: Image x 2 pyrUp: 1.3809ms resize up: 2.2338ms

** Zoom In: Image x 2 pyrUp: 5.29369ms resize up: 5.08109ms

** Zoom In: Image ... (more)

edit retag flag offensive close merge delete

Comments

For a fair comparison you should use cv::resize with the INTER_AREA interpolation mode as that's what you should use for downsampling.

SR gravatar imageSR ( 2016-11-06 16:14:56 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2016-06-19 21:30:11 -0600

Tetragramm gravatar image

The Gaussian Blur removes a significant amount of noise. For the algorithms that use it such as ORB, Optical Flow Pyr LK and others, that noise can cause significant accuracy problems. It is not something to use wherever and whenever you need a smaller image, that is not it's purpose. But for many multi-scale algorithms, a resize is not enough.

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-06-19 09:03:23 -0600

Seen: 7,456 times

Last updated: Jun 19 '16