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

2021-03-25 15:30:35 浏览数 (1)

导读

本期将介绍并演示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

C‍anny边缘检测器高阈值(建议取值>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分篇讲解,敬请期待!如果您忘了有哪些内容,可点击上面↑蓝字链接观看。

0 人点赞