本期将介绍并演示OpenCV中使用textureFlattening实现图像中指定区域纹理平滑的效果。
介绍
OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C 源码)
OpenCV无缝融合应用(二)--指定目标颜色改变(附C 源码)
OpenCV无缝融合应用(三)--局部区域亮度调整(附C 源码)
textureFlattening与上述三种方法同属于Seamless Cloning部分,算法均来自下面这篇论文:
https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf
百度网盘下载:
链接:https://pan.baidu.com/s/1Ma_9ZF4r0SgNmfygHe3kgQ
提取码:0857
算法解读可参考下面链接:
https://blog.csdn.net/zhaoyin214/article/details/88196575
在与Poisson求解器集成之前,通过仅保留边缘位置处的梯度,可以冲洗所选区域的纹理,使其内容具有平坦的外观。这里使用Canny Edge Detector。该算法假定源图像的颜色接近目标图像的颜色。这种假设意味着,当颜色不匹配时,源图像的颜色将趋向于目标图像的颜色。边缘检测器选取的边缘越少(选择性越强),边缘映射就越稀疏,扁平化效果就越明显。函数说明:
参数:
src | 输入8位3通道图像 |
---|---|
mask | 输入8位1或3通道图像(掩码图像) |
dst | 输出结果图(要求和src相同的大小和类型) |
low_threshold | Canny边缘检测器低阈值(建议取值0~100) |
high_threshold | Canny边缘检测器高阈值(建议取值>100) |
kernel_size | Sobel核大小,默认值3 |
效果展示
实现指定区域纹理平滑(全局人像处理有点类似油画效果):
实现步骤与源码
程序实现步骤:
(1) 使用鼠标滑动绘制指定目标并生成mask;
(2) 使用;两个滑动条动态改变low_threshold和high_threshold参数的值;
(3) 滑动条回调函数中使用textureFlattening函数完成纹理平滑。
src图:
鼠标拖动勾选人的轮廓部分(low_thres=72, high_thres=0)以及运行结果:
鼠标拖动勾选人的轮廓部分(low_thres=72, high_thres=145)以及运行结果:
其他效果大家可以自行尝试,完整C 源码如下:
代码语言:javascript复制// SeamlessCloning.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int low_thres = 30, high_thres = 45;
Mat src, temp, mask, result;
Rect rect;
Point pt;
bool flag = false;
void OnChange(int, void*)
{
//Mat mask = Mat::zeros(src.size(), src.type());
//rectangle(mask, rect, Scalar::all(255), -1);
//illuminationChange(src, mask, result, alpha / 100.0, beta / 100.0);
textureFlattening(src, mask, result, low_thres, high_thres, 3);
imshow("textureFlattening", result);
}
///鼠标消息回调函数
void OnMouse(int event, int x, int y, int flag, void* param)
{
switch (event)
{
case EVENT_LBUTTONDOWN: //鼠标左键按下
//cout<<"left button down"<<endl;
flag = true;
pt.x = x;
pt.y = y;
break;
case EVENT_MOUSEMOVE: //鼠标移动
//cout<<"mouse move"<<endl;
if (flag)
{
circle(temp, Point(x, y), 5, Scalar(0, 0, 255), -1, 8);
circle(mask, Point(x, y), 5, Scalar(255, 255, 255), -1, 8);
}
break;
case EVENT_LBUTTONUP: //鼠标左键弹起
//cout<<"left button up"<<endl;
flag = false;
break;
default:
break;
}
}
int main()
{
src = imread("B.jpg");
temp = src.clone();
mask = Mat::zeros(src.size(), CV_8UC1);
namedWindow("src", WINDOW_NORMAL);
imshow("src", src);
namedWindow("Mouse", WINDOW_NORMAL);
setMouseCallback("Mouse", OnMouse, 0); //设置鼠标回调函数
while (1)
{
imshow("Mouse", temp);
if (27 == waitKey(10)) //Esc跳出循环
break;
}
vector<vector<Point>> contours;
vector<Vec4i> hierarcy;
findContours(mask, contours, hierarcy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
drawContours(mask, contours, -1, Scalar::all(255), -1, 8);
namedWindow("textureFlattening", WINDOW_NORMAL);
createTrackbar("low_thres", "textureFlattening", &low_thres, 500, OnChange);
createTrackbar("high_thres", "textureFlattening", &high_thres, 500, OnChange);
OnChange(0, 0);
waitKey();
return 0;
}
后记:貌似纹理平滑的效果没什么大用,但这部分功能同属无缝克隆部分,所以这里还是做简短介绍。到这里,OpenCV无缝克隆部分算是完结了,也算是有始有终吧!下篇文章开始将进入2020 Top 10 OpenCV Projects分篇讲解,敬请期待!如果您忘了有哪些内容,可点击上面↑蓝字链接观看。