OpenCV磨皮效果
九柳 人气:01.高斯模糊
1.什么是高斯模糊
前面我们就知道了均值模糊和中值模糊,现在我们开始了解高斯模糊。
首先高斯指的是高斯函数,这个我想大家应该都知道,是一种非常常见的概率分布函数。大概就长这样吧。
通过均值模糊类比,我们可以大胆的猜出来高斯模糊的含义:
每一次需要处理的像素矩阵中不同地方的像素的值在最后的赋值像素的占比是不一样的。这个占比是按照高斯函数所分布的。
也就是说,越是远离中心像素的像素所占比重就更少,而中心像素值在赋值像素中的比重是最重的。
或者说,我们知道之前均值模糊所乘以的矩阵是
而高斯模糊中所乘的3*3矩阵可以是这样的
可视化后就是这样的
虽然我们可以从数学上得知高斯模糊和均值模糊的区别,但是在效果上我个人觉得高斯模糊可能能比起均值模糊能更好的保留边缘信息(只是个人看法)
最后把高斯模糊的计算公式提供给数学大佬
2.opencv提供的API
GaussianBlur(Mat src, Mat dst, Size(11, 11), sigmax, sigmay);
其中Size(x, y), x, y 必须是正数而且是奇数
参数SigmaX表示高斯方程中X方向的标准方差
参数SigmaY表示高斯方程中X方向的标准方差
在高斯分布中,方差可以理解为这个高斯分布的平缓程度,也就是说中间值所占比重的大小,方差越小,中间值所占比重越大,此时模糊的效果会相对更低一点(在同一个size下)
可视化一下你会乘的矩阵:
当方差较大时:
方差较小时:
这里两幅图不是完全合适,只是类比
2.双边模糊
1.什么是双边模糊
由于考虑到不管是均值模糊或者高斯模糊,最后的效果都是整个图像的模糊。有时候我们无需整体的模糊,而比如只模糊边缘,或者只模糊细节。
而双边模糊便是实现了对边缘信息的保留而弱化了细节。(这个效果可以用来磨皮,可以想想为啥)
实现的原理是我们确定一个数表示两个像素之间的差值的阈值,一旦两个像素之间超过了这个阈值,那么就不对这两个像素进行高斯模糊处理,一旦没有超过,就进行模糊处理。因为边缘地区的像素差值是比较大的,这样就能保留边缘的信息。
2.opencv的API
bilateralFilter(src, dest, d=15, 150, 3);
15 –计算的半径,半径之内的像数都会被纳入计算,如果提供-1 则根据sigma space参数取值
150 – sigma color 决定多少差值之内的像素会被计算
3 – sigma space 如果d的值大于0则声明无效,否则根据它来计算d值
3.磨皮美颜效果的实现
1.实现过程
通过对双边模糊处理后的图像再进行对比度加深的操作,最后就是让模糊的边缘再进行加深,几乎回到原来的效果。而模糊效果去掉皮肤上的细节,从而可以让皮肤显得光滑并且颜色很有光泽。
并且我利用滑轨可以动态台哦姐双边模糊的阈值从而让你们自己控制磨皮的效果。
2.主要代码
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/highgui/highgui_c.h> #include <iostream> using namespace cv; using namespace std; int main(int argc, char** argv) { string path = "xxxxxxxxxxxx.jpg"; Mat img = imread(path); Mat img2 = Mat::zeros(img.size(), img.type()); Mat img3; Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); imshow("img1", img); int x = 1, y = 1; namedWindow("Trackbars", (10, 100));//新建了一个窗口--轨迹栏 createTrackbar("x", "Trackbars", &x, 200); while (1) { bilateralFilter(img,img2,15,x,3); imshow("img2", img2); filter2D(img2, img3, img.depth(), kernel);//src.depth()表示位图深度,和type相关 imshow("img3", img3); waitKey(10); } waitKey(0); return 0; }
3.效果
原图:
磨皮后:
(边缘信息没有损失,但是色块更加均匀了还是)
加载全部内容