导读

本期将介绍并演示OpenCV中使用textureFlattening实现图像中指定区域纹理平滑的效果。

介绍

OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)

OpenCV无缝融合应用(二)--指定目标颜色改变(附C++源码)

OpenCV无缝融合应用(三)--局部区域亮度调整(附C++源码)

textureFlattening与上述三种方法同属于Seamless Cloning部分,算法均来自下面这篇论文:OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_回调函数

https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf

百度网盘下载:

链接:https://pan.baidu.com/s/1Ma_9ZF4r0SgNmfygHe3kgQ

提取码:0857


OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_c++_02

在与Poisson求解器集成之前,通过仅保留边缘位置处的梯度,可以冲洗所选区域的纹理,使其内容具有平坦的外观。这里使用Canny Edge Detector。该算法假定源图像的颜色接近目标图像的颜色。这种假设意味着,当颜色不匹配时,源图像的颜色将趋向于目标图像的颜色。边缘检测器选取的边缘越少(选择性越强),边缘映射就越稀疏,扁平化效果就越明显。函数说明:

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_scala_03

参数:

src

输入8位3通道图像

mask

输入8位1或3通道图像(掩码图像)

dst

输出结果图(要求和src相同的大小和类型)

low_threshold

Canny边缘检测器低阈值(建议取值0~100)

high_threshold

Canny边缘检测器高阈值(建议取值>100)

kernel_size

Sobel核大小,默认值3

效果展示

实现指定区域纹理平滑(全局人像处理有点类似油画效果):

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_c++_04

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_回调函数_05

实现步骤与源码

程序实现步骤:

(1) 使用鼠标滑动绘制指定目标并生成mask;

(2) 使用;两个滑动条动态改变low_threshold和high_threshold参数的值;

(3) 滑动条回调函数中使用textureFlattening函数完成纹理平滑。

src图:

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_c++_06

鼠标拖动勾选人的轮廓部分(low_thres=72, high_thres=0)以及运行结果:

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_scala_07

鼠标拖动勾选人的轮廓部分(low_thres=72, high_thres=145)以及运行结果:

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_回调函数_08

其他效果大家可以自行尝试,完整C++源码如下:

#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分篇讲解,敬请期待!如果您忘了有哪些内容,可点击上面↑蓝字链接观看。

更多视觉图像处理相关内容,请长按关注:OpenCV与AI深度学习。

OpenCV无缝融合应用(四)--纹理平滑(附C++源码)_scala_09