文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

目标

在这篇教程中您将学习如何:

  • 利用OpenCV中copyMakeBorder函数设置边框(给图像进行额外填充)

理论

注意

以下结束属于Bradski and Kaehler《Learning OpenCV》一书。

  1. 在之前的教程中我们学习了如何对图像进行卷积操作。如何处理边界是经常需要考虑到的问题。如何需要计算的点处于边界上我们该如何进行卷积运算?
  2. 大多数OpenCV函数是通过拷贝一幅图像到另一个略大的图像中然后自动填补边界实现(通过下面的示例代码中解释的任意一种方法)。通过这种方法对所有的点进行卷积操作都没有问题。(额外填补的部分在操作结束后将去除)
  3. 在这篇教程中,我们简要的介绍2种为图像添加(边界)的方法:

        1.BORDER_CONSTANT:为图片添加一个常量边界(即黑色或者0

        2.BORDER_REPLICATE:行或者列的新边界是原始边界的复制。

        更多的内容可以在代码部分查看

第 1 段(可获 2 积分)

代码

    1.这个程序实现了什么功能?

  • 加载一张图片
  • 让用户选择以何种方式向图片中加载边框。有两种选项:

        1.Constant value border:添加一个常量数值的边框。这个值每0.5秒将随机更新。

        2.Replicated border: 边界的像素值将会由原始图像的边界复制得到。

        用户通过输入'c'(常量)和'r'(复制)来选择

  • 当用户输入'ESC'时程序结束。

    2.本教程代码如下所示。你也可以从里下载。

第 2 段(可获 2 积分)
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>

using namespace cv;

/// 全局变量
Mat src, dst;
int top, bottom, left, right;
int borderType;
Scalar value;
char* window_name = "copyMakeBorder Demo";
RNG rng(12345);

/** @主函数  */
int main( int argc, char** argv )
{

  int c;

  /// 加载一张图片
  src = imread( argv[1] );

  if( !src.data )
  { return -1;
    printf(" No data entered, please enter the path to an image file \n");
  }

  /// 程序使用说明
  printf( "\n \t copyMakeBorder Demo: \n" );
  printf( "\t -------------------- \n" );
  printf( " ** Press 'c' to set the border to a random constant value \n");
  printf( " ** Press 'r' to set the border to be replicated \n");
  printf( " ** Press 'ESC' to exit the program \n");

  /// 创建窗口
  namedWindow( window_name, CV_WINDOW_AUTOSIZE );

  /// 为滤波器设置参数
  top = (int) (0.05*src.rows); bottom = (int) (0.05*src.rows);
  left = (int) (0.05*src.cols); right = (int) (0.05*src.cols);
  dst = src;

  imshow( window_name, dst );

  while( true )
    {
      c = waitKey(500);

      if( (char)c == 27 )
        { break; }
      else if( (char)c == 'c' )
        { borderType = BORDER_CONSTANT; }
      else if( (char)c == 'r' )
        { borderType = BORDER_REPLICATE; }

      value = Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );
      copyMakeBorder( src, dst, top, bottom, left, right, borderType, value );

      imshow( window_name, dst );
    }

  return 0;
}

 

第 3 段(可获 2 积分)

解释

    1.首先我们先声明需要使用的变量:

Mat src, dst;
int top, bottom, left, right;
int borderType;
Scalar value;
char* window_name = "copyMakeBorder Demo";
RNG rng(12345);

    特别值得关注的变量rng是一个随机数生成器。我们使用它来生成随机的边框颜色,我们很快就会看到。

    2.和以前一样我们加载图片src

src = imread( argv[1] );

if( !src.data )
{ return -1;
  printf(" No data entered, please enter the path to an image file \n");
}

    3.在给说一个简短的程序使用说明后,我们创建一个窗口:

namedWindow( window_name, CV_WINDOW_AUTOSIZE );

    4.现在我们初始化定义了边界大小的参数(右边界)。我们定义它们为原图像src5%的大小。

top = (int) (0.05*src.rows); bottom = (int) (0.05*src.rows);
left = (int) (0.05*src.cols); right = (int) (0.05*src.cols);

    5.程序从一个while循环开始。如果用户按下了'c'或者'r'键,变量borderType将会获得 BORDER_CONSTANT或者BORDER_REPLICATE代表的值:

while( true )
 {
   c = waitKey(500);

   if( (char)c == 27 )
     { break; }
   else if( (char)c == 'c' )
     { borderType = BORDER_CONSTANT; }
   else if( (char)c == 'r' )
     { borderType = BORDER_REPLICATE; }

    6.在每次迭代后(每隔0.5秒),变量value将被更新…

value = Scalar( rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255) );

    这个值将通过由RNG变量rng生成的随机值在[0,255]的范围内随机选择一个值。

    7.最后,我们调用函数copyMakeBorder用于添加给子的边界:

copyMakeBorder( src, dst, top, bottom, left, right, borderType, value );

    这些参数分别是:

  1. src:原图像
  2. dst:目标图像
  3. topbottomleftright: 图像每一条边的像素长度,我们定义它们为原始图像5%的大小。
  4. borderType:定义了使用何种边界。在这个例程中他有定值和复制两种选择。
  5. value: 如果borderTypeBORDER_CONSTANT,这个是用于填补边界像素的值

    8.我们利用先前创建的图像展示输出图像

imshow( window_name, dst );

 

第 4 段(可获 2 积分)

结论

  1. 当编译完上述程序,您将可以利用以给定的图像路径为参数来执行它。它的结果应如下所示:
  • 默认情况下,它将以BORDER_CONSTANT的方式填补边界。因此,将显示一系列随机着色的边界。
  • 如果你按下'r'键,边界将变量原边界的像素复制。
  • 如果你按下'c'键,随机颜色的边界将再次出现
  • 如果你按下'ESC'键,程序将会推出。

以下将会展示一些边界颜色如何变化和BORDER_REPLICATE效果的截图

Final result after copyMakeBorder application

第 5 段(可获 2 积分)

文章评论