【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

这篇具有很好参考价值的文章主要介绍了【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  在【快速阅读二】从OpenCv的代码中扣取泊松融合算子(Poisson Image Editing)并稍作优化 一文的最后,我曾经提到有个使用泊松融合来来实现Seamless Tiling的效果,我自己尝试去实现,暂时没有获取正确的结果,论文里给出的效果如下: 

   【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。                              

  一开始我没怎么看这个tinling的意思,总是以为算法的目的是左图通过泊松融合的处理,能够处理成右图的效果,所以怎么测试也打不到真确的结果。

  后面又看了几篇文章,原来他并不是这个意思,注意到上面左图里上下共有2*3个相同的块,如下图所示:  

                                 【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

  他的意思是通过修改某种边界条件对这个图使用泊松融合,得到后的结果图,再进行拼接就可以得到那种无缝的效果了,即先泊松,再拼接,而不是先拼接,后泊松。我们去看看Tiling这个单词的意思也明白这个道理了。 

  那么在原文中他说只需要  we have chosen fnorth = fsouth = 0:5(gnorth + gsouth), and similarly for the eastand west borders.就可以了。

  后面我在泊松图像编辑(Possion Image Edit)原理、实现与应用 这位仁兄的博客的尾部也看到了关于这个过程的一个较为详细的注释,直接复制他博客里的图吧(谢谢)。

 

【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

  即用原图的梯度场,用修改后边界后的图作为融合的前景图进行融合,这样得到的融合的结果图,一个简单的代码如下所示:

void IM_SeamlessTiling(unsigned char* Src, unsigned char* Dest, int Width, int Height, int Stride)
{
    int Channel = Stride / Width;
    unsigned char* Fore = (unsigned char*)malloc(Height * Stride * sizeof(unsigned char));
    unsigned char* Mask = (unsigned char*)calloc(Height * Width, sizeof(unsigned char));
    memcpy(Fore, Src, Height * Stride);
    //    上下边界和左右边界设为原图像的边界和的一半。
    for (int X = 0; X < Width * Channel; X++)
    {
        Fore[X] = (Src[X] + Src[(Height - 1) * Stride + X]) / 2;
        Fore[(Height - 1) * Stride + X] = Fore[X];
    }
    for (int Y = 1; Y < Height - 1; Y++)
    {
        for (int C = 0; C < Channel; C++)
        {
            Fore[Y * Stride + C] = (Src[Y * Stride + C] + Src[Y * Stride + (Width - 1) * Channel + C]) / 2;
            Fore[Y * Stride + (Width - 1) * Channel + C] = Fore[Y * Stride + C];
        }
    }
    memset(Mask , 255, Width * Height);
    //    然后引导向量场仍然使用原图像的梯度场。这样得到的结果就可以用来无缝拼接
    //    最后一个参数为0,倒数第二个参数也为,Mask设置为全255,则就是直接使用Src的梯度场了
    IM_NormalClone(Fore, Src, Mask, Dest, Width, Height, Stride, 0, 0);
    free(Fore);
    free(Mask);
}

  在原始的opencv代码里,对于蒙版在内部有个如下的操作:

    Mat Kernel(Size(3, 3), CV_8UC1);
    Kernel.setTo(Scalar(1));
    erode(binaryMask, binaryMask, Kernel, Point(-1,-1), 3);

  我感觉我在上一篇文章里说到他的作用是错误的,按理说不应该需要这个的,但是实际测试就是用了这个对于非规则的图还是有一定好处的,他融合的更为自然,但是在这里的Tiling的应用中,就不应该需要了。

  这个简单的操作的效果确实还是蛮好玩的,除去论文里那个图,我们有弄了几副测试图,效果如下:

   【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。  【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

                【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。                              【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

 

                                                 【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。                                                                                                                  【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。   

                  直接拼贴的效果                                           泊松融合后拼接的效果

  以下是拼接过程中使用到的小图。

         【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。             【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。                 【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

     可见进行泊松融合后的图,弥合的非常自然。

  还是在同一篇博客里,作者还对这个想法进行了扩展,因为前面的融合是对单幅图四个边进行融合,另外一个更为常见的情形是对两个不同的图片在某一条边进行融合,这个情况再图像拼接, 多福图像合成等等方面也有着较为常见的应用。

  比如两幅图在水平方向进行拼接,这个时候就可以用如下的思路来解决问题(也是直接拷贝的作者的原图,谢谢):

       【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

   这个图的思路也是很简单的,左右两幅图拼接,则在左侧图的最右侧那一列以及右侧图最左侧那一列,都用两幅图的平均值代替,然后分别用两幅图各自的梯度场进行泊松融合,得到的两幅图再进行拼接,就显得自然了。

   一个简单的代码如下所示:

void IM_InnerSeamlessStitching(HBitmap Src1, HBitmap Src2, HBitmap Dest1, HBitmap Dest2, int Direction)
{
    int Channel = Src1.Stride / Src1.Width;
    if (Src1.PixelFormat != Src1.PixelFormat)                return;
    if ((Direction == 0) && (Src1.Height != Src2.Height))    return;
    if ((Direction == 1) && (Src1.Width != Src2.Width))        return;

    unsigned char* Fore1 = (unsigned char*)malloc(Src1.Height * Src1.Stride * sizeof(unsigned char));
    unsigned char* Fore2 = (unsigned char*)malloc(Src2.Height * Src2.Stride * sizeof(unsigned char));
    unsigned char* Mask1 = (unsigned char*)calloc(Src1.Height * Src1.Width, sizeof(unsigned char));
    unsigned char* Mask2 = (unsigned char*)calloc(Src2.Height * Src2.Width, sizeof(unsigned char));

    memcpy(Fore1, Src1.Scan0, Src1.Height * Src1.Stride);
    memcpy(Fore2, Src2.Scan0, Src2.Height * Src2.Stride);

    //    水平方向融合
    if (Direction == 0)
    {
        for (int Y = 0; Y < Src1.Height; Y++)
        {
            if (Channel == 1)
            {
                int Avg = (Src1.Scan0[Y * Src1.Stride + Src1.Width - 1] + Src2.Scan0[Y * Src2.Stride]) / 2;
                Fore1[Y * Src1.Stride + Src1.Width - 1] = Avg;
                Fore2[Y * Src2.Stride] = Avg;
            }
            else
            {
                int AvgB = (Src1.Scan0[Y * Src1.Stride + (Src1.Width - 1) * 3 + 0] + Src2.Scan0[Y * Src2.Stride + 0]) / 2;
                int AvgG = (Src1.Scan0[Y * Src1.Stride + (Src1.Width - 1) * 3 + 1] + Src2.Scan0[Y * Src2.Stride + 1]) / 2;
                int AvgR = (Src1.Scan0[Y * Src1.Stride + (Src1.Width - 1) * 3 + 2] + Src2.Scan0[Y * Src2.Stride + 2]) / 2;
                Fore1[Y * Src1.Stride + (Src1.Width - 1) * 3 + 0] = AvgB;
                Fore1[Y * Src1.Stride + (Src1.Width - 1) * 3 + 1] = AvgG;
                Fore1[Y * Src1.Stride + (Src1.Width - 1) * 3 + 2] = AvgR;
                Fore2[Y * Src2.Stride + 0] = AvgB;
                Fore2[Y * Src2.Stride + 1] = AvgG;
                Fore2[Y * Src2.Stride + 2] = AvgR;
            }
        }
    }
    else if (Direction == 1)
    {
        for (int X = 0; X < Src1.Width * Channel; X++)
        {
            //    上下两个可以采用不一样的值,但是做点融合也是不错的,实测还是有点小问题
            //    Fore1[(Src1.Height - 1) * Src1.Stride + X] = (Src1.Scan0[(Src1.Height - 1) * Src1.Stride + X] * 77 + Src2.Scan0[X] * 51) / 128;
            //    Fore2[X] = (Src1.Scan0[(Src1.Height - 1) * Src1.Stride + X] * 51 + Src2.Scan0[X] * 77) / 128;*/
            
            int Avg = (Src1.Scan0[(Src1.Height - 1) * Src1.Stride + X] + Src2.Scan0[X]) / 2;
            Fore1[(Src1.Height - 1) * Src1.Stride + X] = Avg;
            Fore2[X] = Avg;
        }
    }
    memset(Mask1, 255, Src1.Width * Src1.Height);
    memset(Mask2, 255, Src2.Width * Src2.Height);
    //    然后引导向量场仍然使用原图像的梯度场。这样得到的结果就可以用来无缝拼接
    //    最后一个参数为0,倒数第二个参数也为,Mask设置为全255,则就是直接使用Src的梯度场了
    IM_NormalClone(Fore1, Src1.Scan0, Mask1, Dest1.Scan0, Src1.Width, Src1.Height, Src1.Stride, 0, 0);
    IM_NormalClone(Fore2, Src2.Scan0, Mask2, Dest2.Scan0, Src2.Width, Src2.Height, Src2.Stride, 0, 0);

    free(Fore1);
    free(Fore2);
    free(Mask1);
    free(Mask2);
}

   我手上没有合适的图片,就自己随意处理了结果图,感觉还有那么一点用处:

   【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。  【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

   【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。  【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

  可以看到,使用泊松融合后,已经没有明显的分解线了。

  这个算法有一个很好的用法就是,对于某些大图像,需要分块进行处理,但是分块后必然会出现块于块之间出现过渡不自然的情况,直接拼接在一起有明显的痕迹,用上面的泊松融合则可以解决这个问题。

  另外, 实际中可能还会遇到分界线不是垂直或者水平的现象,这种,个人感觉也是可以通过泊松融合来解决,只要能确定相应的分解mask,在分解线处求平均值,就一样能把边缘值的影响平均到图像内部,这个暂时还没有去研究。可以留待后续继续处理。

  另外,提一个算法优化方面的问题,如果图像比较大,直接处理会打来很大的算法效率瓶颈,那么在这里其实是没有必要全图处理的,可以在相邻的区域取一定范围的像素进行融合就可以了,而且这个一定范围也可以做些固化,比如我们知道在OpenCV里不同长度的FFT其运算效率是不同的,对于有些数据,效率很高,因此,我们可以取这些值来做运算。、

    对应的测试Demo和测试图片已经更新,下载地址: https://files.cnblogs.com/files/Imageshop/PossionBlending.rar?t=1705395766&download=true

       如果想时刻关注本人的最新文章,也可关注公众号或者添加本人微信:  laviewpbt

                             【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

翻译

搜索

复制文章来源地址https://www.toymoban.com/news/detail-805245.html

到了这里,关于【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Opencv】----- 图片无缝融合

    上次写了一篇关于GAN缺陷生成的图片的,发现大家的对这个根本不感兴趣,可能是用于在座的各位觉得样本有的是,我为什么还苦哈哈的去生成啊,说的也不是没有道理,可能只是我搞了更加苦哈哈的工业深度学习吧,所以这种技术才显得格外感兴趣,最讨厌听到的客户说,

    2024年02月11日
    浏览(22)
  • 图像融合论文阅读:CS2Fusion: 通过估计特征补偿图谱实现自监督红外和可见光图像融合的对比学习

    @article{wang2024cs2fusion, title={CS2Fusion: Contrastive learning for Self-Supervised infrared and visible image fusion by estimating feature compensation map}, author={Wang, Xue and Guan, Zheng and Qian, Wenhua and Cao, Jinde and Liang, Shu and Yan, Jin}, journal={Information Fusion}, volume={102}, pages={102039}, year={2024}, publisher={Elsevier} } 论文级

    2024年01月22日
    浏览(38)
  • 在html中使用js实现图片的无缝滚动(四种状态)

    获取整个ul和ul下面的所有li, 把ul里面的li内容添加一份,因为需要完成图片滚动效果所以需要二份完成无缝对接, 定义初始速度。 设置定时器 在定时中进行判断 实现原理:因为ul是跟着父元素div进行定位的,所以ul的offsetleft的值初始值为0。 只需要改变ul的left值就可以完成

    2024年02月09日
    浏览(27)
  • 无缝数据转换!使用C++ 实现 Excel文件与CSV之间的相互转换

    CSV格式是一种通用的文本文件格式,可在多个应用程序之间共享和使用。相比之下,Excel文件是一种电子表格格式,通常只能在Microsoft Excel中编辑和查看。因此,将Excel文件转换为CSV格式可使数据更方便地在其他应用程序中使用;而将CSV文件转换为Excel格式则有利于在Microsoft

    2024年02月11日
    浏览(32)
  • 【计算机视觉课程设计】基于暗通道先验单幅图像去雾算法的实现(MATLAB)

           随着信息化时代的到来,计算机视觉得以迅速发展,在社会生活中的各个领域发挥了重要作用。然而,近年来大气污染逐渐加重,雾霾天气出现的频率越来越高,导致户外成像设备不能捕捉到高质量的清晰图像,无法正常运用于计算机视觉系统。因此,对雾天图像进

    2024年02月05日
    浏览(33)
  • 【快速阅读一】带蒙版的均值模糊快速实现以及其在填充无效区域时的应用。

    最近遇到一个需求,从相机获取的数据局部区域存在空值,即那些地方没有有效数据,如果直接赋值为0,则很有可能得到错误的结果,如果不填充值,很多算法又无法进行,因此,需要一种填充算法把这些空白区域设置成合适的值。 我想了一下,有几个算法可 能可以解决这

    2024年02月04日
    浏览(22)
  • 深度学习中的图像融合:图像融合论文阅读与实战

    个人博客 :Sekyoro的博客小屋 个人网站 :Proanimer的个人网站 介绍图像融合概念,回顾sota模型,其中包括数字摄像图像融合,多模态图像融合, 接着评估一些代表方法 介绍一些常见应用,比如RGBT目标跟踪,医学图像检查,遥感监测 动机: 由于硬件设备的理论和技术限制,单一

    2024年02月02日
    浏览(40)
  • AI论文技巧 │使用ChatGPT快速阅读文献--详细流程+实用指令【建议收藏】

    论文的长征路还没开始走,在最开始研究地图的时候,已经如看天书,那接下来的路很难攻克! 有什么好办法呢? 咱们可以利用ChatGPT的强大能力。只要输入文献,它就秒解文献里的关键信息,让我们迅速搞清楚 文献的主题、目的、手法和结果 ,别再费劲啃文了。 ◎ 找到关

    2024年02月21日
    浏览(47)
  • 图像融合论文阅读:(MFEIF)学习深度多尺度特征集成和边缘注意引导的图像融合

    @article{liu2021learning, title={Learning a deep multi-scale feature ensemble and an edge-attention guidance for image fusion}, author={Liu, Jinyuan and Fan, Xin and Jiang, Ji and Liu, Risheng and Luo, Zhongxuan}, journal={IEEE Transactions on Circuits and Systems for Video Technology}, volume={32}, number={1}, pages={105–119}, year={2021}, publisher={IEEE

    2024年02月04日
    浏览(31)
  • 使用Web3.js与OKX Web3钱包进行交互:实现去中心化应用的无缝连接

    随着Web3.0技术的不断发展,越来越多的开发者开始探索如何利用去中心化钱包与区块链网络进行交互。在这篇文章中,我们将深入探讨如何通过Web3.js库来连接和操作OKX Web3钱包,以实现对加密货币、NFT以及链上智能合约的管理和交易。 Web3.js 是一个由以太坊社区开发的核心

    2024年02月19日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包