点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

本文转自|OpenCV学堂

概述

OpenCV在使用卷积进行图像处理过程种,如何处理边缘像素锚定输出两个技术细节一直是很多人求而不得的疑惑。其实OpenCV在做卷积滤波时会对图像进行边界填充,实现对边缘像素的卷积计算的支持,不同填充方式不同锚定点会得到图像卷积输出不同的结果。

边界填充

我们首先来看一下OpenCV种支持标准卷积边缘填充做法,OpenCV支持的有如下几种卷积边缘填充算法:

常量边界

BORDER_CONSTANT

iiiiii|abcdefgh|iiiiiii

边界复制

BORDER_REPLICATE

aaaaaa|abcdefgh|hhhhhhh

边界反射

BORDER_REFLECT

fedcba|abcdefgh|hgfedcb

边界换行

BORDER_WRAP

cdefgh|abcdefgh|abcdefg

边界反射101

BORDER_REFLECT_101

gfedcb|abcdefgh|gfedcba

边界透明-很不幸运的是OpenCV4已经不支持啦!

BORDER_TRANSPARENT

uvwxyz|abcdefgh|ijklmno

默认填充方式

OpenCV中 filter2D, blur, GaussianBlur等卷积操作默认支持为BORDER_DEFAULT(BORDER_REFLECT_101)

各种不同方式对边缘的填充效果如下:

上图背景为红色,填充上下左右四个像素大小边缘!右下角为原图,左上角图像为常量边缘填充效果(i=0黑色)。

相关代码实现如下:

image = cv.imread("D:/images/qxx.png");
ih, iw = image.shape[:2]
border = 4# 边界填充
b1 = cv.copyMakeBorder(image, border, border, border, border, cv.BORDER_CONSTANT)
b2 = cv.copyMakeBorder(image, border, border, border, border, cv.BORDER_REPLICATE)
b3 = cv.copyMakeBorder(image, border, border, border, border, cv.BORDER_REFLECT)
b4 = cv.copyMakeBorder(image, border, border, border, border, cv.BORDER_WRAP)
b5 = cv.copyMakeBorder(image, border, border, border, border, cv.BORDER_REFLECT_101)# 边界填充类型说明
cv.putText(image, "input", (20,20), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0))
cv.putText(b1, "BORDER_CONSTANT", (20, 20), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0))
cv.putText(b2, "BORDER_REPLICATE", (20, 20), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0))
cv.putText(b3, "BORDER_REFLECT", (20, 20), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0))
cv.putText(b4, "BORDER_WRAP", (20, 20), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0))
cv.putText(b5, "BORDER_REFLECT_101", (20, 20), cv.FONT_HERSHEY_PLAIN, 1.0, (255, 0, 0))# 拼接结果输出
h = b1.shape[0]*2+8
w = b1.shape[1]*3+16
bh, bw = b1.shape[:2]
result = np.zeros([h, w, 3], dtype=np.uint8)
result[:,:,:] = (0, 0, 255)
result[0:bh,0:bw,:] = b1;
result[0:bh, bw+8:bw+bw+8, :] = b2;
result[0:bh, bw+bw+16:bw+bw+bw+16, :] = b3;
result[bh+8:bh+bh+8,0:bw,:] = b4;
result[bh+8:bh+bh+8, bw+8:bw+bw+8, :] = b5;
result[bh+12:bh+12+ih, bw+bw+20:bw+bw+20+iw, :] = image;# 显示
cv.imshow("result", result)
cv.imwrite("D:/border_result.png", result)
cv.waitKey(0)
cv.destroyAllWindows()

锚定位置

在进行卷积处理的时候,卷积mask与对应的像素块点乘得到输出,把输出结果赋值给哪个像素点是由锚定参数anchor决定,以自定义滤波函数filter2D为例说明

void cv::filter2D(InputArray src,OutputArray dst,int ddepth,InputArray      kernel,Point       anchor = Point(-1,-1),double    delta = 0,int borderType = BORDER_DEFAULT
)
其中
kernel - 表示输入的自定义卷积核大小
anchor - 表示锚定点位置,默认情况Point(-1, -1)表示是卷积核的中心位置
borderType - 表示边缘填充的像素大小,ksize/2其中ksize表示卷积核大小

上述函数在卷积核为奇数的时候,卷积核的中心位置很容易确定,比如3x3的卷积核大小,中心位置为Point(1,1)5x5的卷积核大小中心位置为Point(2,2)

但是当卷积核大小为偶数的时候,很多人都搞不清楚中心位置是如何确定的,其实这个时候中心也为(ksize/2), 对2x2的卷积核,中心位置为Point(1,1)4x4的卷积核中心位置为Point(2,2)

锚定位置对卷积结果的影响

以2x2与4x4的卷积核为与3x3与5x5的像素数据为例

情况一

2x2卷积核对3x3的像素块

当锚定点为默认(1,1)/(-1,-1)时候:

当锚定点设置为(0,0)时:

可以看到二者的输出结果全然不同,原因在于当锚定点不同的时候,卷积mask的开始位置也会不不同,图示如下:

情况二:

4x4卷积核对5x5的像素块:

使用BORDER_DEFAULT填充方式,填充之后为:

不同锚定位置的均值卷积输出结果:

三个不同锚定点对应卷积mask的起始位置与锚定像素输出:

代码演示如下:

src = np.zeros([3, 3], dtype=np.uint8)
src[0, 0] = 16
src[1, 1] = 8
src[2, 2] = 4
print("\n input image: \n",src)k1 = [[1, 0], [0, -1]]
print("\nkernel : \n", k1)
result = cv.copyMakeBorder(src, 1, 1, 1, 1, cv.BORDER_DEFAULT)
print("\nBORDER_DEFAULT 边界填充 : \n", result)
dst = cv.filter2D(src, cv.CV_32F, np.asarray(k1), None, anchor=(0, 0), borderType=cv.BORDER_DEFAULT)
print("\nfilter2D : \n", dst)
print("\n")src = np.zeros([5, 5], dtype=np.uint8)
src[0, 0] = 32
src[1, 1] = 16
src[2, 2] = 8
src[3, 3] = 4
src[4, 4] = 2
print("\ninput: \n", src)
k2 = np.ones([4, 4], dtype=np.int32)
print("\nkernel:\n", k2)
result = cv.copyMakeBorder(src, 3, 3, 3, 3, cv.BORDER_DEFAULT)
print("\n边界填充:\n", result)
dst = cv.filter2D(src, cv.CV_32F, np.asarray(k2), None, anchor=(-1, -1), borderType=cv.BORDER_DEFAULT)
print("\n filter2D Result: \n", dst)

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

详解OpenCV卷积滤波之边缘处理与锚定输出相关推荐

  1. 【OpenCV 4开发详解】可分离滤波

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  2. 【OpenCV 4开发详解】高斯滤波

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  3. 【OpenCV 4开发详解】方框滤波

    本文首发于"小白学视觉"微信公众号,欢迎关注公众号 本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究! 经过几个月的努力,小白终于完成了市面上第一本OpenCV 4 ...

  4. 详解OpenCV中的Lucas Kanade稀疏光流单应追踪器

    详解OpenCV中的Lucas Kanade稀疏光流单应追踪器 1. 效果图 2. 源码 参考 这篇博客将详细介绍OpenCV中的Lucas Kanade稀疏光流单应追踪器. 光流是由物体或相机的运动 ...

  5. OpenCV-Python实战(10)——详解 OpenCV 轮廓检测

    OpenCV-Python实战(10)--详解 OpenCV 轮廓检测 0. 前言 1. 轮廓介绍 2. 轮廓检测 3. 轮廓压缩 4. 图像矩 4. 1 一些基于矩的对象特征 4.2 Hu 不变矩 ...

  6. 详解OpenCV的椭圆曲线点坐标近似计算函数ellipse2Poly()

    详解OpenCV的椭圆曲线点坐标近似计算函数ellipse2Poly() 函数ellipse2Poly()可用于近似计算椭圆曲线的像素坐标. 而前面介绍过的函数ellipse()则是直接在图像中绘制椭 ...

  7. 详解 OpenCV 透视变换原理 及 实例

    OpenCV提供了两种图片变换的方式:仿射变换和透视变换,两者的区别很容易区分, 前者是将矩形的图片变成平行四边形 后者是将图片变成梯形 这两种变换虽然都有各自的应用场景,但在实际的图片变换中由于透视 ...

  8. NVIDIA Jetson TK1学习与开发(七):图文详解OpenCV在Jetson TK1上的安装和使用

    图文详解OpenCV在Jetson TK1上的安装和使用 本文介绍如何在Jetson TK1上安装并且使用OpenCV,并给出了示例,供大家参考学习. 1.Jetson TK1平台的OpenCV优化包 ...

  9. group convolution (分组卷积)的计算量详解、卷积计算量特征图大小,池化特征图大小、深度通道deep-wise 卷积

    group convolution (分组卷积)的计算量详解.卷积计算量特征图大小,池化特征图大小.深度通道deep-wise 卷积 提示:最近忙着各种提前批的笔试面试,所以没太多空刷题了都,先复盘一 ...

最新文章

  1. shell编程:实现shell字符串连接功能
  2. BOJ 15 Panic Room
  3. leetcode 787. Cheapest Flights Within K Stops | 787. K 站中转内最便宜的航班(BFS)
  4. 全国计算机等级考试题库二级C操作题100套(第31套)
  5. 中英文标点符号切换的组合键_易混标点符号:一字线(—)、短横线(-)、浪纹线(~)...
  6. Windows 10 LTSB 还原默认照片查看器
  7. 企业管理软件解决方案 出售 :针对华东区中小企业订单仓储管理流程
  8. AutoMap1.0发布
  9. 用curl自动登录HTTPS站点
  10. android自定义ViewPager之——处理与ScrollView的事件冲突
  11. 计算机组成原理华中科技大学秦磊华,计算机组成原理(华科)chap1
  12. IP 点分十进制表示法
  13. 发送手机验证码登录(使用榛子云短信平台)
  14. 简单的求三角函数sin,cos的图像
  15. Android事件机制深入探讨(一)
  16. 自动计数报警器c语言,计数报警器设计
  17. vue组件库(Element UI)
  18. 银行保险机构信息科技外包风险管理办法学习笔记
  19. Unity中的资源管理-一整套简单的资源管理方案(1)
  20. [面试日记] 1,时隔五年再次开始面试

热门文章

  1. Python爬取B站5000条视频,揭秘为何千万人为它流泪
  2. 报名 | 美团是怎样给你推荐外卖的?美团大脑知识图谱详解
  3. 重磅 | 王劲被百度起诉后首露面:称打印机电脑已报废,赔了318块钱,没接到法院传票
  4. 颠覆认知:SRE 到底是干啥的?
  5. IntelliJ IDEA 2021.3.2 发布:告别不断建议安装xx插件的提示!
  6. 对比 MySQL 的 Binlog 日志处理工具
  7. Java打造一款SSH客户端,而且已开源
  8. 基于 Nginx+lua+Memcache 实现灰度发布
  9. 老大,你为什么在代码中要求我们使用LocalDateTime而不是Date?
  10. 数据挖掘技术在出行体验上的应用!