• OpenCV每日函数 计算摄影模块(5) 无缝克隆算法


    一、概述

            借助无缝克隆算法,您可以从一张图像中复制一个对象,然后将其粘贴到另一张图像中,从而形成一个看起来无缝且自然的构图。

    二、函数原型

            给定一个原始彩色图像,可以无缝混合该图像的两个不同颜色版本。

    void 	cv::colorChange (InputArray src, InputArray mask, OutputArray dst, float red_mul=1.0f, float green_mul=1.0f, float blue_mul=1.0f)
    src输入 8 位 3 通道图像。
    mask输入 8 位 1 或 3 通道图像。
    dst输出与 src 大小和类型相同的图像。
    red_mulR 通道倍增因子。
    green_mulG 通道倍增因子。
    blue_mulB 通道倍增因子。

             对选区内部的梯度场应用适当的非线性变换,然后用泊松求解器积分,局部修改图像的表观照明。

    void 	cv::illuminationChange (InputArray src, InputArray mask, OutputArray dst, float alpha=0.2f, float beta=0.4f)
    src输入 8 位 3 通道图像。
    mask输入 8 位 1 或 3 通道图像。
    dst输出与 src 大小和类型相同的图像。
    alpha值范围在 0-2 之间。
    beta值范围在 0-2 之间。

            图像编辑任务涉及全局变化(颜色/强度校正、过滤器、变形)或与选择有关的局部变化。 在这里,我们有兴趣以无缝且轻松的方式实现局部更改,这些更改仅限于手动选择的区域 (ROI)。 变化的程度从轻微的扭曲到完全被新颖的内容替代。

    void 	cv::seamlessClone (InputArray src, InputArray dst, InputArray mask, Point p, OutputArray blend, int flags)
    src输入 8 位 3 通道图像。
    dst输入 8 位 3 通道图像。
    mask输入 8 位 1 或 3 通道图像。
    p在 dst 图像中指向放置对象的位置。
    blend输出与 dst 大小和类型相同的图像。
    flags可以是 cv::NORMAL_CLONE、cv::MIXED_CLONE 或 cv::MONOCHROME_TRANSFER 的克隆方法

            通过仅保留边缘位置的梯度,在与泊松求解器集成之前,可以洗掉所选区域的纹理,使其内容具有平坦的外观。 这里使用 Canny 边缘检测器。

    void 	cv::textureFlattening (InputArray src, InputArray mask, OutputArray dst, float low_threshold=30, float high_threshold=45, int kernel_size=3)
    src输入 8 位 3 通道图像。
    mask输入 8 位 1 或 3 通道图像。
    dst输出与 src 大小和类型相同的图像。
    low_threshold范围从 0 到 100。
    high_threshold值 > 100。
    kernel_size要使用的 Sobel 内核的大小。

    三、OpenCV源码

    1、源码路径

    opencv\modules\photo\src\seamless_cloning.cpp

    2、源码代码

    1. #include "precomp.hpp"
    2. #include "opencv2/photo.hpp"
    3. #include "seamless_cloning.hpp"
    4. using namespace std;
    5. using namespace cv;
    6. static Mat checkMask(InputArray _mask, Size size)
    7. {
    8. Mat mask = _mask.getMat();
    9. Mat gray;
    10. if (mask.channels() > 1)
    11. cvtColor(mask, gray, COLOR_BGRA2GRAY);
    12. else
    13. {
    14. if (mask.empty())
    15. gray = Mat(size.height, size.width, CV_8UC1, Scalar(255));
    16. else
    17. mask.copyTo(gray);
    18. }
    19. return gray;
    20. }
    21. void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
    22. {
    23. CV_INSTRUMENT_REGION();
    24. const Mat src = _src.getMat();
    25. const Mat dest = _dst.getMat();
    26. Mat mask = checkMask(_mask, src.size());
    27. dest.copyTo(_blend);
    28. Mat blend = _blend.getMat();
    29. Mat mask_inner = mask(Rect(1, 1, mask.cols - 2, mask.rows - 2));
    30. copyMakeBorder(mask_inner, mask, 1, 1, 1, 1, BORDER_ISOLATED | BORDER_CONSTANT, Scalar(0));
    31. Rect roi_s = boundingRect(mask);
    32. if (roi_s.empty()) return;
    33. Rect roi_d(p.x - roi_s.width / 2, p.y - roi_s.height / 2, roi_s.width, roi_s.height);
    34. Mat destinationROI = dest(roi_d).clone();
    35. Mat sourceROI = Mat::zeros(roi_s.height, roi_s.width, src.type());
    36. src(roi_s).copyTo(sourceROI,mask(roi_s));
    37. Mat maskROI = mask(roi_s);
    38. Mat recoveredROI = blend(roi_d);
    39. Cloning obj;
    40. obj.normalClone(destinationROI,sourceROI,maskROI,recoveredROI,flags);
    41. }
    42. void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float red, float green, float blue)
    43. {
    44. CV_INSTRUMENT_REGION();
    45. Mat src = _src.getMat();
    46. Mat mask = checkMask(_mask, src.size());
    47. _dst.create(src.size(), src.type());
    48. Mat blend = _dst.getMat();
    49. Mat cs_mask = Mat::zeros(src.size(), src.type());
    50. src.copyTo(cs_mask, mask);
    51. Cloning obj;
    52. obj.localColorChange(src, cs_mask, mask, blend, red, green, blue);
    53. }
    54. void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float alpha, float beta)
    55. {
    56. CV_INSTRUMENT_REGION();
    57. Mat src = _src.getMat();
    58. Mat mask = checkMask(_mask, src.size());
    59. _dst.create(src.size(), src.type());
    60. Mat blend = _dst.getMat();
    61. Mat cs_mask = Mat::zeros(src.size(), src.type());
    62. src.copyTo(cs_mask, mask);
    63. Cloning obj;
    64. obj.illuminationChange(src, cs_mask, mask, blend, alpha, beta);
    65. }
    66. void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
    67. float low_threshold, float high_threshold, int kernel_size)
    68. {
    69. CV_INSTRUMENT_REGION();
    70. Mat src = _src.getMat();
    71. Mat mask = checkMask(_mask, src.size());
    72. _dst.create(src.size(), src.type());
    73. Mat blend = _dst.getMat();
    74. Mat cs_mask = Mat::zeros(src.size(), src.type());
    75. src.copyTo(cs_mask, mask);
    76. Cloning obj;
    77. obj.textureFlatten(src, cs_mask, mask, low_threshold, high_threshold, kernel_size, blend);
    78. }

    四、效果图像示例

    需要精确的抠mask才能融合的更好

  • 相关阅读:
    AlphaFold2源码解析(1)--安装使用
    传奇服务器配置如何搭建
    leetcode解题思路分析(一百二十六)1038 - 1044 题
    (七)vulhub专栏:Log4j远程代码执行漏洞复现
    (算法设计与分析)第三章动态规划-第二节:动态规划之背包类型问题
    Java 命令行工具
    代码随想录66——额外题目【回溯、贪心】:52N皇后II、649Dota2 参议院、1221分割平衡字符串
    JSON数据处理工具-在线工具箱网站tool.qqmu.com的使用指南
    中国传统美食网页HTML代码 学生网页课程设计期末作业下载 美食大学生网页设计制作成品下载 DW餐饮美食网页作业代码下载
    Javascript基础-DOM
  • 原文地址:https://blog.csdn.net/bashendixie5/article/details/125361421