技术点

图片拼接成全景大图, 只要是使用了 opencv 中的 stitcher 类进行识别及合成。 其流程如下:
在这里插入图片描述

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
bool bitmapToMatrix(JNIEnv *env, jobject obj_bitmap, cv::Mat &matrix) {
void *bitmapPixels; // Save picture pixel data
AndroidBitmapInfo bitmapInfo; // Save picture parameters

ASSERT_FALSE(AndroidBitmap_getInfo(env, obj_bitmap, &bitmapInfo) >=
0); // Get picture parameters
ASSERT_FALSE(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888
|| bitmapInfo.format ==
ANDROID_BITMAP_FORMAT_RGB_565); // Only ARGB? 8888 and RGB? 565 are supported
ASSERT_FALSE(AndroidBitmap_lockPixels(env, obj_bitmap, &bitmapPixels) >=
0); // Get picture pixels (lock memory block)
ASSERT_FALSE(bitmapPixels);

if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC4,
bitmapPixels); // Establish temporary mat
tmp.copyTo(
matrix); // Copy to target matrix
} else {
cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC2, bitmapPixels);
cv::cvtColor(tmp, matrix, cv::COLOR_BGR5652RGB);
}

//convert RGB to BGR
cv::cvtColor(matrix, matrix, cv::COLOR_RGB2BGR);
AndroidBitmap_unlockPixels(env, obj_bitmap); // Unlock
return true;
}


bool matrixToBitmap(JNIEnv *env, cv::Mat &matrix, jobject obj_bitmap) {
void *bitmapPixels; // Save picture pixel data
AndroidBitmapInfo bitmapInfo; // Save picture parameters

ASSERT_FALSE(AndroidBitmap_getInfo(env, obj_bitmap, &bitmapInfo) >=
0); // Get picture parameters
ASSERT_FALSE(bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888
|| bitmapInfo.format ==
ANDROID_BITMAP_FORMAT_RGB_565); // Only ARGB? 8888 and RGB? 565 are supported
ASSERT_FALSE(matrix.dims == 2
&& bitmapInfo.height == (uint32_t) matrix.rows
&& bitmapInfo.width ==
(uint32_t) matrix.cols); // It must be a 2-dimensional matrix with the same length and width
ASSERT_FALSE(matrix.type() == CV_8UC1 || matrix.type() == CV_8UC3 || matrix.type() == CV_8UC4);
ASSERT_FALSE(AndroidBitmap_lockPixels(env, obj_bitmap, &bitmapPixels) >=
0); // Get picture pixels (lock memory block)
ASSERT_FALSE(bitmapPixels);

if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC4, bitmapPixels);
switch (matrix.type()) {
case CV_8UC1:
cv::cvtColor(matrix, tmp, cv::COLOR_GRAY2RGBA);
break;
case CV_8UC3:
cv::cvtColor(matrix, tmp, cv::COLOR_RGB2RGBA);
break;
case CV_8UC4:
matrix.copyTo(tmp);
break;
default:
AndroidBitmap_unlockPixels(env, obj_bitmap);
return false;
}
} else {
cv::Mat tmp(bitmapInfo.height, bitmapInfo.width, CV_8UC2, bitmapPixels);
switch (matrix.type()) {
case CV_8UC1:
cv::cvtColor(matrix, tmp, cv::COLOR_GRAY2BGR565);
break;
case CV_8UC3:
cv::cvtColor(matrix, tmp, cv::COLOR_RGB2BGR565);
break;
case CV_8UC4:
cv::cvtColor(matrix, tmp, cv::COLOR_RGBA2BGR565);
break;
default:
AndroidBitmap_unlockPixels(env, obj_bitmap);
return false;
}
}
AndroidBitmap_unlockPixels(env, obj_bitmap); // Unlock
return true;
}

extern "C"
JNIEXPORT jint JNICALL
Java_cn_xiaoxige_opencvdemo2_MainActivity_tmpStitchBitMap(JNIEnv *env, jobject thiz,
jobjectArray bitmaps) {
try {
vector<Mat> mats;
int size = env->GetArrayLength(bitmaps);
mats.reserve(size);
for (int i = 0; i < size; ++i) {
Mat mat;
if (bitmapToMatrix(env, env->GetObjectArrayElement(bitmaps, i), mat)) {
mats.push_back(mat);
}
}
Ptr<Stitcher> stitcher = Stitcher::create();
if (stitcher == nullptr) return -1;

auto *matcher = new detail::BestOf2NearestMatcher(false, 0.5f);
stitcher->setFeaturesMatcher(matcher);
stitcher->setBundleAdjuster(new detail::BundleAdjusterRay());
stitcher->setSeamFinder(new detail::NoSeamFinder);
stitcher->setExposureCompensator(new detail::NoExposureCompensator());//曝光补偿
stitcher->setBlender(new detail::FeatherBlender());
Mat mat;
Stitcher::Status state = stitcher->stitch(mats, mat);
return state;
} catch (...) {
return -1;
}
}

核心代码也就两行

1
2
Ptr<Stitcher> stitcher = Stitcher::create();
Stitcher::Status state = stitcher->stitch(mats, mat);