参考了https://github.com/starhiking/opencv-programme/blob/master/recorrection.cpp
https://www.cnblogs.com/skyfsm/p/6902524.html这两篇文章,详细内容大家去这两个博客看吧,我这边就是记录一下怎么实现的方便以后自己复习。
我们的目的就是将斜着的图案改变角度。
看到这个图片先分析要使用的方法,因为背景是纯黑色与目标图片色差大,轮廓清晰,所以考虑寻找目标图片的轮廓,使用findContours函数,得到目标图片进行角度旋转。
步骤:
1.图像灰度化
2.二值化
3.检测轮廓
4.寻找最大轮廓,计算轮廓大小,角度
5.根据角度选择矫正。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src, gray, bisrc;
src = imread("fapiao.jpg", 1);
if (src.data == 0)
{
printf("没有读入图片");
return 0;
}
cvtColor(src, gray, COLOR_RGB2GRAY);
threshold(gray, bisrc, 0, 255, THRESH_BINARY);
vector<vector<Point>>contours;
findContours(bisrc, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
float area = boundingRect(contours[0]).area();
Rect maxrectb;
int index = 0;
for (int i = 0; i < contours.size(); i++)
{
if (boundingRect(contours[i]).area()>area)
{
//maxrectb = boundingRect(contours[i]);
index = i;
}
}
// rectangle(src, maxrectb.tl(), maxrectb.br(), Scalar::all(255), 2, 8, 0); //测试boundingRect 话框
RotatedRect rect = minAreaRect(contours[index]);
Point2f rectPoint[4];
rect.points(rectPoint);//获取四个顶点坐标
for (int i = 0; i < 4;i++)
{
line(src, rectPoint[i], rectPoint[(i + 1) % 4], Scalar(0, 255, 0), 2, 8, 0);
}
double angle = rect.angle;
// angle += 90;
Point2f center = rect.center;
Mat RoiSrcImg = Mat::zeros(src.size(), src.type());
Mat dst(src.rows,src.cols,CV_8UC1);
drawContours(dst, contours, -1, Scalar(255),-1);
imshow ("dst", dst);
// srcImage.copyTo(RoiSrcImg,binaryImage);
src.copyTo(RoiSrcImg);
Mat Matrix = getRotationMatrix2D(center, angle, 1);//得到旋转矩阵算子
warpAffine(RoiSrcImg, RoiSrcImg, Matrix, RoiSrcImg.size(), 1, 0, Scalar(0, 0, 0));
imshow("src Image", src);
imshow("recorrected", RoiSrcImg);
waitKey(0);
return 0;
}
在程序中发现了两种获取图形的函数 boundingRect和minAreaRect,他俩不同在于前者获取的图形边是有整幅图像水平的,后者获取的图形是可以有旋转角度的。如下图
1 Rect boundingRect(InputArrayt points)
points:输入信息,可以为包含点的容器(vector)或者Mat
2 RotatedRect minAreaRect(InputArray points)
points:输入信息,可以为包含点的容器(vector)或者Mat