Ex4:Image Warping and Image Morphing

计算机视觉作业四

完整代码见github地址:https://github.com/linjiafengyang/ComputerVision

作业4

测试数据

普通A4打印纸,上面可能有手写笔记或者打印内容,但是拍照时可能角度不正。(参考Dataset2)。
输出:
已经矫正好的标准普通A4纸(长宽比为A4纸的比例),并裁掉无用的其他内容,只保留完整A4纸张。
实验数据集依旧使用作业3的数据集。

说明:尽量保留A4纸上的原有信息不变或减少图像信息(原图像内容不要做缩放,A4纸的面积基本不变),以利于后期的文字识别和处理。

测试结果

以下面两张图为例:
这里写图片描述

这里写图片描述

代码文件

在作业3的基础上,先求A4纸的四个顶点,再进行Warping为标准普通A4纸,最后裁剪。

ImageWarping.h文件:

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
#include "CImg.h"
#include <iostream>
#include <vector>
using namespace cimg_library;
using namespace std;

struct Point {
double x, y;
int cnt;
Point(double _x, double _y, int _cnt): x(_x), y(_y), cnt(_cnt) {}
};
struct Line {
double k, b;
Line(double _k, double _b): k(_k), b(_b) {}
int index;
double distance;
Line(int _index, double _distance): index(_index), distance(_distance) {}
};
class Hough {
private:
CImg<float> grayImage; // 灰度图
CImg<float> blurred_img; // 高斯滤波平滑得到的图
CImg<float> houghspace; // 霍夫空间图
CImg<float> hough_result; // 霍夫检测图
CImg<float> A4; // a4纸结果图
vector<Point> peaks; // 霍夫空间直线经过最多的点
vector<Line> lines; // 直线
vector<Point> intersections; // 直线交点

double sigma;
double gradient_threshold;
double vote_threshold;
double peak_dis;
int x_min, x_max, y_min, y_max;
public:
Hough(CImg<float> srcImg, double sigma, double gradient_threshold, double vote_threshold, double peak_dis);
CImg<float> imageWarping(CImg<float> srcImg);
CImg<float> RGBtoGray(const CImg<float>& srcImg); // 转灰度图
CImg<float> initHoughSpace(); // 初始化霍夫空间
void findPeaks(); // 投票算法
void drawLines(); // 寻找并画出直线
void drawIntersections(); // 寻找并画出直线交点
vector<CImg<float> > computeTransformMatrix(CImg<float> a4); // 计算变换矩阵
CImg<float> warping(CImg<float> srcImg); // image warping
};

ImageWarping.cpp文件:

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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include "ImageWarping.h"

Hough::Hough(CImg<float> srcImg, double sigma, double gradient_threshold, double vot_threshold, double peak_dis) {
this->hough_result = srcImg;
this->sigma = sigma;
this->gradient_threshold = gradient_threshold;
this->vote_threshold = vot_threshold;
this->peak_dis = peak_dis;
this->x_min = 0;
this->x_max = srcImg._width - 1; // 图像宽度
this->y_min = 0;
this->y_max = srcImg._height - 1; // 图像高度
}
CImg<float> Hough::imageWarping(CImg<float> srcImg) {
this->grayImage = RGBtoGray(srcImg); // 转灰度图
this->blurred_img = grayImage.get_blur(sigma); // 高斯滤波平滑
this->houghspace = initHoughSpace(); // 初始化霍夫空间
findPeaks(); // 找出霍夫空间中直线经过最多的点
drawLines(); // 寻找并画出直线
drawIntersections(); // 寻找并画出直线交点
//hough_result.display();
this->A4 = warping(srcImg); // image warping
return A4;
}
// 转灰度图
CImg<float> Hough::RGBtoGray(const CImg<float>& srcImg) {
CImg<float> grayImage = CImg<float>(srcImg._width, srcImg._height, 1, 1, 0);
cimg_forXY(grayImage, x, y) {
grayImage(x, y, 0) = (int)round((double)srcImg(x, y, 0, 0) * 0.299 +
(double)srcImg(x, y, 0, 1) * 0.587 +
(double)srcImg(x, y, 0, 2) * 0.114);
}
return grayImage;
}
// 初始化霍夫空间
CImg<float> Hough::initHoughSpace() {
CImgList<float> gradient = blurred_img.get_gradient("xy", 2);

CImg<float> gradient_x = gradient[0]; // x方向上的梯度
CImg<float> gradient_y = gradient[1]; // y方向上的梯度

int maxp = (int)sqrt(grayImage._width*grayImage._width + grayImage._height*grayImage._height);
CImg<float> hough_space(360, maxp, 1, 1, 0); // 初始化hough space

cimg_forXY(grayImage, i, j) {
double grad = sqrt(gradient_x(i, j)*gradient_x(i, j) + gradient_y(i, j)*gradient_y(i, j));
if (grad > gradient_threshold) {
grayImage(i, j) = grad;
cimg_forX(hough_space, alpha) {
double theta = ((double)alpha*cimg::PI) / 180;
int p = (int)(i*cos(theta) + j*sin(theta));
if (p >= 0 && p < maxp) {
hough_space(alpha, p)++; // 累加矩阵
}
}
}
}
return hough_space;
}
// 投票算法找出霍夫空间中直线经过最多的点
void Hough::findPeaks() {
peaks.clear();
cimg_forXY(houghspace, theta, p) {
if (houghspace(theta, p) > vote_threshold) {
bool flag = true;
double alpha = (double)theta*cimg::PI / 180;
// y的范围
const int y0 = ((double)p / (sin(alpha))) - double(x_min)*(1 / tan(alpha));
const int y1 = ((double)p / (sin(alpha))) - double(x_max)*(1 / tan(alpha));
// x的范围
const int x0 = ((double)p / (cos(alpha))) - double(y_min)*(tan(alpha));
const int x1 = ((double)p / (cos(alpha))) - double(y_max)*(tan(alpha));

if (x0 >= x_min && x0 <= x_max || x1 >= x_min && x1 <= x_max ||
y0 >= y_min && y0 <= y_max || y1 >= y_min && y1 <= y_max) {
for (int i = 0; i < peaks.size(); i++) {
if (sqrt((peaks[i].x - theta)*(peaks[i].x - theta)
+ (peaks[i].y - p)*(peaks[i].y - p)) < peak_dis) {
flag = false;
if (peaks[i].cnt < houghspace(theta, p)) {
Point temp(theta, p, houghspace(theta, p));
peaks[i] = temp;
}
}
}
if (flag) {
Point temp(theta, p, houghspace(theta, p));
peaks.push_back(temp);
}
}
}
}
}
// 寻找并画出直线
void Hough::drawLines() {
lines.clear();
for (int i = 0; i < peaks.size(); i++) {
double theta = double(peaks[i].x)*cimg::PI / 180;
double k = -cos(theta) / sin(theta); // 直线斜率
double b = double(peaks[i].y) / sin(theta);
Line templine(k, b);
lines.push_back(templine);
cout << "Line " << i << ": y = " << k << "x + " << b << endl;
}

const double lines_color[] = { 255, 0, 0 };
for (int i = 0; i < lines.size(); i++) {
const int x0 = (double)(y_min - lines[i].b) / lines[i].k;
const int x1 = (double)(y_max - lines[i].b) / lines[i].k;
const int y0 = x_min*lines[i].k + lines[i].b;
const int y1 = x_max*lines[i].k + lines[i].b;

if (abs(lines[i].k) > 1) {
hough_result.draw_line(x0, y_min, x1, y_max, lines_color);
}
else {
hough_result.draw_line(x_min, y0, x_max, y1, lines_color);
}
}

}
bool sortByDistance(Line a, Line b) {
return a.distance < b.distance;
}
// 寻找并画出直线交点
void Hough::drawIntersections() {
vector<Point> tempIntersections;
int k = 0;
for (int i = 0; i < lines.size(); i++) {
for (int j = i + 1; j < lines.size(); j++) {
double k0 = lines[i].k, k1 = lines[j].k;
double b0 = lines[i].b, b1 = lines[j].b;

double x = (b1 - b0) / (k0 - k1);
double y = (k0*b1 - k1*b0) / (k0 - k1);

if (x >= 0 && x < grayImage._width && y >= 0 && y < grayImage._height) {
Point tempPoint(x, y, 0);
tempIntersections.push_back(tempPoint);
cout << "Intersection " << k++ << ": x = " << x << ", y = " << y << endl;
}
}
}

const double intersections_color[] = { 255, 0, 0 };
vector<Line> sort_line;
for (int i = 0; i < tempIntersections.size(); i++) {
hough_result.draw_circle(tempIntersections[i].x, tempIntersections[i].y, 50, intersections_color);

double temp_x = tempIntersections[i].x - tempIntersections[0].x;
double temp_y = tempIntersections[i].y - tempIntersections[0].y;
double dis = sqrt(temp_x*temp_x + temp_y*temp_y);
Line temp(i, dis);
sort_line.push_back(temp);
}
sort(sort_line.begin(), sort_line.end(), sortByDistance);
intersections.clear();
for (int i = 0; i < sort_line.size(); i++) {
intersections.push_back(tempIntersections[sort_line[i].index]); // 四个角点
}
}
// 计算变换矩阵
vector<CImg<float> > Hough::computeTransformMatrix(CImg<float> a4) {
vector<Point> destRectPoints;
Point tempPoint1(0, 0, 0);
Point tempPoint2(a4._width - 1, 0, 0);
Point tempPoint3(0, a4._height - 1, 0);
Point tempPoint4(a4._width - 1, a4._height - 1, 0);
destRectPoints.push_back(tempPoint1); destRectPoints.push_back(tempPoint2);
destRectPoints.push_back(tempPoint3); destRectPoints.push_back(tempPoint4);

CImg<float> y1(1, 3, 1, 1, 0), y2(1, 3, 1, 1, 0), y3(1, 3, 1, 1, 0), y4(1, 3, 1, 1, 0);
CImg<float> c1(1, 3, 1, 1, 0), c2(1, 3, 1, 1, 0), c3(1, 3, 1, 1, 0), c4(1, 3, 1, 1, 0);
CImg<float> A1(3, 3, 1, 1, 1), A2(3, 3, 1, 1, 1);

for (int i = 0; i < 3; i++) {
A1(0, i) = destRectPoints[i].x; A1(1, i) = destRectPoints[i].y;
A2(0, i) = destRectPoints[3-i].x; A2(1, i) = destRectPoints[3-i].y;

y1(0, i) = intersections[i].x; y2(0, i) = intersections[i].y;
y3(0, i) = intersections[3-i].x; y4(0, i) = intersections[3-i].y;
}
c1 = y1.solve(A1); c2 = y2.solve(A1);
c3 = y3.solve(A2); c4 = y4.solve(A2);

CImg<float> temptransform1(3, 3, 1, 1, 0), temptransform2(3, 3, 1, 1, 0);
for (int i = 0; i < 3; i++) {
temptransform1(i, 0) = c1(0, i);
temptransform1(i, 1) = c2(0, i);

temptransform2(i, 0) = c3(0, i);
temptransform2(i, 1) = c4(0, i);
}
temptransform1(0, 2) = 0; temptransform1(1, 2) = 0; temptransform1(2, 2) = 1;
temptransform2(0, 2) = 0; temptransform2(1, 2) = 0; temptransform2(2, 2) = 1;
vector<CImg<float> > temptransform;
temptransform.push_back(temptransform1);
temptransform.push_back(temptransform2);
return temptransform;
}
// image warping
CImg<float> Hough::warping(CImg<float> srcImg) {
// 当分辨率是150像素/英寸时,A4纸像素长宽分别是1754×1240
// 当分辨率是300像素/英寸时,A4纸像素长宽分别是3508×2479
CImg<float> a4(1240, 1754, 1, 3, 0);
//CImg<float> a4(2479, 3508, 1, 3, 0);
vector<CImg<float> > transform;
transform = computeTransformMatrix(a4); // 计算变换矩阵

CImg<float> y(1, 2, 1, 1, 0);
CImg<float> c(1, 2, 1, 1, 0);
CImg<float> A(2, 2, 1, 1, 1);
A(0, 0) = 0;
A(0, 1) = a4._width - 1;
y(0, 0) = a4._height - 1;
y(0, 1) = 0;
c = y.solve(A);

CImg<float> temp1(1, 3, 1, 1, 1), temp2(1, 3, 1, 1, 1);
cimg_forXY(a4, i, j) {
temp1(0, 0) = i;
temp1(0, 1) = j;

double inner_procuct = i * c(0, 0) - j + c(0, 1);
temp2 = inner_procuct >= 0 ? transform[0] * temp1 : transform[1] * temp1;
temp2(0, 0) = temp2(0, 0) < 0 ? 0 : (temp2(0, 0) > x_max ? x_max : temp2(0, 0));
temp2(0, 1) = temp2(0, 1) < 0 ? 0 : (temp2(0, 1) > y_max ? y_max : temp2(0, 1));

a4(i, j, 0) = srcImg(temp2(0, 0), temp2(0, 1), 0);
a4(i, j, 1) = srcImg(temp2(0, 0), temp2(0, 1), 1);
a4(i, j, 2) = srcImg(temp2(0, 0), temp2(0, 1), 2);
}
return a4;
}

main.cpp文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
#include "ImageWarping.cpp"
#include <time.h>
#include <iostream>
int main() {
CImg<float> src("Dataset/6.bmp");
// 4.bmp需要将sigma设为5.5f
// args: src sigma gradient_threshold vote_threshold peak_dis
Hough hough(src, 10.5f, 30, 1000, 60);
CImg<float> result = hough.imageWarping(src);
result.display();
result.save("result/6.bmp");
return 0;
}

附加题

这里写图片描述

这里写图片描述

根据Image Morphing方法完成中间11帧的差值,得到一个Image Morphing的动画视频。

测试结果

见github地址:https://github.com/linjiafengyang/ComputerVision

代码文件

ImageMorphing.h文件:

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
#include <iostream>
#include "CImg.h"
#include <vector>
#include <string>

using namespace std;
using namespace cimg_library;

struct Point {
float x, y;
Point(float _x, float _y): x(_x), y(_y) {}
};
struct Triangle {
Point p1, p2, p3;
Triangle(Point _p1, Point _p2, Point _p3): p1(_p1), p2(_p2), p3(_p3) {}
};
class ImageMorphing {
private:
vector<Point> src_points;
vector<Point> dst_points;
vector<vector<Point> > mid_points;

vector<vector<int> > index;
vector<Triangle> src_triangle_list;
vector<Triangle> dst_triangle_list;
vector<vector<Triangle> > mid_triangle_list;

CImg<float> src;
CImg<float> dst;
CImgList<float> result;

int frame_cnt;
public:
ImageMorphing(CImg<float> src, CImg<float> dst, vector<Point> src_points, vector<Point> dst_points,
vector<vector<int> > index, int frame_cnt);
void setSrcTriangleList();
void setDstTriangleList();
void setMidTriangleList();
CImg<float> computeTransformMatrix(Triangle before, Triangle after); // 计算变换矩阵
bool isInTriangle(Point P, Triangle tri); // 重心法判断一个点是否在三角形内
CImgList<float> morphing();
};

ImageMorphing.cpp文件:

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
116
117
118
119
120
121
122
123
124
125
126
#include "ImageMorphing.h"

ImageMorphing::ImageMorphing(CImg<float> src, CImg<float> dst, vector<Point> src_points,
vector<Point> dst_points, vector<vector<int>> index, int frame_cnt) {
this->src = src;
this->dst = dst;
this->src_points = src_points;
this->dst_points = dst_points;
this->index = index;
this->frame_cnt = frame_cnt;
setSrcTriangleList();
setDstTriangleList();
setMidTriangleList();
}
// src图的三角形
void ImageMorphing::setSrcTriangleList() {
for (int i = 0; i < index.size(); i++) {
Triangle src_triangle(src_points[index[i][0]], src_points[index[i][1]], src_points[index[i][2]]);
src_triangle_list.push_back(src_triangle);
}
}
// dst图的三角形
void ImageMorphing::setDstTriangleList() {
for (int i = 0; i < index.size(); i++) {
Triangle dst_triangle(dst_points[index[i][0]], dst_points[index[i][1]], dst_points[index[i][2]]);
dst_triangle_list.push_back(dst_triangle);
}
}
// morphing过程中每一帧的三角形
void ImageMorphing::setMidTriangleList() {
for (int i = 0; i < frame_cnt; i++) {
vector<Point> temp_mid_points;
for (int j = 0; j < src_points.size(); j++) {
float mid_x = float(src_points[j].x) + float(i+1)/(frame_cnt+1) * (dst_points[j].x - src_points[j].x);
float mid_y = float(src_points[j].y) + float(i+1)/(frame_cnt+1) * (dst_points[j].y - src_points[j].y);
Point mid_point(mid_x, mid_y);
temp_mid_points.push_back(mid_point);
}
mid_points.push_back(temp_mid_points);
}

for (int i = 0; i < frame_cnt; i++) {
vector<Triangle> temp_mid_triangles;
for (int j = 0; j < index.size(); j++) {
Triangle mid_triangle(mid_points[i][index[j][0]], mid_points[i][index[j][1]], mid_points[i][index[j][2]]);
temp_mid_triangles.push_back(mid_triangle);
}
mid_triangle_list.push_back(temp_mid_triangles);
}
}
// 重心法判断一个点是否在三角形内
bool ImageMorphing::isInTriangle(Point P, Triangle tri) {
float x0 = tri.p3.x - tri.p1.x, y0 = tri.p3.y - tri.p1.y;
float x1 = tri.p2.x - tri.p1.x, y1 = tri.p2.y - tri.p1.y;
float x2 = P.x - tri.p1.x, y2 = P.y - tri.p1.y;

float temp_00 = x0 * x0 + y0 * y0;
float temp_01 = x0 * x1 + y0 * y1;
float temp_02 = x0 * x2 + y0 * y2;
float temp_11 = x1 * x1 + y1 * y1;
float temp_12 = x1 * x2 + y1 * y2;

float u = float(temp_11 * temp_02 - temp_01 * temp_12) / (float)(temp_00 * temp_11 - temp_01 * temp_01);
float v = float(temp_00 * temp_12 - temp_01 * temp_02) / (float)(temp_00 * temp_11 - temp_01 * temp_01);
if (u + v <= 1 && u >= 0 && v >= 0) return true;
return false;
}
// 计算变换矩阵
CImg<float> ImageMorphing::computeTransformMatrix(Triangle before, Triangle after) {
CImg<float> A(3, 3, 1, 1, 1);
CImg<float> y1(1, 3, 1, 1, 0), y2(1, 3, 1, 1, 0);
CImg<float> c1(1, 3, 1, 1, 0), c2(1, 3, 1, 1, 0);

A(0, 0) = before.p1.x; A(1, 0) = before.p1.y;
A(0, 1) = before.p2.x; A(1, 1) = before.p2.y;
A(0, 2) = before.p3.x; A(1, 2) = before.p3.y;

y1(0, 0) = after.p1.x; y2(0, 0) = after.p1.y;
y1(0, 1) = after.p2.x; y2(0, 1) = after.p2.y;
y1(0, 2) = after.p3.x; y2(0, 2) = after.p3.y;

c1 = y1.solve(A);
c2 = y2.solve(A);

CImg<float> transform(3, 3, 1, 1, 0);
for (int i = 0; i < 3; i++) {
transform(i, 0) = c1(0, i);
transform(i, 1) = c2(0, i);
}
transform(2, 2) = 1;
return transform;
}
// 对每一帧进行morphing
CImgList<float> ImageMorphing::morphing() {
int size = mid_triangle_list[0].size();

result.push_back(src); // 放入第一帧
for (int k = 0; k < frame_cnt; k++) {
CImg<float> middle(dst._width, dst._height, 1, 3, 1);
cimg_forXY(middle, i, j) {
CImg<float> x(1, 3, 1, 1, 1), y1(1, 3, 1, 1, 1), y2(1, 3, 1, 1, 1);
for (int m = 0; m < size; m++) {
Point p(i, j);
if (isInTriangle(p, mid_triangle_list[k][m])) {
x(0, 0) = i;
x(0, 1) = j;
// middle image到src image的变换
CImg<float> transform1 = computeTransformMatrix(mid_triangle_list[k][m], src_triangle_list[m]);
y1 = transform1 * x;
// middle image到dst image的变换
CImg<float> transform2 = computeTransformMatrix(mid_triangle_list[k][m], dst_triangle_list[m]);
y2 = transform2 * x;
// src和dst组合得到middle
float a = float(k+1)/(frame_cnt+1);
middle(i, j, 0) = (1 - a) * src(y1(0, 0), y1(0, 1), 0) + a * dst(y2(0, 0), y2(0, 1), 0);
middle(i, j, 1) = (1 - a) * src(y1(0, 0), y1(0, 1), 1) + a * dst(y2(0, 0), y2(0, 1), 1);
middle(i, j, 2) = (1 - a) * src(y1(0, 0), y1(0, 1), 2) + a * dst(y2(0, 0), y2(0, 1), 2);
break;
}
}
}
result.push_back(middle); // 放入中间morphing的每一帧
}
result.push_back(dst); // 放入最后一帧
return result;
}

main.cpp文件:

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
#include "ImageMorphing.cpp"
#include <fstream>
#include <sstream>
#include <string>
int main() {
CImg<float> src, dst;
src.load_bmp("dataset/1.bmp");
dst.load_bmp("dataset/2.bmp");

// read source points
vector<Point> src_points;
ifstream infile_src_points;
infile_src_points.open("points/src_points.txt");
if (infile_src_points.is_open()) {
string s;
int x, y;
while (getline(infile_src_points, s)) {
stringstream ss(s);
ss >> x >> y;
Point p(x, y);
src_points.push_back(p);
}
}
else {
cout << "Can't open the file src_points.txt" << endl;
return 0;
}

// read destination points
vector<Point> dst_points;
ifstream infile_dst_points;
infile_dst_points.open("points/dst_points.txt");
if (infile_dst_points.is_open()) {
string s;
int x, y;
while (getline(infile_dst_points, s)) {
stringstream ss(s);
ss >> x >> y;
Point p(x, y);
dst_points.push_back(p);
}
}
else {
cout << "Can't open the file dst_points.txt" << endl;
return 0;
}

// read the indexs of triangles points
vector<vector<int> > index;
ifstream infile_tri;
infile_tri.open("points/triangle.txt");
if (infile_tri.is_open()) {
string s;
int index1, index2, index3;
while (getline(infile_tri, s)) {
vector<int> tempindex;
stringstream ss(s);
ss >> index1 >> index2 >> index3;
tempindex.push_back(index1 - 1);
tempindex.push_back(index2 - 1);
tempindex.push_back(index3 - 1);
index.push_back(tempindex);
}
}
else {
cout << "Can't open the file triangle.txt" << endl;
return 0;
}

ImageMorphing imageMorphing(src, dst, src_points, dst_points, index, 11); // 11帧
CImgList<float> result = imageMorphing.morphing();
string dir_name;
for (int i = 0; i < result.size(); i++) {
dir_name = "result/";
string s = to_string(i+1);
s += ".bmp";
dir_name += s;
result[i].save_bmp(dir_name.c_str()); // Save every frame
}
return 0;
}
------本文结束感谢阅读------