Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【快速阅读三】使用泊松融合实现单幅图的无缝拼贴及消除两幅图片直接的拼接缝隙。

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

作者头像
用户1138785
发布于 2024-01-20 02:42:51
发布于 2024-01-20 02:42:51
1.1K00
代码可运行
举报
运行总次数:0
代码可运行

在【快速阅读二】从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)原理、实现与应用 这位仁兄的博客的尾部也看到了关于这个过程的一个较为详细的注释,直接复制他博客里的图吧(谢谢)。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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代码里,对于蒙版在内部有个如下的操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    Mat Kernel(Size(3, 3), CV_8UC1);
    Kernel.setTo(Scalar(1));
    erode(binaryMask, binaryMask, Kernel, Point(-1,-1), 3);

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

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

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

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

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

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【快速阅读二】从OpenCv的代码中扣取泊松融合算子(Poisson Image Editing)并稍作优化
  泊松融合我自己写的第一版程序大概是2016年在某个小房间里折腾出来的,当时是用的迭代的方式,记得似乎效果不怎么样,没有达到论文的效果。前段时间又有网友问我有没有这方面的程序,我说Opencv已经有了,可以直接使用,他说opencv的框架太大,不想为了一个功能的需求而背上这么一座大山,看能否做个脱离那个环境的算法出来,当时,觉得工作量挺大,就没有去折腾,最近年底了,项目渐渐少了一点,公司上面又在搞办公室政治,我地位不高,没有参与权,所以乐的闲,就抽空把这个算法从opencv里给剥离开来,做到了完全不依赖其他库实现泊松融合乐,前前后后也折腾进半个月,这里还是做个开发记录和分享。
用户1138785
2024/01/17
5550
【快速阅读二】从OpenCv的代码中扣取泊松融合算子(Poisson Image Editing)并稍作优化
【短道速滑二】古老的基于亮度平均值的自动Gamma校正算法。
在github上搜索代码Auto Gamma Correction,找到一个比较古老的代码,详见:https://github.com/PedramBabakhani/Automatic-Gamma-Correction,配套的代码使用VHDL语言写的,看了半天一个for循环没有,是在看不懂,幸好里面有篇算法对应的论文下载,论文名字叫《ASIC implementation of automatic gamma correction based on average of brightness 》,下载看了下,大概搞明白了他的大概意思。
用户1138785
2020/07/27
1.2K0
基础的拉普拉斯金字塔融合用于改善图像增强中易出现的过增强问题(一)
  拉普拉斯金字塔融合是多图融合相关算法里最简单和最容易实现的一种,我们在看网络上大部分的文章都是在拿那个苹果和橙子融合在一起,变成一个果橙的效果作为例子说明。在这方面确实融合的比较好。但是本文我们主要讲下这个在图像增强方面的运用。
用户1138785
2019/05/24
1.9K0
【算法随记五】使用FFT变换自动去除图像中严重的网纹。
  这个课题在很久以前就已经有所接触,不过一直没有用代码去实现过。最近买了一本《机器视觉算法与应用第二版》书,书中再次提到该方法:使用傅里叶变换进行滤波处理的真正好处是可以通过使用定制的滤波器来消除图像中某些特定频率,例如这些特定频率可能代表着图像中重复出现的纹理。
用户1138785
2019/10/08
1.8K1
【算法随记五】使用FFT变换自动去除图像中严重的网纹。
学界 | 从泊松方程的解法,聊到泊松图像融合
AI 科技评论按,本文作者成指导,字节跳动算法工程师,本文首发于知乎(https://zhuanlan.zhihu.com/p/68349210),AI 科技评论获其授权转载,正文内容如下:
AI科技评论
2019/06/18
1.9K0
学界 | 从泊松方程的解法,聊到泊松图像融合
【手撕算法】图像融合之泊松融合:原理讲解及C++代码实现
本人为图像处理的小白,在机缘巧合下,看到了泊松融合的图像处理,觉得很强大也十分有趣,对其中的数学原理也十分感兴趣。因此便查找了很多资料,包括原理加实现。这篇文章主要基于我自己对泊松融合的理解,再进行解释一遍,并将它进行实现,一个是帮助自己加深了解,第二个也算是作为自己的笔记。
周旋
2022/09/19
4K1
【手撕算法】图像融合之泊松融合:原理讲解及C++代码实现
图像处理中任意核卷积(matlab中conv2函数)的快速实现。
用户1138785
2018/01/03
3.9K0
OpenCV图像拼接改进算法之完美拼接
之前写了两篇文章分别是图像单应性矩阵变换与图像拼接,图像拼接中使用单应性矩阵实现图像特征对齐,从而为图像拼接特别是无缝拼接打下基础,看一下上一篇我的图像拼接效果如下:
OpenCV学堂
2020/02/20
13.8K2
四种比较简单的图像显著性区域特征提取方法原理及实现-----> AC/HC/LC/FT。
本文探讨了四种显著性检测算法及其在图像处理中的应用。首先介绍了显著性检测的背景和意义,然后详细阐述了基于高斯差分(OGD)、全局统计(GS)、局部自适应(LOA)和自适应阈值(AT)四种显著性检测算法的原理和实现。文章还对各种算法的优缺点进行了分析,并通过实验对四种算法的性能进行了评估。
用户1138785
2018/01/03
3.6K0
四种比较简单的图像显著性区域特征提取方法原理及实现-----> AC/HC/LC/FT。
13行代码实现最快速最高效的积分图像算法。
本文介绍了基于积分图像的计算机图像处理技术,包括其基本概念、操作步骤和应用场景。通过积分图像,可以方便地进行图像的局部特征提取和图像处理,包括图像滤波、边缘检测、图像分割和特征提取等。同时,本文还介绍了一些常用的积分图像处理算法,包括卷积、高斯滤波、Canny边缘检测和霍夫变换等。这些算法在计算机视觉和图像处理领域都有广泛的应用,对于图像处理的效果和性能有着重要的影响。
用户1138785
2018/01/03
1.9K0
13行代码实现最快速最高效的积分图像算法。
单应性矩阵应用-基于特征的图像拼接
前面写了一篇关于单应性矩阵的相关文章,结尾说到基于特征的图像拼接跟对象检测中单应性矩阵应用场景。得到很多人留言反馈,让我继续写,于是就有这篇文章。这里有两张照片(我手机拍的),背景是我老家的平房,周围是一片开阔地带,都是麦子。有图为证:
OpenCV学堂
2020/02/21
3.2K1
AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。
  查表算法,无疑也是一种非常常用、有效而且快捷的算法,我们在很多算法的加速过程中都能看到他的影子,在图像处理中,尤其常用,比如我们常见的各种基于直方图的增强,可以说,在photoshop中的调整菜单里80%的算法都是用的查表,因为他最终就是用的曲线调整。
用户1138785
2022/10/28
1.6K0
AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。
【沥血整理】灰度(二值)图像重构算法及其应用(morphological reconstruction)。
        不记得是怎么接触并最终研究这个课题的了,认识我的人都知道我是没有固定的研究对象的,一切看运气和当时的兴趣。本来研究完了就放在那里了,一直比较懒的去做总结,但是想一想似乎在网络上就没有看到关于这个方面的资料,能搜索到的都是一些关于matlab相关函数的应用,决定还是抽空趁自己对这个算法还有点记忆的时候写点东西吧,毕竟这个算法还有一些应用是值得回味和研究的。而且也具有一定的工程价值。
用户1138785
2022/09/21
1K0
【沥血整理】灰度(二值)图像重构算法及其应用(morphological reconstruction)。
【查虫日志】快速判断一副灰度图像中是否只有黑色和白色值(即是否为二值图像)过程中bool变量的是是非非。
  二值图像我们在图像处理过程中是经常遇到的,有的时候我们在进行一个算法处理前,需要判断下一副图像的数据是否符合二值图的需求,这个时候我们可以写个简单的函数来做个判断,比如我写了一个很简单的的代码如下:
用户1138785
2019/07/01
7930
【查虫日志】快速判断一副灰度图像中是否只有黑色和白色值(即是否为二值图像)过程中bool变量的是是非非。
OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)
seamlessClone是OpenCV3后添加的函数,使用此函数可以轻松将一幅图像中的指定目标复制后粘贴到另一幅图像中,并自然的融合。函数说明:
Color Space
2021/03/09
5.1K0
关于Cewu Lu等的《Combining Sketch and Tone for Pencil Drawing Production》一文铅笔画算法的理解和笔录。
本文研究了如何利用图像处理技术对图像进行细化和去噪,并探讨了其在医学图像处理领域的应用。作者提出了一种基于频率域的图像细化算法,该算法采用迭代的方式对图像进行细化,并通过实验证明该算法可以有效提高图像的细化效果。同时,作者还提出了一种基于小波变换的图像去噪算法,该算法采用小波变换对图像进行分解,并通过实验证明该算法可以有效提高图像的去噪效果。在医学图像处理领域,图像细化和去噪是常用的预处理步骤,因此该算法具有较高的实用价值。
用户1138785
2018/01/03
1.2K0
关于Cewu Lu等的《Combining Sketch and Tone for Pencil Drawing Production》一文铅笔画算法的理解和笔录。
一种快速简便优秀的全局曲线调整与局部信息想结合的非线性彩色增强算法(多图深度分析和探索)
  本文的分析基于《Adaptive and integrated neighborhood-dependent approach for nonlinear enhancement of color images》一文相关内容,但对其进行了深度的改良。
用户1138785
2019/10/15
1.1K0
一种快速简便优秀的全局曲线调整与局部信息想结合的非线性彩色增强算法(多图深度分析和探索)
【算法随记三】小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读。
  在本人的博客里,分享了有关中值模糊的O(1)算法,详见:任意半径中值滤波(扩展至百分比滤波器)O(1)时间复杂度算法的原理、实现及效果 ,这里的算法的执行时间和参数是无关的。整体来说,虽然速度也很快,但是在某些特殊情况下我们还是需要更快的速度。特别是对于小半径的中值,我们有理由去对其进一步的优化的。本文我们进一步探讨这个问题。
用户1138785
2019/07/02
6650
C# 图片RGB处理判断
方法需要传入新的图片对象(Bitmap),原图的标准RGB平均值,新图的RGB颜色,新图和原图的RGB相差偏移量。 返回新图的RGB平均值是否在原图的RGB平均值偏移量之内。
Echo_Wish
2023/11/30
2520
【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSE算法的Demosaic过程优化。
  Demosaic,中文直接发翻译为去马赛克, 但是其本质上并不是去除马赛克,这让很多第一次接触这个名词或者概念的人总会想的更多。因此,一般传感器在采集信息时一个位置只采集RGB颜色中的一个通道,这样可以减少采集量,降低成本,由于人的视觉对绿色最为敏感,所以一般情况下,绿色分量会比红色和蓝色分量多一倍的信息,这样,根据RGB不同的位置排布,就产生了RGGB、GBRG、GRBG、BGGR四种常用的模式,比如RGGB模式就如下所示:
用户1138785
2024/09/03
2250
【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSE算法的Demosaic过程优化。
推荐阅读
【快速阅读二】从OpenCv的代码中扣取泊松融合算子(Poisson Image Editing)并稍作优化
5550
【短道速滑二】古老的基于亮度平均值的自动Gamma校正算法。
1.2K0
基础的拉普拉斯金字塔融合用于改善图像增强中易出现的过增强问题(一)
1.9K0
【算法随记五】使用FFT变换自动去除图像中严重的网纹。
1.8K1
学界 | 从泊松方程的解法,聊到泊松图像融合
1.9K0
【手撕算法】图像融合之泊松融合:原理讲解及C++代码实现
4K1
图像处理中任意核卷积(matlab中conv2函数)的快速实现。
3.9K0
OpenCV图像拼接改进算法之完美拼接
13.8K2
四种比较简单的图像显著性区域特征提取方法原理及实现-----> AC/HC/LC/FT。
3.6K0
13行代码实现最快速最高效的积分图像算法。
1.9K0
单应性矩阵应用-基于特征的图像拼接
3.2K1
AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。
1.6K0
【沥血整理】灰度(二值)图像重构算法及其应用(morphological reconstruction)。
1K0
【查虫日志】快速判断一副灰度图像中是否只有黑色和白色值(即是否为二值图像)过程中bool变量的是是非非。
7930
OpenCV图像无缝融合-seamlessClone介绍与使用(Python/C++源码)
5.1K0
关于Cewu Lu等的《Combining Sketch and Tone for Pencil Drawing Production》一文铅笔画算法的理解和笔录。
1.2K0
一种快速简便优秀的全局曲线调整与局部信息想结合的非线性彩色增强算法(多图深度分析和探索)
1.1K0
【算法随记三】小半径中值模糊的急速实现(16MB图7.5ms实现) + Photoshop中蒙尘和划痕算法解读。
6650
C# 图片RGB处理判断
2520
【工程应用十二】Bayer图像格式中Hamilton-Adams及Zhang Wu 基于LMMSE算法的Demosaic过程优化。
2250
相关推荐
【快速阅读二】从OpenCv的代码中扣取泊松融合算子(Poisson Image Editing)并稍作优化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验