OpenCV图片动态特效显示(三)-- 平移显示及拉伸显示效果

2020-12-03 10:54:11 浏览数 (1)

学更好的别人,

做更好的自己。

——《微卡智享》

本文长度为2927,预计阅读8分钟

前言

前两篇的特效已经实现了展开、渐显及马赛克的实现,今天来实现图像的平移效果及通过显示窗体的函数改造展开显示的代码实现拉伸效果。

实现效果

上图中可以看到,就是使用平移实现的效果,其实这个和我们第一章的显示不同就在于,我们展开的显示,垂直方向全是从上到下的显示,只不过先显示头部还是底部,同理从左到右,和从右到左也是全部从左边开始显示。

平移显示

微卡智享

平移显示的原理也比较简单,就是每显示一行,所以复制的行数就多增加一行。

核心代码

代码语言:javascript复制
//平移显示
//参数:Mat 源图像,
//      width图像宽度, 
//      height图像高度
//      direction方向 0-从上到下  1-从下到上  2-从左到右  3-从右到左
void translationshow(Mat src, int width, int height, int direction)
{
  Mat dst = Mat(src.size(), CV_8UC3);
  if (direction == 0) {
    for (int i = 1; i < height;   i) {
      src(Rect(0, height - i, width, i))
        .copyTo(dst(Rect(0, 0, width, i)));
      
      imshow("translationshow0", dst);
      waitKey(1);
    }
  }
  else if (direction == 1) {
    for (int i = 1; i < height;   i) {
      src(Rect(0, 0, width, i))
        .copyTo(dst(Rect(0, height - i, width, i)));

      imshow("translationshow1", dst);
      waitKey(1);
    }
  }
  else if (direction == 2) {
    for (int i = 1; i < width;   i) {
      src(Rect(width - i, 0, i, height))
        .copyTo(dst(Rect(0, 0, i, height)));

      imshow("translationshow2", dst);
      waitKey(1);
    }
  }
  else if (direction == 3) {
    for (int i = 1; i < width;   i) {
      src(Rect(0, 0, i, height))
        .copyTo(dst(Rect(width - i, 0, i, height)));

      imshow("translationshow3", dst);
      waitKey(1);
    }
  }
  waitKey(0); 
}

线程调用

代码语言:javascript复制
  //平移显示
  future<void> fttranslation0 = async(launch::async, translationshow, src, src.cols, src.rows, 0);
  
  future<void> fttranslation1 = async(launch::async, translationshow, src, src.cols, src.rows, 1);
  
  future<void> fttranslation2 = async(launch::async, translationshow, src, src.cols, src.rows, 2);
  
  future<void> fttranslation3 = async(launch::async, translationshow, src, src.cols, src.rows, 3);

通过上面的方式就可以直接实现开头GIF动画的样子了。

窗口位置显示

微卡智享

前面两章动画时我们imshow的显示位置在过程一中还要自己手动鼠标点一下,这次我在单元里又封装了一个给显示图片窗体定位的函数。

窗体定位代码

代码语言:javascript复制
//显示窗口设置  
//参数  img 显示的图像源,
//      winname 显示的窗口名称,
//      pointx  显示的坐标x
//      pointy  显示的坐标y
void setshowwindow(Mat img, string winname, int pointx, int pointy)
{
  //设置显示窗口
  namedWindow(winname, WindowFlags::WINDOW_NORMAL);
  //设置图像显示大小
  resizeWindow(winname, img.size());
  //设置图像显示位置
  moveWindow(winname, pointx, pointy);
}

在我们显示的前加入窗体定位的调用后,就实现的位置的方式。而用上面窗体位置显示的函数放在我们第一篇展开显示的代码中,就会展现出拉伸的显示效果。

我们来改造一下展开显示的代码:

原来的显示代码最后加入一个是否用窗体控制的参数,如果是true就调用setshowwindow的方法。

完整改造后代码

代码语言:javascript复制
//垂直方向显示   direction 0-从上到下  1-从下到上 2-从左向右  3-从右向左
void directionshow(Mat src, int width, int height, int direction, bool windowflag) {
  Mat tmpsrc, dst;
  if (direction == 0) {
    if(windowflag) setshowwindow(src, "direction0", 1, 100);
    for (int i = 1; i < height; i  ) {
      tmpsrc = src(Rect(0, 0, width, i));
      tmpsrc.copyTo(dst);

      imshow("direction0", dst);
      waitKey(1);
    }
  }
  else if (direction == 1) {
    if (windowflag) setshowwindow(src, "direction1", src.cols   1, 100);
    for (int i = 1; i < height;   i) {
      tmpsrc = src(Rect(0, height- i, width, i));
      tmpsrc.copyTo(dst);

      imshow("direction1", dst);
      waitKey(1);
    }
  }
  else if (direction == 2) {
    if (windowflag) setshowwindow(src, "direction2", src.cols * 2   1, 100);
    for (int i = 1; i < width;   i) {
      tmpsrc = src(Rect(0, 0, i, height));
      tmpsrc.copyTo(dst);

      imshow("direction2", dst);
      waitKey(1);
    }
  }
  else {
    if (windowflag) setshowwindow(src, "direction3", src.cols * 3   1, 100);
    for (int i = width - 1; i > 1; --i) {
      tmpsrc = src(Rect(i, 0, width - i, height));
      tmpsrc.copyTo(dst);

      imshow("direction3", dst);
      waitKey(1);
    }
  }
  cout << "over" << direction << endl;
  waitKey(0);
}

实现效果

0 人点赞