OPENCV】seamless clone 功能比较

Tags: DIP


opencv 自带的 poisson image editing是对2003年SIGGRAPH文章poisson image editing的实现。 提供了6中不同的功能,分别是normal clone, mixed clone, monochrome transfer, color change, illumination change, texture flattening。这篇文章对比下这几种功能的差异。

  • normal clone: 不保留dstination 图像的texture细节。目标区域的梯度只由源图像决定。
  • mixed clone: 保留destination 图像的texture 细节。目标区域的梯度是由原图像和目的图像的组合计算出来(计算dominat gradient)。
  • monochrome change: 不保留src图像的颜色细节,只有src图像的质地,颜色和目标图像一样,可以用来进行皮肤质地填充。
    这三个功能在opencv中是同一个函数,使用不同的flag切换不同功能:
    seamlessClone(src, dst, mask, p, result, flags)
  • color change: 同一幅图像的颜色融合
    colorChange(src, mask, result, red_mul, green_mul, blue_mul)
    后面三个参数是rgb三个通道的乘数因子,在0.5-2.5之间。值越大起到锐化的作用。
  • illumination change: 对区域内illuminaton 变换明显的地方做修改
    illuminationChange(src, mask, result, alpha=0.2f, beta=0.4f)
    beta越大,图片平滑越多,alpha越大,越接近原图细节。alpha和beta都是0-2之间。对于加亮曝光不足的区域比较有效果。
  • texture flattening: 仅仅保留边缘处的梯度,选中区域的质地没有保留。
    textureFlattening(src, mask, result, double low_thresh=30, double high_thresh=45, int kernel_size=3)

如:
src:

53qOmS.png

dst:

53qjra.jpg


normal clone:

53qdW2.jpg


mixed clone:

53qGxz.jpg

monochrome transfer:

53qQoQ.jpg


color change:

55zG2Y.jpg


illumination change:

55zjCr.jpg

texture flattening:

55zddR.jpg

实现

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/photo/photo.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

static void onTrackbar(int, void*);
static void onMouse(int event, int x, int y, int flags, void*);

int value1, value2, value3;
int method=1;
cv::Mat dst, src, mask, result, displayImg;
cv::Point center;
cv::Point prevPt(-1,-1);
char c; 
int main(){
    std::string folder = "/Users/yuhua.cheng/Desktop/FaceBeauty/test/data/";
    src = cv::imread(folder + "src.jpg", -1);
    dst = cv::imread(folder + "dst.jpg", -1);
    // cv::Mat mask = cv::imread(folder + "face_mask.png", 0);
    if(src.empty()){
        std::cout << "Unable to load src!\n";
    }
    if(dst.empty()){
        std::cout << "Unable to load dst!\n";
    }
    if(src.type() == 24){
        cvtColor(src, src, cv::COLOR_BGRA2GRAY);
    }
    if(dst.type() == 24){
        cvtColor(dst, dst, cv::COLOR_BGRA2GRAY);
    }

    center.x = dst.rows/2;
    center.y = dst.cols/2;
    mask = cv::Mat::zeros(dst.size(), CV_8U);
    displayImg = dst.clone();
    cv::namedWindow("image", 1);
    cv::imshow("image", dst);
    cv::namedWindow("result",1);
    cv::setMouseCallback("image", onMouse, 0);
    while(1){
        c = (char) cv::waitKey();
        if(c == 'q'){
            break;
        }
        if(c == 'i'){
            std::cout << "Enter the method you want to use:" << std::endl;
            std::cin >> method;
            cv::createTrackbar("value1","result",&value1,20,onTrackbar);
            cv::createTrackbar("value2","result",&value2,20,onTrackbar);
            cv::createTrackbar("value3","result",&value3,20,onTrackbar);
            onTrackbar(0,0);
         }
    }
    cv::waitKey(0);
    return 0;
}
static void onTrackbar(int, void*){
    if(method==1){
        cv::Mat mask(src.size(), CV_8U, cv::Scalar::all(255));
        cv::seamlessClone(src, dst, mask, center, result, 1);
        imshow("result",result);
    }
    if(method==2){
        cv::Mat mask(src.size(), CV_8U, cv::Scalar::all(255));
        cv::seamlessClone(src, dst, mask, center, result, 2);
        imshow("result",result);
    }
    if(method==3){
        cv::Mat mask(src.size(), CV_8U, cv::Scalar::all(255));
        cv::seamlessClone(src, dst, mask, center, result, 3);
        imshow("result",result);
    }
    if(method==4){
        float red_mul = value1/10+0.5;
        float green_mul = value2/10+0.5;
        float blue_mul = value3/10+0.5;
        cv::colorChange(dst, mask, result, red_mul, green_mul, blue_mul);
        cv::imwrite("result.jpg", result);
        imshow("result", result);
    }   
    if(method==5){
        float alpha = value1/10;
        float beta = value2/10;
        cv::illuminationChange(dst, mask, result, alpha, beta);
        cv::imwrite("result.jpg", result);
        imshow("result", result);
    }
    if(method==6){
        int low_thresh = value1*5;
        int high_thresh = value2*5+100;
        int k_size = 3;
        cv::textureFlattening(dst, mask, result, low_thresh, high_thresh, k_size );
        cv::imwrite("result.jpg", result);
        imshow("result", result);
    }
}
static void onMouse(int event, int x, int y, int flags, void*){

    if (event == cv::EVENT_LBUTTONUP || !(flags & cv::EVENT_FLAG_LBUTTON))
        prevPt = cv::Point(-1, -1);
    else if (event == cv::EVENT_LBUTTONDOWN)
        prevPt = cv::Point(x, y);
    else if (event == cv::EVENT_MOUSEMOVE && (flags & cv::EVENT_FLAG_LBUTTON))
    {
        cv::Point pt(x, y);
        if (prevPt.x < 0)
            prevPt = pt;
        cv::line(mask, prevPt, pt, cv::Scalar::all(255), 40, 8, 0); // handmask 实际祛痘磨皮区域
        cv::line(displayImg, prevPt, pt, cv::Scalar::all(255), 40, 8, 0);
        prevPt = pt;
        imshow("image", displayImg);
    }
}

Reference

  1. Seamless Cloning using OpenCV ( Python , C++ ) |
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值