如果要實現兩個圖片橫向拼接一起,若通過遍歷每個Mat的每個元素值,拷貝到新的Mat中,性能問題突出。
- colRange 方法是指定一個區域范圍作為選區,返回這個選區,它也是Mat類型。
package com.test.face;
import org.opencv.core.Mat;
import org.opencv.core.Range;
public class Test {
/**
* 橫向拼接兩個圖像的數據(Mat),該兩個圖像的類型必須是相同的類型,如:均為CvType.CV_8UC3類型
* @param m1 要合並的圖像1(左圖)
* @param m2 要合並的圖像2(右圖)
* @return 拼接好的Mat圖像數據集。其高度等於兩個圖像中高度較大者的高度;其寬度等於兩個圖像的寬度之和。類型與兩個輸入圖像相同。
* @throws Exception 當兩個圖像數據的類型不同時,拋出異常
*/
public Mat concat(Mat m1, Mat m2) throws Exception{
System.out.println("圖1 width="+m1.size().width);
System.out.println("圖1 height="+m1.size().height);
System.out.println("圖2 width="+m2.size().width);
System.out.println("圖2 height="+m2.size().height);
if(m1.type() != m2.type()){
throw new Exception("concat:兩個圖像數據的類型不同!");
}
long time = System.currentTimeMillis();
//寬度為兩圖的寬度之和
double w = m1.size().width + m2.size().width;
//高度取兩個矩陣中的較大者的高度
double h = m1.size().height > m2.size().height ? m1.size().height : m2.size().height;
//創建一個大矩陣對象
Mat des = Mat.zeros((int)h, (int)w, m1.type());
//在最終的大圖上標記一塊區域,用於存放復制圖1(左圖)的數據,大小為從第0列到m1.cols()列
Mat rectForM1 = des.colRange(new Range(0, m1.cols()));
//標記出位於rectForM1的垂直方向上中間位置的區域,高度為圖1的高度,此時該區域的大小已經和圖1的大小相同。(用於存放復制圖1(左圖)的數據)
int rowOffset1 = (int)(rectForM1.size().height-m1.rows())/2;
rectForM1 = rectForM1.rowRange(rowOffset1, rowOffset1 + m1.rows());
//在最終的大圖上標記一塊區域,用於存放復制圖2(右圖)的數據
Mat rectForM2 = des.colRange(new Range(m1.cols(), des.cols()));
//標記出位於rectForM2的垂直方向上中間位置的區域,高度為圖2的高度,此時該區域的大小已經和圖2的大小相同。(用於存放復制圖2(右圖)的數據)
int rowOffset2 = (int)(rectForM2.size().height-m2.rows())/2;
rectForM2 = rectForM2.rowRange(rowOffset2, rowOffset2 + m2.rows());
//將圖1拷貝到des的指定區域 rectForM1
m1.copyTo(rectForM1);
//將圖2拷貝到des的指定區域 rectForM2
m2.copyTo(rectForM2);
System.out.println("圖片合並耗時:"+(System.currentTimeMillis()-time)+"ms");
return des;
}
}
