admin 管理员组文章数量: 887006
多张截图拼接成长图
背景:工作中我们经常需要将一张张的截图拼接成一整张图。但是因为图片顶部和底部tabBar的存在,我们没有办法直接拼接。下面我们利用opencv的方法实现图片的完美拼接。
素材图片:
基本算法:
1、需要拼接的图片需要有1/3重合的部分,否则无法拼接。所以在截图的时候需要尽量保证图片重合部分超过1/3,否则会拼接失败。 2、重点是需要找到从哪里开始拼接。人眼很容易找到拼接的地方,但是机器需要一个明确的坐标才能进行拼接,所以需要下面的算法来实现拼接。 3、从第一张图片的2/3处截取1/6的图片作为模版,这里最后留下1/6是因为部分截图有底部tabBar,需要排除。 4、用截取到的模版,在第二张图片中查找是否有这块,如果没有则两个图片无法拼接。找到之后返回坐标。 5、根据第四步返回的坐标,截取图片,然后两个图片拼接即可。
相关依赖:
<dependency><groupId>org.bytedeco</groupId><artifactId>javacv</artifactId><version>1.5.7</version></dependency><dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.7</version></dependency>
这里是老的依赖版本,但是我这边都进行了验证是可以正常运行的。如果你需要升级新的版本,需要自己验证依赖是否冲突。
实现代码:
package com.test.image;import org.apachemons.collections.CollectionUtils;
import org.bytedeco.javacpp.DoublePointer;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Point;
import org.bytedeco.opencv.opencv_core.Rect;import java.util.ArrayList;
import java.util.List;import static org.bytedeco.opencv.global.opencv_core.*;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imread;
import static org.bytedeco.opencv.global.opencv_imgcodecs.imwrite;
import static org.bytedeco.opencv.global.opencv_imgproc.*;public class ImageMergeService {/*** 基础算法:* 1、需要拼接的图片需要有1/3重合的部分,否则无法拼接。* 2、重点是需要找到从哪里开始拼接。* 3、从第一张图片的2/3处截取1/6的图片作为模版,这里最后留下1/6是因为部分截图有底部tabBar,需要排除。* 4、用截取到的模版,在第二张图片中查找是否有这块,如果没有则两个图片无法拼接。找到之后返回坐标。* 5、根据第四步返回的坐标,截取图片,然后两个图片拼接即可。** @param picMats*/public static Mat mergePic(List<Mat> picMats ){if(CollectionUtils.isEmpty(picMats)){return null;}Mat resultMat = picMats.get(0);for( int i=1; i< picMats.size(); i++ ){resultMat = mergePic(resultMat,picMats.get(i));}return resultMat;}public static Mat mergePic( Mat baseMat, Mat targetMat ){if(baseMat.size().height()<targetMat.size().height()){return null;}if(baseMat.size().width()!=targetMat.size().width()){return null;}int height = targetMat.size().height();int startHeight = (int)(height*0.7);int templateHeight = height/6;Mat template = new Mat(baseMat, new Rect(0, baseMat.size().height()+startHeight-targetMat.size().height(), baseMat.size().width(), templateHeight));imwrite( "template.png",template);Mat sameMat = targetMat.clone();matchTemplate(targetMat,template,sameMat,TM_CCOEFF_NORMED );DoublePointer minVal = new DoublePointer();DoublePointer maxVal = new DoublePointer();Point minLoc = new Point();Point maxLoc = new Point();minMaxLoc(sameMat,minVal,maxVal,minLoc,maxLoc,null);System.out.println(sameMat.ptr(maxLoc.x(),maxLoc.y()));System.out.println(maxVal);System.out.println(maxLoc.y());if(maxLoc.y()>targetMat.size().height()-templateHeight){System.out.println("没有找到重合的部分!");return baseMat;}Mat findTemplate = new Mat(targetMat, new Rect(0,maxLoc.y(), targetMat.size().width(), templateHeight));double diff = compareImage(template,findTemplate);System.out.println(diff);if(diff<0.999){System.out.println("没有找到重合的部分!");return baseMat;}Mat topMat = new Mat(baseMat,new Rect(0, 0, baseMat.size().width(),baseMat.size().height()+startHeight-targetMat.size().height() ));Mat tailMat = new Mat(targetMat, new Rect(0, maxLoc.y(), targetMat.size().width(), targetMat.size().height()-maxLoc.y()));Mat resultMat = baseMat.clone();vconcat(topMat, tailMat, resultMat);imwrite( "resultMat.png",resultMat);return resultMat;}public static double compareImage( Mat targetImage, Mat baseImage ){Mat targetImageClone = targetImage.clone();Mat baseImageColne = baseImage.clone();Mat imgDiff1 = targetImage.clone();Mat imgDiff = targetImage.clone();/*** 首先将图片转成灰度图,*/cvtColor(targetImage, targetImageClone, COLOR_BGR2GRAY);cvtColor(baseImage, baseImageColne, COLOR_BGR2GRAY);/*** 两个矩阵相减,获得差异图。*/subtract(targetImageClone, baseImageColne, imgDiff1);subtract(baseImageColne, targetImageClone, imgDiff);/*** 按比重进行叠加。*/addWeighted(imgDiff, 1, imgDiff1, 1, 0, imgDiff);/*** 图片二值化,大于24的为1,小于24的为0*/threshold(imgDiff, imgDiff, 24, 255, THRESH_BINARY);erode(imgDiff, imgDiff, new Mat());dilate(imgDiff, imgDiff, new Mat());return 1-((double) countNonZero(imgDiff) / (imgDiff.size().height() * imgDiff.size().width()));}public static void main( String[] args ){String pic1="picture0.jpg";String pic2="picture1.jpg";String pic3="picture2.jpg";List<Mat> picMatList = new ArrayList<Mat>();picMatList.add(imread(pic1));picMatList.add(imread(pic2));picMatList.add(imread(pic3));mergePic(picMatList);}
}
拼接结果:
对比上面的素材图片,这里实现了无缝拼接。
本文标签: 多张截图拼接成长图
版权声明:本文标题:多张截图拼接成长图 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1732351015h1533055.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论