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文件:
#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文件:
#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::findPea