服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - OpenCV实现图像背景虚化效果原理详解

OpenCV实现图像背景虚化效果原理详解

2022-10-25 13:52Mr.Winter` C/C++

相信用过相机的同学都知道虚化特效,这是一种使焦点聚集在拍摄主题上,让背景变得朦胧的效果。本文将详细介绍一些这一效果的实现原理以及代码,需要的可以参考一下

0 写在前面

相信用过相机的同学都知道虚化特效,这是一种使焦点聚集在拍摄主题上,让背景变得朦胧的效果,例如本文最后实现的背景虚化效果

OpenCV实现图像背景虚化效果原理详解

相机虚化特效背后的原理是什么?和计算机视觉有什么关系?本文带你研究这些问题。

 

1 小孔成像

小学我们就知道,没有光就不存在图像,为了产生图像,场景必须有一个或多个、直接或间接的光源。

OpenCV实现图像背景虚化效果原理详解

如图所示,光照主要分为三类:

  • 散射
  • 直接光照
  • 漫反射

在获得光源后,将产生从物体到检测平面的光线。

由于从物体上某点A出发存在无数条四散的光线到达检测平面,因此可以认为A的成像点A’均匀地分布在成像平面上,同理其他点亦然。所以这种情况下,检测平面上是无数张物体图像的混叠,导致成像模糊甚至无法成像。

OpenCV实现图像背景虚化效果原理详解

面对一张白纸上看不到你的脸,不是因为白纸上没有来自于你的光线,而是因为来自于你不同部分的光线在白纸上产生了重叠,不信你试试?

那如何在白纸上成像?

其实非常简单,采用小学就尝试过的小孔成像

OpenCV实现图像背景虚化效果原理详解

本质上小孔相当于一个滤光器,仅保留从物点发出的少数光线,此时应能获得清晰的图像。

 

2 光学成像

小孔成像的缺陷是成像光线较少,亮度低。为了既能获得较多光线,又不让像点四散在检测面上造成影像重叠,引入具有聚光性的透镜。透镜成像与小孔成像的本质都是避免因像点四散导致的无法成像,前者利用聚光,后者则利用滤光。

OpenCV实现图像背景虚化效果原理详解

现代相机在应用上通常使用透镜成像,但不管是透镜成像还是小孔成像,都是计算机视觉研究的基本模型和假设,例如透视几何相机内参矩阵畸变修正等等,因此本节对于建立机器视觉的研究思维很有帮助。

 

3 虚化效果

介绍完前面的基础知识,终于开始图像虚化特效的原理啦!

理想透镜应保证光线聚焦于一点——焦点,这个点不会产生任何成像混叠,图像最清晰。在焦点前后光线开始四散,形成不同程度的成像重叠区域,称为弥散圆,对于人眼而言,在一定范围内影象产生的模糊是不能辨认的,不能辨认的弥散圆范围称为容许弥散圆

OpenCV实现图像背景虚化效果原理详解

当对被摄主体平面调焦时,因为容许弥散圆的存在,在一定离焦范围内,成像仍然清晰,这个范围称为焦深。调整成像面和镜头距离,使成像面处于焦深内,物体可以清晰成像的过程,称为对焦。

类似地,对被摄物体而言,位于调焦物平面前后的能相对清晰成像的景物间纵深距离称为景深。图像虚化效果就和这个景深有关系!

  • 景深越小,被摄物体前后能清晰成像的范围越小,也就相应地出现朦胧虚化的效果
  • 景深越大,被摄物体前后能清晰成像的范围越大,也就没有虚化效果

OpenCV实现图像背景虚化效果原理详解

如何调节景深?记住一句话:光圈越大景深越小,所以拿手机拍照的时候,大光圈也就代表了虚化效果!

所以下次有机会给女生拍照的话,请先确认

“请问你喜欢小景深还是大景深?”

 

4 代码实战

相机背景虚化特效在图像处理中可以采用引导滤波器实现,源码如下。

//引导滤波器
Mat guidedFilter(Mat& srcMat, Mat& guidedMat, int radius, double eps)
{
  srcMat.convertTo(srcMat, CV_64FC1);
  guidedMat.convertTo(guidedMat, CV_64FC1);
  // 计算均值
  Mat mean_p, mean_I, mean_Ip, mean_II;
  boxFilter(srcMat, mean_p, CV_64FC1, Size(radius, radius));                      // 生成待滤波图像均值mean_p 
  boxFilter(guidedMat, mean_I, CV_64FC1, Size(radius, radius));                   // 生成引导图像均值mean_I   
  boxFilter(srcMat.mul(guidedMat), mean_Ip, CV_64FC1, Size(radius, radius));      // 生成互相关均值mean_Ip
  boxFilter(guidedMat.mul(guidedMat), mean_II, CV_64FC1, Size(radius, radius));   // 生成引导图像自相关均值mean_II
  // 计算相关系数、Ip的协方差cov和I的方差var------------------
  Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);
  Mat var_I = mean_II - mean_I.mul(mean_I);
  // 计算参数系数a、b
  Mat a = cov_Ip / (var_I + eps);
  Mat b = mean_p - a.mul(mean_I);
  // 计算系数a、b的均值
  Mat mean_a, mean_b;
  boxFilter(a, mean_a, CV_64FC1, Size(radius, radius));
  boxFilter(b, mean_b, CV_64FC1, Size(radius, radius));
  // 生成输出矩阵
  Mat dstImage = mean_a.mul(srcMat) + mean_b;
  return dstImage;
}

关于引导滤波器的相关原理我们下次再开新的章节阐述。

主函数内调用滤波器即可,效果如文首所示。

int main()
{
  Mat resultMat; 
  Mat vSrcImage[3], vResultImage[3];
  Mat vResultImage[3];    
  Mat srcImage = imread("1.jpg");
  imshow("源图像", srcImage);
  // 对源图像进行通道分离,并对每个分通道进行引导滤波
  split(srcImage, vSrcImage);
  for (int i = 0; i < 3; i++)
  {
      Mat tempImage;
      vSrcImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0);
      Mat cloneImage = tempImage.clone();
      Mat resultImage = guidedFilter(tempImage, cloneImage, 5, 0.3);
      vResultImage[i] = resultImage;
  }
  // 将分通道导向滤波后结果合并
  merge(vResultImage, 3, resultMat);
  imshow("背景虚化特效", resultMat);
  waitKey(0);
  return 0;
}

一个小小的图像虚化特效,背后牵扯出光学成像的各种原理,构建了计算机视觉模型的地基。正如我们每个人一样,也许你觉得自己很渺小,说不定也是别人的中流砥柱呢!

到此这篇关于OpenCV实现图像背景虚化效果原理详解的文章就介绍到这了,更多相关OpenCV图像背景虚化内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/FRIGIDWINTER/article/details/123431702

延伸 · 阅读

精彩推荐
  • C/C++win10+VS2017+Cuda10.0环境配置详解

    win10+VS2017+Cuda10.0环境配置详解

    这篇文章主要介绍了win10+VS2017+Cuda10.0环境配置详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下...

    HallieDong9782021-09-18
  • C/C++C++图像处理之双边滤波

    C++图像处理之双边滤波

    这篇文章主要为大家详细介绍了C++图像处理之双边滤波,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Asimov_Liu4912022-01-20
  • C/C++Windows安装配置C/C++(VS2017)OpenSSL开发环境配置教程

    Windows安装配置C/C++(VS2017)OpenSSL开发环境配置教程

    这篇文章主要为大家详细介绍了Windows安装配置C/C++,OpenSSL开发环境配置教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    九黑生魂10062021-05-24
  • C/C++C++设计模式之组合模式

    C++设计模式之组合模式

    这篇文章主要介绍了C++设计模式之组合模式,本文讲解什么是组合模式、组合模式的优点、组合模式实例等内容,需要的朋友可以参考下...

    果冻想4302021-02-04
  • C/C++常用排序算法的C语言版实现示例整理

    常用排序算法的C语言版实现示例整理

    这篇文章主要介绍了常用排序算法的C语言版实现示例整理,包括快速排序及冒泡排序等,基本上都给出了时间复杂度,需要的朋友可以参考下...

    wuzhekai19856242021-03-28
  • C/C++数据结构之红黑树详解

    数据结构之红黑树详解

    这篇文章主要介绍了数据结构之红黑树详解,红黑树是一种自平衡二叉查找树,它的统计性能要好于平衡二叉树(AVL树),因此,红黑树在很多地方都有应用,需...

    C语言程序设计8012021-01-30
  • C/C++C++通过Callback向C#传递数据的方法

    C++通过Callback向C#传递数据的方法

    下面小编就为大家分享一篇C++通过Callback向C#传递数据的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    特务小强9222022-02-17
  • C/C++C语言中static的使用介绍

    C语言中static的使用介绍

    大家好,本篇文章主要讲的是C语言中static的使用介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览...

    前秃无量10212022-07-22