图像的简单copyPaste实现

简介

  本篇是对实现复制粘贴的笔记记录。
注:本篇使用的所有图像皆来源自网络,如有侵权,请联系本人删除。

基本原理

  这里分为两步:1、从第一张图像中抠出感兴趣区域。 
                 2、将感兴趣区域粘贴到第二张图片中。
    分别可以参考前面文档:1、opencv实现图像分割,分离前景和背景(2)
                          2、残差金字塔实现

抠图部分

  参考前面的提到的文档:《opencv实现图像分割,分离前景和背景(2)》,最后将扣出来的感兴趣图像复制到resCopy,并将对应图像掩码保存到
binMask中。
     对应结果显示如下:
     
        手动抠图操作                  扣去图像的掩码                    抠出的图像

掩码处理

  在直接根据掩码进行图像粘贴融合之前,需要先对掩码进行处理,否则会导致融合图像的边缘很模糊。
具体的操作,可以参考前面提到的文档:《残差金字塔实现》
    大致代码如下:
GaussianBlur(pySrc[0], pyDst[0], Size(g_nGaussianBlurValue*2+1,g_nGaussianBlurValue*2+1), 0, 0);
pyWidth[1]  = pyWidth[0] / 2;
pyHeight[1] = pyHeight[0] / 2;
resize(pyDst[0], pySrc[1], Size(pyHeight[1], pyWidth[1]));
 
GaussianBlur(pySrc[1], pyDst[1], Size(g_nGaussianBlurValue*2+1,g_nGaussianBlurValue*2+1), 0, 0);
pyWidth[2]  = pyWidth[1] / 2;
pyHeight[2] = pyHeight[1] / 2;
resize(pyDst[1], pySrc[2], Size(pyHeight[2], pyWidth[2]));
 
GaussianBlur(pySrc[2], pyDst[2], Size(g_nGaussianBlurValue*2+1,g_nGaussianBlurValue*2+1), 0, 0);
pyWidth[3]  = pyWidth[2] / 2;
pyHeight[3] = pyHeight[2] / 2;
resize(pyDst[2], pySrc[3], Size(pyHeight[3], pyWidth[3]));
 
resize(pySrc[3], tmp, Size(pyHeight[2], pyWidth[2]));
pyDst[2] = tmp;
 
resize(pyDst[2], tmp, Size(pyHeight[1], pyWidth[1]));
pyDst[1] = tmp;
 
resize(pyDst[1], tmp, Size(pyHeight[0], pyWidth[0]));
pyDst[0] = tmp;
 
imshow("mask22", pyDst[0]);
binMask = pyDst[0];
  最开始的pySrc[0]就是之前的掩码图像binMask,先建立该图像的高斯金字塔,接着对图像进行恢复。注意这里并没有使用残差金字塔,所以恢复后的
图像将会是原图像的边缘模糊处理后图像。
    对应的效果显示如下:
                           
              原始掩码图像                                       处理后掩码图像

图像粘贴

  获得了处理之后的掩码,接着就是进行最后的图像粘贴融合操作。
  1、计算出掩码对应感兴趣区域,在原图中的坐标位置,保存到rectResCopy中。
void getResCopyAddr(Mat src){
    int i, j;
    IplImage ipI = src;
    int width = src.rows;
    int height = src.cols;
    int minWidth,maxWidth, minHeight, maxHeight;
    CvScalar s1;
 
    for(i=0; i<width; i++){
        for(j=0; j<height; j++){
            s1 = cvGet2D(&ipI, i, j);
            if(s1.val[0] > 0){
                if(maxWidth == 0){
                    minWidth = i;   
                    maxWidth = i;   
                    minHeight = j;  
                    maxHeight = j;  
                }
                if(minWidth > i)
                    minWidth = i;
                if(maxWidth < i)
                    maxWidth = i;
                if(minHeight > j)
                    minHeight = j;
                if(maxHeight < j)
                    maxHeight = j;
            }
        }
    }
    rectResCopy.x = minWidth;
    rectResCopy.y = minHeight;
    rectResCopy.width = maxWidth - minWidth;
    rectResCopy.height = maxHeight - minHeight;
}
  2、根据掩码图像像素值,进行融合图像权重计算计算:如果掩码值为0,则新像素值全部为被粘贴图像;如果掩码值为[1, 254],则新
像素值为:(被粘贴图像 * (1 - (掩码值 / 255))) + (感兴趣区域 * (掩码值 / 255));如果掩码值为255,则新像素值为感兴趣区域。
void getPaste(Mat src1, Mat src2, Rect rectAddr){
    int i, j;
    IplImage ip1 = src1;
    IplImage ip2 = src2;
    IplImage ip3 = binMask;
    CvScalar s1, s2, s3;
    int dstWidth  = src1.rows;
    int dstHeight = src1.cols;
    int addrX = 70, addrY = 70;
    double scale;
 
    if(addrX + rectAddr.width > dstWidth){
        printf("pic Size is too big in Width!\n");
        return; 
    }
    if(addrY + rectAddr.height > dstHeight){
        printf("pic Size is too big in Height!\n");
        return; 
    }
 
    for(i=rectAddr.x; i<rectAddr.x + rectAddr.width; i++){
        for(j=rectAddr.y; j<rectAddr.y + rectAddr.height; j++){
            s1 = cvGet2D(&ip1, addrX + i - rectAddr.x, addrY + j -rectAddr.y);
            s2 = cvGet2D(&ip2, i, j);
            s3 = cvGet2D(&ip3, i, j);
            if(s3.val[0] > 0){
                scale = s3.val[0] / 255;
                s1.val[0] = (s1.val[0] * (1 - scale)) + (s2.val[0] * scale);
                s1.val[1] = (s1.val[1] * (1 - scale)) + (s2.val[1] * scale);
                s1.val[2] = (s1.val[2] * (1 - scale)) + (s2.val[2] * scale);
                cvSet2D(&ip1, addrX + i - rectAddr.x, addrY + j -rectAddr.y, s1);
            }                                                                                                                        
        }
    }
}

结果显示

  显示的结果如下:
                                                         
                直接融合                                                 处理掩码后融合
  代码下载:http://download.csdn.net/detail/u011630458/9424343
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值