OpenCV如何实现无缝克隆算法

蜗牛 互联网技术资讯 2022-06-21 21 0

这篇“OpenCV如何实现无缝克隆算法”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“OpenCV如何实现无缝克隆算法”文章吧。

    一、概述

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

    二、函数原型

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

    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_mul R 通道倍增因子
    green_mul G 通道倍增因子
    blue_mul B 通道倍增因子

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

    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、源码代码

    #include "precomp.hpp"
    #include "opencv2/photo.hpp"
     
    #include "seamless_cloning.hpp"
     
    using namespace std;
    using namespace cv;
     
    static Mat checkMask(InputArray _mask, Size size)
    {
        Mat mask = _mask.getMat();
        Mat gray;
        if (mask.channels() > 1)
            cvtColor(mask, gray, COLOR_BGRA2GRAY);
        else
        {
            if (mask.empty())
                gray = Mat(size.height, size.width, CV_8UC1, Scalar(255));
            else
                mask.copyTo(gray);
        }
     
        return gray;
    }
     
    void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
    {
        CV_INSTRUMENT_REGION();
     
        const Mat src  = _src.getMat();
        const Mat dest = _dst.getMat();
        Mat mask = checkMask(_mask, src.size());
        dest.copyTo(_blend);
        Mat blend = _blend.getMat();
     
        Mat mask_inner = mask(Rect(1, 1, mask.cols - 2, mask.rows - 2));
        copyMakeBorder(mask_inner, mask, 1, 1, 1, 1, BORDER_ISOLATED | BORDER_CONSTANT, Scalar(0));
     
        Rect roi_s = boundingRect(mask);
        if (roi_s.empty()) return;
        Rect roi_d(p.x - roi_s.width / 2, p.y - roi_s.height / 2, roi_s.width, roi_s.height);
     
        Mat destinationROI = dest(roi_d).clone();
     
        Mat sourceROI = Mat::zeros(roi_s.height, roi_s.width, src.type());
        src(roi_s).copyTo(sourceROI,mask(roi_s));
     
        Mat maskROI = mask(roi_s);
        Mat recoveredROI = blend(roi_d);
     
        Cloning obj;
        obj.normalClone(destinationROI,sourceROI,maskROI,recoveredROI,flags);
    }
     
    void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float red, float green, float blue)
    {
        CV_INSTRUMENT_REGION();
     
        Mat src  = _src.getMat();
        Mat mask = checkMask(_mask, src.size());
        _dst.create(src.size(), src.type());
        Mat blend = _dst.getMat();
     
        Mat cs_mask = Mat::zeros(src.size(), src.type());
        src.copyTo(cs_mask, mask);
     
        Cloning obj;
        obj.localColorChange(src, cs_mask, mask, blend, red, green, blue);
    }
     
    void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float alpha, float beta)
    {
        CV_INSTRUMENT_REGION();
     
        Mat src  = _src.getMat();
        Mat mask = checkMask(_mask, src.size());
        _dst.create(src.size(), src.type());
        Mat blend = _dst.getMat();
     
        Mat cs_mask = Mat::zeros(src.size(), src.type());
        src.copyTo(cs_mask, mask);
     
        Cloning obj;
        obj.illuminationChange(src, cs_mask, mask, blend, alpha, beta);
     
    }
     
    void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
                               float low_threshold, float high_threshold, int kernel_size)
    {
        CV_INSTRUMENT_REGION();
     
        Mat src  = _src.getMat();
        Mat mask = checkMask(_mask, src.size());
        _dst.create(src.size(), src.type());
        Mat blend = _dst.getMat();
     
        Mat cs_mask = Mat::zeros(src.size(), src.type());
        src.copyTo(cs_mask, mask);
     
        Cloning obj;
        obj.textureFlatten(src, cs_mask, mask, low_threshold, high_threshold, kernel_size, blend);
    }

    四、效果图像示例

    OpenCV如何实现无缝克隆算法  opencv 第1张

    OpenCV如何实现无缝克隆算法  opencv 第2张

    OpenCV如何实现无缝克隆算法  opencv 第3张

    以上就是关于“OpenCV如何实现无缝克隆算法”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注蜗牛博客行业资讯频道。

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    评论