一、函数参考
1、细节增强
此滤镜可增强特定图像的细节。
void cv::detailEnhance (InputArray src, OutputArray dst, float sigma_s=10, float sigma_r=0.15f)
2、保边平滑滤波器
滤波是图像和视频处理中的基本操作。保边平滑滤波器用于许多不同的应用。这是一种实时对图像和视频执行高质量边缘保留过滤的新方法。这个解决方案基于一个变换,该变换定义了 5D 中 2D 图像流形上的曲线与实线之间的等距。这种变换保留了这些曲线上点之间的测地线距离,自适应地扭曲输入信号,以便可以在线性时间内有效地执行一维边缘保留滤波。展示了 1D 边缘保留滤波器的三种实现,展示了如何通过迭代 1D 过滤操作来生成高质量的 2D 边缘保留滤波器,并实证分析了该过程的收敛性。有几个理想的特点:一维操作的使用导致现有技术的显着加速和潜在的内存节省;它的计算成本不受滤波器参数选择的影响;它是第一个实时处理任意比例的彩色图像的边缘保留滤波器,无需借助二次采样或量化。展示了我们的域变换和边缘保留过滤器在几个实时图像和视频处理任务上的多功能性,包括边缘保留过滤、景深效果、风格化、重新着色、着色、细节增强和色调映射。
void cv::edgePreservingFilter (InputArray src, OutputArray dst, int flags=1, float sigma_s=60, float sigma_r=0.4f)
图像处理和计算机视觉中的大多数平滑滤波器(例如高斯滤波器或箱形滤波器)都有一个称为 sigma_s(用于 Sigma_Spatial)的参数,用于确定平滑量。一个典型的平滑滤波器用它的邻居的加权和来代替一个像素的值。邻域越大,过滤后的图像看起来越平滑。邻域的大小与参数 sigma_s 成正比。
在边缘保持过滤器中有两个相互竞争的目标——a)平滑图像 b)不平滑边缘/颜色边界。换句话说,我们不能简单地用相邻像素的加权和来替换像素的颜色。相反,我们希望将像素处的颜色值替换为邻域中颜色与该像素相似的像素的平均值。所以我们有两个参数:sigma_s和sigma_r。就像其他平滑滤波器一样, sigma_s控制邻域的大小,而sigma_r(用于 sigma_range)控制邻域内不同颜色的平均方式。较大的sigma_r会产生较大的恒定颜色区域。
3、铅笔画
类似铅笔的非真实感线条画。
void cv::pencilSketch (InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s=60, float sigma_r=0.07f, float shade_factor=0.02f)
4、风格化
风格化旨在产生具有各种效果的数字图像,而不是专注于照片写实。 边缘感知滤镜是风格化的理想选择,因为它们可以提取低对比度区域,同时保留或增强高对比度特征。
void cv::stylization (InputArray src, OutputArray dst, float sigma_s=60, float sigma_r=0.45f)
二、OpenCV源码
1、源码路径
opencv\modules\photo\src\npr.cpp
2、源码代码
#include "precomp.hpp"
#include "opencv2/photo.hpp"
#include <iostream>
#include <stdlib.h>
#include "npr.hpp"
using namespace std;
using namespace cv;
void cv::edgePreservingFilter(InputArray _src, OutputArray dst, int flags, float sigma_s, float sigma_r)
{
CV_INSTRUMENT_REGION();
Mat I = _src.getMat();
Domain_Filter obj;
Mat img;
I.convertTo(img,CV_32FC3,1.0/255.0);
Mat res;
obj.filter(img, res, sigma_s, sigma_r, flags);
convertScaleAbs(res, dst, 255,0);
}
void cv::detailEnhance(InputArray _src, OutputArray dst, float sigma_s, float sigma_r)
{
CV_INSTRUMENT_REGION();
Mat I = _src.getMat();
float factor = 3.0f;
Mat img;
I.convertTo(img,CV_32FC3,1.0/255.0);
Mat lab;
vector <Mat> lab_channel;
cvtColor(img,lab,COLOR_BGR2Lab);
split(lab,lab_channel);
Mat L;
lab_channel[0].convertTo(L,CV_32FC1,1.0/255.0);
Domain_Filter obj;
Mat res;
obj.filter(L, res, sigma_s, sigma_r, 1);
Mat detail = L - res;
multiply(detail,factor,detail);
L = res + detail;
L.convertTo(lab_channel[0],CV_32FC1,255);
merge(lab_channel,lab);
cvtColor(lab,res,COLOR_Lab2BGR);
res.convertTo(dst,CV_8UC3,255);
}
void cv::pencilSketch(InputArray _src, OutputArray _dst1, OutputArray _dst2, float sigma_s, float sigma_r, float shade_factor)
{
CV_INSTRUMENT_REGION();
Mat I = _src.getMat();
_dst1.create(I.size(), CV_8UC1);
Mat dst1 = _dst1.getMat();
_dst2.create(I.size(), CV_8UC3);
Mat dst2 = _dst2.getMat();
Mat img = Mat(I.size(),CV_32FC3);
I.convertTo(img,CV_32FC3,1.0/255.0);
Domain_Filter obj;
Mat sketch = Mat(I.size(),CV_32FC1);
Mat color_sketch = Mat(I.size(),CV_32FC3);
obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor);
sketch.convertTo(dst1,CV_8UC1,255);
color_sketch.convertTo(dst2,CV_8UC3,255);
}
void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
{
CV_INSTRUMENT_REGION();
Mat I = _src.getMat();
_dst.create(I.size(), CV_8UC3);
Mat dst = _dst.getMat();
Mat img;
I.convertTo(img,CV_32FC3,1.0/255.0);
int h = img.size().height;
int w = img.size().width;
Mat res;
Mat magnitude = Mat(h,w,CV_32FC1);
Domain_Filter obj;
obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER);
obj.find_magnitude(res,magnitude);
Mat stylized;
vector <Mat> temp;
split(res,temp);
multiply(temp[0],magnitude,temp[0]);
multiply(temp[1],magnitude,temp[1]);
multiply(temp[2],magnitude,temp[2]);
merge(temp,stylized);
stylized.convertTo(dst,CV_8UC3,255);
}