美文网首页
【OPENCV】seamless clone 功能比较

【OPENCV】seamless clone 功能比较

作者: ItchyHiker | 来源:发表于2018-08-04 17:22 被阅读0次

    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. https://www.learnopencv.com/seamless-cloning-using-opencv-python-cpp/

    相关文章

      网友评论

          本文标题:【OPENCV】seamless clone 功能比较

          本文链接:https://www.haomeiwen.com/subject/ulmmvftx.html