فصل دوم - حوزهٔ مکان

بزرگ‌نمایی و کوچک‌نمایی تصویر

معمولاً نیاز است که اندازهٔ یک عکس را تغییر داد. در اُ سی وی به منظور تغیر اندازهٔ عکس‌ها تابع تبدیل هندسی resize وجود دارد ولی در این بخش به بیان مفهوم هرم تصویر می‌پردازیم که کاربردهای زیادی در برنامه‌های بینایی دارد.

هرم تصویر مجموعه‌ای از تصاویر است که همگی از یک تصویر اصلی سرچشمه گرفته‌اند و به ترتیب کوچک می‌شوند تا به یک اندازهٔ مشخص برسند.

دو نوع هرم تصویر داریم:

  • هرم گوسی1: در این روش برای ساخت هرم از میانگین‌گیری گوسی استفاده می‌شود.
  • هرم لاپلاسی2: مشابه هرم گوسی است با این تفاوت که از یک تبدیل لاپلاس برای ساخت هرم استفاده می‌کند.

هرم موجود در اُ سی وی از نوع گوسی است.

هرم گوسی:

هرم را به صورت یک مجموعه از لایه‌ها در نظر بگیرید که هر چه لایه در سطح بالاتری قرار گرفته باشد، کوچک‌تر خواهد بود.

هرم تصویر (سطح زیرین تصویر اصلی است)
هرم تصویر (سطح زیرین تصویر اصلی است)

لایه‌ها از پایین به بالا شماره گذاری شده‌اند. پس لایهٔ i+1 که با$G_{i + 1}$ نشان داده می‌شود، از لایهٔ i که با $G_{i}$ نشان داده می‌شود کوچکتر است.

در هرم گوسی برای تولید لایهٔ i+1 از روی لایه i، به شیوهٔ زیر عمل می‌کنیم:

  • $G_{i}$ را با یک کرنل گوسی زیر کانوالو می‌کنیم:

    mage5

  • همهٔ سطرها و ستون‌های زوج را پاک می‌کنیم.

عکس به دست آمده دقیقاً یک چهارم عکس پیشین خواهد بود. با تکرار فرایند بالا روی عکس اصلی (یعنی $G_0$)، می‌توان تمام هرم را درست کرد.

رویهٔ بالا به منظور کوچک نمایی تصویر بود. برای بزرگ‌نمایی تصویر باید مراحل زیر را انجام دهیم:

  • ابتدا ابعاد لایه i را دو برابر کرده و سطرها و ستون‌های زوج آن را با صفر پر می‌کنیم.

  • تصویر به دست آمده در مرحله قبل را در کرنل بالا (البته با درایه‌های آن که در 4 ضرب شده‌اند) کانوالو می‌کنیم. با این کار مقدار پیکسل‌های جدید معرفی شده در مرحلهٔ قبل که با صفر پر شده بودند، تخمین زده می‌شوند.

دو رویهٔ بالا (یعنی کوچک نمایی و بزرگ‌نمایی)، در توابع pyrDown و pyrUp پیاده سازی شده‌اند.

کد

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

using namespace cv;

/// Global variables
Mat src, dst, tmp;
char* window_name = "Pyramids Demo";

/**
 * @function main
 */
int main( int argc, char** argv )
{
  /// General instructions
  printf( "\n Zoom In-Out demo  \n " );
  printf( "------------------ \n" );
  printf( " * [u] -> Zoom in  \n" );
  printf( " * [d] -> Zoom out \n" );
  printf( " * [ESC] -> Close program \n \n" );

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

  tmp = src;
  dst = tmp;

  /// Create window
  namedWindow( window_name, CV_WINDOW_AUTOSIZE );
  imshow( window_name, dst );

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

    if( (char)c == 27 )
      { break; }
    if( (char)c == 'u' )
      { pyrUp( tmp, dst, Size( tmp.cols*2, tmp.rows*2 ) );
        printf( "** Zoom In: Image x 2 \n" );
      }
    else if( (char)c == 'd' )
     { pyrDown( tmp, dst, Size( tmp.cols/2, tmp.rows/2 ) );
       printf( "** Zoom Out: Image / 2 \n" );
     }

    imshow( window_name, dst );
    tmp = dst;
  }
  return 0;
}

توضیح

در خط 44 مشخص شده که اگر کاربر کلید ESC را فشار دهد از برنامه خارج شود.

در خط 46 مشخص شده که اگر کاربر کلید u را فشار دهد عمل بزرگ‌نمایی توسط تابع pyrUp انجام شود. این تابع سه آرگومان دارد:

  • tmp: تصویر ورودی است. در ابتدا برابر با تصویر src است.

  • dst: تصویر خروجی است (همان که برروی صفحه نمایش داده خواهد شد و در حقیقت دو برابر تصویر ورودی است).

  • Size(tmp.cols\*2, tmp.rows\*2): اندازهٔ تصویر خروجی است. از آنجایی که قصد بزرگ‌نمایی داریم، تابع pyrUp انتظار دارد که این اندازه دو برابر اندازهٔ تصویر ورودی باشد.

در خط 50 مشخص شده که اگر کاربر کلید d را فشار دهد عمل کوچک نمایی توسط تابع pyrDown انجام شود. این تابع سه آرگومان دارد:

  • tmp: تصویر ورودی است. در ابتدا برابر با تصویر src است.

  • dst: تصویر خروجی است (همان که برروی صفحه نمایش داده خواهد شد و در حقیقت نصف تصویر ورودی است).

  • Size(tmp.cols/2 , tmp.rows/2): اندازهٔ تصویر خروجی است. از آنجایی که قصد کوچک نمایی داریم، تابع pyrDown انتظار دارد که این اندازه نصف اندازهٔ تصویر ورودی باشد.

توجه داشته باشید که ابعاد تصویر ورودی به توابع pyrDown و pyrUp باید حتماً ضریبی از دو باشد، در غیر این صورت خطایی مبتنی بر رعایت نکردن این محدودیت دریافت خواهید کرد.

خروجی

برنامه را به صورت زیر اجرا می‌کنیم:

PyrUpDown.exe "PICTURES /1.jpg"
تصویر ورودی
تصویر ورودی
نتیجه دو بار کوچک‌نمایی تصویر اصلی
نتیجهٔ دو بار کوچک‌نمایی تصویر اصلی
نتیجه دو بار بزرگ‌نمایی تصویر کوچک شده
نتیجه دو بار بزرگ‌نمایی تصویر کوچک شده

همانطور که می‌بینید تصویر آخر دارای وضوح کمتری نسبت به تصویر ورودی است.


  1. Gaussian pyramid ↩

  2. Laplacian pyramid ↩