{"id":24903555,"url":"https://github.com/cuixing158/multibandblender","last_synced_at":"2025-03-27T19:34:43.900Z","repository":{"id":272419428,"uuid":"916525736","full_name":"cuixing158/multiBandBlender","owner":"cuixing158","description":"matlab  multiBandBlender implementation","archived":false,"fork":false,"pushed_at":"2025-03-07T10:55:25.000Z","size":16664,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-07T11:34:44.523Z","etag":null,"topics":["alogorithms","gaussian-pyr","homography","image-blending","image-processing","image-stitching","imageblending","laplacian-pyramid","multi-band-blending","multiband"],"latest_commit_sha":null,"homepage":"","language":"MATLAB","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cuixing158.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":"https://raw.githubusercontent.com/cuixing158/OpticalFlow-Visualization/refs/heads/main/README_media/sponsors.jpg"}},"created_at":"2025-01-14T09:13:50.000Z","updated_at":"2025-03-07T10:55:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"f1cd5862-eb52-40c0-b753-c3f22b1deb08","html_url":"https://github.com/cuixing158/multiBandBlender","commit_stats":null,"previous_names":["cuixing158/multibandblender"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuixing158%2FmultiBandBlender","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuixing158%2FmultiBandBlender/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuixing158%2FmultiBandBlender/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cuixing158%2FmultiBandBlender/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cuixing158","download_url":"https://codeload.github.com/cuixing158/multiBandBlender/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245911498,"owners_count":20692600,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alogorithms","gaussian-pyr","homography","image-blending","image-processing","image-stitching","imageblending","laplacian-pyramid","multi-band-blending","multiband"],"created_at":"2025-02-01T22:21:25.233Z","updated_at":"2025-03-27T19:34:43.873Z","avatar_url":"https://github.com/cuixing158.png","language":"MATLAB","funding_links":["https://raw.githubusercontent.com/cuixing158/OpticalFlow-Visualization/refs/heads/main/README_media/sponsors.jpg"],"categories":[],"sub_categories":[],"readme":"\n# Multi\\-Band Blender MATLAB\n\n[![Sponsor](https://img.shields.io/badge/-Sponsor-red?style=for-the-badge\u0026logo=GitHub-Sponsors\u0026logoColor=white)](https://raw.githubusercontent.com/cuixing158/OpticalFlow-Visualization/refs/heads/main/README_media/sponsors.jpg)\n[![Open in MATLAB Online](https://www.mathworks.com/images/responsive/global/open-in-matlab-online.svg)](https://matlab.mathworks.com/open/github/v1?repo=cuixing158/multiBandBlender\u0026file=ExamplesEntry.mlx)\n[![View multiBandBlender on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://ww2.mathworks.cn/matlabcentral/fileexchange/179089-multibandblender)\n![MATLAB build](https://img.shields.io/badge/MATLAB-R2024b+-success.svg)\n[![MATLAB](https://github.com/cuixing158/multiBandBlender/actions/workflows/ci.yml/badge.svg)](https://github.com/cuixing158/multiBandBlender/actions/workflows/ci.yml)\n\n# :eyes: Overview\n\nMulti\\-Band Blender在MATLAB中的实现示例，主要是展示如何使用[MultiBandBlender类](./MultiBandBlender.m),三个成员函数`prepare()`,`feed()`,`blend()`在不同的应用场景下如何融合使用。\n\n# :clipboard: Requirements\n\n- MATLAB R2024b or later\n- Computer Vision Toolbox™\n- Image Processing Toolbox™\n\n\u003e [!NOTE]\n\u003e 如果需要在MATLAB环境中运行python代码，那么要安装[opencv\\-python](https://pypi.org/project/opencv-python/)包。\n\n# :notebook: 示例1\n\n本示例简单展示了两幅图像overlap区域的融合，从估计对齐的单应矩阵，然后使用alpha线性组合融合有比较明显的重叠区，随后使用multiBand融合可以明显改善效果。当然也支持对多幅图像输入融合，不限于本示例的2幅图像。\n\n```matlab\n%  img1 和 img2 是需要融合的两幅图像\nimg1 = imread('data/medium16.JPG');\nimg2 = imread('data/medium17.JPG');\nimshowpair(img1,img2,\"montage\")\n```\n\n![figure_0.png](ExamplesEntry_media/figure_0.png)\n\n这2幅图像有比较大的亮度差异，特别是曝光有明显不同。\n\n\u003cdetails\u003e\n\n\u003csummary\u003e单应矩阵计算代码展开\u003c/summary\u003e\n\n## 计算单应矩阵\n\n使用典型传统的orb特征点算法和匹配，就可以得到从图像2到图像1的转换矩阵，该矩阵即单应矩阵包含在tform变量中。\n\n```matlab\ngray1 = im2gray(img1);\ngray2 = im2gray(img2);\n\npts1 = detectORBFeatures(gray1);\npts2 = detectORBFeatures(gray2);\n\n[features1,valid_points1] = extractFeatures(gray1,pts1);\n[features2,valid_points2] = extractFeatures(gray2,pts2);\n\nindexPairs = matchFeatures(features1,features2);\n\nmatchedPoints1 = valid_points1(indexPairs(:,1),:);\nmatchedPoints2 = valid_points2(indexPairs(:,2),:);\n\nfigure;\nshowMatchedFeatures(img1,img2,matchedPoints1,matchedPoints2,\"montage\");\n```\n\n![figure_1.png](ExamplesEntry_media/figure_1.png)\n\n```matlab\n\ntform = estgeotform2d(matchedPoints2,matchedPoints1,\"projective\");\nformat shortG\ndisp(\"单应矩阵A：\")\n```\n\n```matlabTextOutput\n单应矩阵A：\n```\n\n```matlab\ndisp(tform.A)\n```\n\n```matlabTextOutput\n      0.41316      0.17689       512.85\n     -0.32616      0.85997       93.323\n  -0.00046859   6.1022e-05            1\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003e全景图像范围计算代码展开\u003c/summary\u003e\n\n## 全景图像范围计算\n\n要把对齐的图像完整显示出来，就要计算整幅全景图像的在全局坐标系下的坐标范围，MATLAB中一般使用[imref2d](https://ww2.mathworks.cn/help/images/ref/imref2d.html)来代表图像位置空间的坐标参考范围。\n\n```matlab\n[h1,w1] = size(img1,[1,2]);\n[h2,w2] = size(img2,[1,2]);\npts_warp2 = transformPointsForward(tform,[1,w2,w2,1;1,1,h2,h2]');\npts_warp1 = [1,w1,w1,1;1,1,h1,h1]';\n[minA,maxA] = bounds([pts_warp1;pts_warp2]);\n\npanoramaWidth = round(maxA(1)-minA(1));\npanoramaHeight = round(maxA(2)-minA(2));\nxLimits = [minA(1),maxA(1)];\nyLimits = [minA(2),maxA(2)];\nR = imref2d([panoramaHeight,panoramaWidth],xLimits,yLimits)\n```\n\n```matlabTextOutput\nR = \n  imref2d with properties:\n\n           XWorldLimits: [1 2711.8]\n           YWorldLimits: [-843.8 935.03]\n              ImageSize: [1779 2711]\n    PixelExtentInWorldX: 0.99993\n    PixelExtentInWorldY: 0.9999\n    ImageExtentInWorldX: 2710.8\n    ImageExtentInWorldY: 1778.8\n       XIntrinsicLimits: [0.5 2711.5]\n       YIntrinsicLimits: [0.5 1779.5]\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\n\u003csummary\u003emask掩码区域计算代码展开\u003c/summary\u003e\n\n## mask掩码区域计算\n\n由于拼接融合算法普遍需要各自输入图像对应的mask图像作为输入，依旧使用上述步骤中的包含对齐单应矩阵的变量`tform`，输出全局参考空间位置坐标范围`R`来计算。\n\n```matlab\nmask1_warped = imageWarp(ones(h1,w1,\"logical\"),rigidtform2d(),OutputView=R);\nmask2_warped = imageWarp(ones(h2,w2,\"logical\"),tform,OutputView=R);\nmask = mask1_warped\u0026mask2_warped;\n\nfg =  imageWarp(img1,rigidtform2d(),outputView=R);\nbg = imageWarp(img2,tform,OutputView=R);\n\nblendImg = imblend(fg,bg,mask1_warped,Mode=\"Alpha\",ForegroundOpacity=0.6); % since R2024b\nfigure;\nimshow(blendImg,R)\ntitle('Blended Image(alpha blend)');\n```\n\n![figure_2.png](ExamplesEntry_media/figure_2.png)\n\n\u003c/details\u003e\n\n## multiBand融合\n\n由于multiBand算法是基于拉普拉斯金字塔对各个频段的不同细节特征进行的融合，为丰富各个频段的像素特征及光滑过渡，故最好需要对输入图像边界像素“镜像”处理。\n\n```matlab\nimg1_warped = imageWarp(img1,rigidtform2d(),OutputView=R,BorderMode=\"BORDER_REFLECT\");\nimg2_warped = imageWarp(img2,tform,OutputView=R,BorderMode=\"BORDER_REFLECT\");\nimshowpair(img2,img2_warped,\"montage\") % 镜像像素处理可视化对比\ntitle(\"original source image(left),reflect image(right)\")\n```\n\n![figure_3.png](ExamplesEntry_media/figure_3.png)\n\n调用MATLAB实现的算法类MultiBandBlender，该类与OpenCV的MultiBandBlender基本兼容，接口API保持一致。如果对于多幅图像输入，那么`prepare()`函数后，对每一幅图像进行一次`feed()`操作，最后通过`blend()`重建全景融合图。频段层级数目一般在2~10之间，数值越大，过渡区域越顺滑。\n\n```matlab\nblender = MultiBandBlender(10);  % num_bands=10\nblender = blender.prepare([1, 1, R.ImageSize(2),R.ImageSize(1)]);  % Prepare [x,y,width,height] global image area\n```\n\n由于之前已经计算单应矩阵，图像`img1_warped`，`img2_warped`已经对齐，故输入给`feed()`函数的第三个参数左上角点坐标为`[1,1]`。\n\n```matlab\nblender = blender.feed(img1_warped, mask1_warped, [1, 1]);  % Feed the first image and mask at position [1, 1]\nblender = blender.feed(img2_warped, mask2_warped, [1, 1]);  % Feed the second image and mask at position [1, 1]\n[dst, ~] = blender.blend();  % Perform the blending and get the result\nfigure;\nimshow(dst)\ntitle(\"Blended Image(multiBandBlend MATLAB Implementation)\")\n```\n\n![figure_4.png](ExamplesEntry_media/figure_4.png)\n\n## :notebook: opencv内置实现(可选项)\n\n此处直接调用opencv库的multiBlend看看融合效果，前提需要安装[opencv\\-python](https://pypi.org/project/opencv-python/)包。关于更多信息请参阅：[Call Python from MATLAB](https://ww2.mathworks.cn/help/matlab/call-python-libraries.html)\n\n```matlab\nblender = py.cv2.detail_MultiBandBlender(int64(0),int64(10));% num_blend=10\nblender.prepare(int64([0,0,R.ImageSize(2),R.ImageSize(1)])); % 总体全景图ROI区域，[x,y,width,height]形式\n\nfm = im2uint8(mask1_warped);% 注意opencv是以uint8类型表示mask掩码\nbm = im2uint8(mask2_warped);% 注意opencv是以uint8类型表示mask掩码\n\nblender.feed(py.numpy.array(img1_warped),py.numpy.array(fm),int64([0,0]));\nblender.feed(py.numpy.array(img2_warped),py.numpy.array(bm),int64([0,0]));\n\nresultAndMask = blender.blend(py.None, py.None);\n\npanorama = uint8(resultAndMask{1});\nfigure;\nimshow(panorama)\ntitle(\"Blended Image(opencv build-in multiBand)\")\n```\n\n![figure_5.png](ExamplesEntry_media/figure_5.png)\n\n# :notebook: 示例2\n\n本示例展示了2幅图像在拼接缝的融合(苹果和橘子图像的融合)，同样，MultiBandBlender类一样灵活支持此类型的输入。\n\n\u003cdetails\u003e\n      \n\u003csummary\u003e 融合示例代码展开\u003c/summary\u003e\n\n```matlab\nimg1_warped = imread(\"data/apple.png\"); % apple1.png,dog.jpg\nimg2_warped = imread(\"data/orange.png\");% orange1.png,cat.jpg\n[height,width,c] = size(img1_warped);\nmask1_warped = zeros(height,width,\"logical\");\nmask1_warped(:,1:round(width/2))=1;\nmask2_warped = 1-mask1_warped;\n\nblender = MultiBandBlender(5);  % Create a blender with 5 bands \nblender = blender.prepare([1, 1,width,height]);  % Prepare for [1, 1,width,height] ROI image area\nblender = blender.feed(img1_warped, mask1_warped, [1, 1]);  % Feed the first image and mask at position [1,1]\nblender = blender.feed(img2_warped, mask2_warped, [1, 1]);  % Feed the second image and mask at position [1,1]\n[dst, ~] = blender.blend();  % Perform the blending and get the result\nfigure;\nimshow(dst)\n```\n\n![figure_6.png](ExamplesEntry_media/figure_6.png)\n\n\u003c/details\u003e\n\n为增强对比，对不同基本数目的num\\_bands看看。\n\n```matlab\nfor i = 1:5\n    blender = MultiBandBlender(i);  % Create a blender with 5 bands\n    blender = blender.prepare([1, 1,width,height]);  % Prepare for [1, 1,width,height] ROI image area\n    blender = blender.feed(img1_warped, mask1_warped, [1, 1]);  % Feed the first image and mask at position [1,1]\n    blender = blender.feed(img2_warped, mask2_warped, [1, 1]);  % Feed the second image and mask at position [1,1]\n    [dst, ~] = blender.blend();  % Perform the blending and get the result\n    figure;\n    imshow(dst)\n    title(\"blended image(numbands=\"+string(i)+\")\")\nend\n```\n\n![figure_7.png](ExamplesEntry_media/figure_7.png)\n\n![figure_8.png](ExamplesEntry_media/figure_8.png)\n\n![figure_9.png](ExamplesEntry_media/figure_9.png)\n\n![figure_10.png](ExamplesEntry_media/figure_10.png)\n\n![figure_11.png](ExamplesEntry_media/figure_11.png)\n\n## :books: References\n\n[1]  [https://docs.opencv.org/4.9.0/d5/d4b/classcv\\_1\\_1detail\\_1\\_1MultiBandBlender.html](https://docs.opencv.org/4.9.0/d5/d4b/classcv_1_1detail_1_1MultiBandBlender.html)\n\n[2] [Python with MATLAB](https://ww2.mathworks.cn/help/matlab/python-language.html)\n\n[3]  [Laplace blending](https://www.uio.no/studier/emner/matnat/its/nedlagte-emner/UNIK4690/v17/forelesninger/lecture_2_3_blending.pdf)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuixing158%2Fmultibandblender","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcuixing158%2Fmultibandblender","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcuixing158%2Fmultibandblender/lists"}