OpenCV图像剪切的扩展和高级用法:任意裁剪,边界扩充

  【尊重原创,转载请注明出处】http://blog.csdn.net/guyuealian/article/details/78113325
   利用感兴趣区域ROI和矩形类Rect,在OpenCV中可以很简单的就实现图像裁剪和剪切的功能,但剪切时常常会出现超出图像边界的区域的情况,对于超出图像边界的区域,我们必须进行特殊的处理,以避免出组数组越界的错误,如图1所示的裁剪错误。
   对于特殊的要求,如,我们希望可以指定的颜色来填充,或者复制边界的像素的填充,甚至想镜像某个位置填充超出的边界,应该怎么办呢?OpenCV3中提供了一个图像边界的函数cv::copyMakeBorder(对应opencv2中的cvCopyMakeBorder)以及borderInterpolate,利用这个函数,可以间接实现这个功能。
    copyMakeBorder函数的用法,请参考博客:http://blog.csdn.net/qianqing13579/article/details/42323397
    注意:copyMakeBorder函数不能直接用于图像裁剪,博客后面会贴出封装好的ImageCropPadding()函数,方便亲们调用
函数原型:copyMakeBorder
void copyMakeBorder( const Mat& src, Mat& dst,int top, int bottom, int left, int right,int borderType, const Scalar& value=Scalar() );

函数功能:
      用于扩充src图像的边缘,使得图像变大变宽,该函数调用了cv::borderInterpolate函数
参数说明:
   src,dst:原图与目标图像top,bottom,left,right分别表示在原图四周扩充边缘的大小borderType:扩充边缘的类型,OpenCV中给出以下几种方式
    说明如下:
  * BORDER_REPLICATE* BORDER_REFLECT* BORDER_REFLECT_101* BORDER_WRAP* BORDER_CONSTANT

图1
cv::Mat src = cv::imread("D:\\OpencvTest\\1.jpg");//原始图像是200*200
cv::Rect rect(-100, -100, 500, 500);
cv::Mat image = src(rect);//这时裁剪,必然出错
Enumerator
BORDER_CONSTANT 

iiiiii|abcdefgh|iiiiiii with some specified i(指定常数填充)

BORDER_REPLICATE

aaaaaa|abcdefgh|hhhhhhh(复制边缘像素填充)

BORDER_REFLECT 

fedcba|abcdefgh|hgfedcb(反射复制边界像素)

BORDER_WRAP

cdefgh|abcdefgh|abcdefg

BORDER_REFLECT_101 

gfedcb|abcdefgh|gfedcba(对称填充,也就是以最边缘像素为轴)

BORDER_TRANSPARENT

uvwxyz|absdefgh|ijklmno

BORDER_REFLECT101 

same as BORDER_REFLECT_101

BORDER_DEFAULT

same as BORDER_REFLECT_101

BORDER_ISOLATED 

do not look outside of ROI

(1)BORDER_REPLICATE:复制法,也就是复制最边缘像素。

     如上图,红色区域为src的最边界像素,蓝色区域是扩充的边界,我们将边缘扩大了5个像素(right=5),蓝色区域的宽度就是5,复制了5次红色区域的值。这种方式也就是OpenCV中的中值滤波medianBlur采用的边界处理方式
  (2)BORDER_REFLECT_101:对称法,也就是以最边缘像素为轴,对称扩展。如下面的图

     绿色区域是src最边界的像素,蓝色区域是我们扩充的5个像素的扩充边界,而红色区域就是蓝色区域在src的对称部分。这种方式也是OpenCV边界处理的默认方式(BORDER_DEFAULT=BORDER_REFLECT_101)
也是filter2D,blur,GaussianBlur,bilateralFilter的默认处理方式,所以这种方式在边界处理中应用还是非常广泛的
(3)BORDER_CONSTANT:常量法,可指定颜色填充常量法就是以一个常量像素值(由参数 value给定)填充扩充的边界值,这种方式在仿射变换,透视变换中非常常见
如下图:

     这里使用了默认的value,黑色填充了边界,所以红色区域的扩充的5个像素宽的边界是黑色的在copyMakeBorder的内部,调用了函数borderInterpolate
  前面提到,copyMakeBorder函数只是进行图像的简单扩充而已,而我们需要的是在图像裁剪时,对超过边界区域实现颜色自动填充。这里实现了一个Demo,对于超出剪切的区域,用红色(或其他)填充,这里贴出封装好的ImageCropPadding()函数,方便亲们调用下面
#include "stdafx.h"
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
using namespace std;
using namespace cv;cv::Mat ImageCropPadding(cv::Mat srcImage, cv::Rect rect)
{//cv::Mat srcImage = image.clone();int crop_x1 = cv::max(0, rect.x);int crop_y1 = cv::max(0, rect.y);int crop_x2 = cv::min(srcImage.cols, rect.x + rect.width); // 图像范围 0到cols-1, 0到rows-1      int crop_y2 = cv::min(srcImage.rows, rect.y + rect.height);int left_x = (-rect.x);int top_y = (-rect.y);int right_x = rect.x + rect.width - srcImage.cols;int down_y = rect.y + rect.height - srcImage.rows;//cv::Mat roiImage = srcImage(cv::Range(crop_y1, crop_y2 + 1), cv::Range(crop_x1, crop_x2 + 1));    cv::Mat roiImage = srcImage(cv::Rect(crop_x1, crop_y1, (crop_x2 - crop_x1), (crop_y2 - crop_y1)));if (top_y > 0 || down_y > 0 || left_x > 0 || right_x > 0)//只要存在边界越界的情况,就需要边界填充    {left_x = (left_x > 0 ? left_x : 0);right_x = (right_x > 0 ? right_x : 0);top_y = (top_y > 0 ? top_y : 0);down_y = (down_y > 0 ? down_y : 0);//cv::Scalar(0,0,255)指定颜色填充    cv::copyMakeBorder(roiImage, roiImage, top_y, down_y, left_x, right_x, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 255));//cv::copyMakeBorder(roiImage, roiImage, top_y, down_y, left_x, right_x, cv::BORDER_REPLICATE);//复制最边缘像素    //cv::copyMakeBorder(roiImage, roiImage, top_y, down_y, left_x, right_x, BORDER_REFLECT_101);  //边缘对称法填充     }//else//若不存在边界越界的情况,则不需要填充了    //{    //  destImage = roiImage;    //}    return roiImage;
}
int main(int argc)
{Mat src = imread("D:\\OpencvTest\\B1.jpg");//原始图像是200*200  cv::imshow("src", src);cv::Rect rect(-50, -50, 300, 300);printf("src:[%d,%d]", src.cols, src.rows);  printf("\n");cv::Mat crop_im1 = ImageCropPadding(src, rect);printf("rect:[%d,%d,%d,%d]", rect.x, rect.y, rect.width, rect.height);printf("\n");printf("crop_im1:[%d,%d]", crop_im1.cols, crop_im1.rows); printf("\n");cv::imshow("crop_im1", crop_im1);cvWaitKey(0);return 0;
}

   这美女不错吧,哈哈!注意,关注点不是美女,而是裁剪超出图像的红色区域。不过,对本人而言,我更喜欢复制边缘像素的填充方法:
   将原来copyMakeBorder函数参数改为:cv::BORDER_REPLICATE
cv::copyMakeBorder(roiImage, destImage, top_y, down_y, left_x, right_x, cv::BORDER_REPLICATE);//复制边缘像素填充
   效果如下图所示,是不是看到美女的手好细好长,美美哒~注意,关注点不是美女,而是裁剪超出图像被复制的像素区域。

   还有更妖媚的填充方法:边缘对称法填充 ,效果如下图所示
cv::copyMakeBorder(roiImage, destImage, top_y, down_y, left_x, right_x, BORDER_REFLECT_101); //边缘对称法填充 
如果你觉得该帖子帮到你,还望贵人多多支持,鄙人会再接再厉,继续努力的~
												

OpenCV图像剪切的扩展和高级用法:任意裁剪,边界扩充相关推荐

  1. OpenCV图像剪切,超出图像区域指定颜色填充

    OpenCV图像剪切,超出图像区域指定颜色填充 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/77486096 在Open ...

  2. opencv 图像 抠图 算法_opencv提取轮廓与抠图

    自然图像抠图/视频抠像技术梳理(image matting, video matting)-计算机视视觉专题1 图像抠图算法学习 - Shared Sampling for Real-Time Alp ...

  3. python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客...

    原文作者:梦想橡皮擦 原文标题:Python OpenCV 图像的双线性插值算法,全网最细致的算法说明 发布时间:2021-02-17 20:55:32 Python OpenCV 365 天学习计划 ...

  4. Matlab图像剪切,超出图像区域指定颜色填充

    Matlab图像剪切,超出图像区域指定颜色填充 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/77507969 Matla ...

  5. Linux基础和c语言的高级用法

    Linux基础 基础命令 与文件相关的: mkdir:创建一个目录文件 touch:创建一个普通文件 rmdir:删除一个空的目录文件 cd:+目录名:进入该目录文件 +路径:进入该路径下 ls:显示 ...

  6. Python,OpenCV图像金字塔cv2.pyrUp(), cv2.pyrDown()

    Python,OpenCV图像金字塔cv2.pyrUp, cv2.pyrDown 1. 效果图 2. 原理 2.1 什么是图像金字塔 2.2 金字塔分类 2.3 应用 3. 源码 参考 这篇博客将介绍 ...

  7. OpenCV 图像加载和显示

    OpenCV 图像加载和显示 OpenCV 图像加载和显示 加载图像(使用cv :: imread) 创建一个名为OpenCV的窗口(使用cv :: namedWindow) 在OpenCV窗口中显示 ...

  8. vim的高级用法配置以及在系统中如何获取帮助

    vim的高级用法配置以及在系统中如何获取帮助 1 vim的三种模式 1.1 使用方法 1.2 vim模式 2 vim工作的基本配置 2.1 临时设定(set设定) 2.2 永久设定方式 3 搜索 4 ...

  9. class() 高级用法 -- lua

    class() 高级用法 class() 除了定义纯 Lua 类之外,还可以从 C++ 对象继承类.比如需要创建一个工具栏,并在添加按钮时自动排列已有的按钮,那么我们可以使用如下的代码:-- 从 CC ...

最新文章

  1. SpringBatch学习一个Demo项目
  2. AngularJs异步文件上传
  3. 团队冲刺第二阶段-2
  4. 从一个页面跳转到用swiper写的全屏滚动页面的指定位置
  5. MySQL查询的进阶操作--分页查询
  6. 代码规范:在Keil5中使用代码格式化工具Astyle(插件)
  7. web服务器-Apache
  8. 【APIO2015】完跪记
  9. Highcharts隐藏网格线
  10. 如何从900万张图片中对600类照片进行分类,附代码
  11. python的变量与注释
  12. CrackMe022
  13. 应用程序热补丁(一):如何用几行代码打造应用程序热补丁
  14. Kettle入门操作——输入流(表输入、excel)详细
  15. dnf连接服务器黑屏xp系统,windows xp进入桌面后黑屏的解决技巧
  16. Android 4.1 (Jelly Bean,果冻豆)
  17. IT程序员的抉择:我要离开帝都了
  18. 硅谷科技巨头CEO一年赚多少?这10位高薪代表了解一下
  19. 微信小程序入门案例-会议邀请函
  20. 无法更新计算机配置系统时间,电脑怎么设置系统时间自动更新

热门文章

  1. Alwayson--问题总结二
  2. 关于表格动态添加行并处理相关表单元素的一些修改
  3. c语言数据结构学习心得——线性表
  4. Python包的相对导入时出现问题解决
  5. [归并][随机算法] JZOJ P3765 想法
  6. 中国科学院大学2014年数学分析高等代数考研试题
  7. 跟小静读《jQuery权威指南》——目录
  8. 排序1+1:冒泡排序法(BubbleSort)的改进以及效率比较
  9. Swift:用UICollectionView整一个瀑布流
  10. mybatis$和#的区别