公众号推送看到的
由于深度学习平时训练的是pytorch框架的东西 传统opencv处理图像用的非常少
温故而知新
示例入下图
把这本书矫正
做法是
先缩小图二分之一,高斯模糊+边缘检测+膨胀 去噪(图像噪点基本没有 所有参数看不出好坏),找轮廓,找出面积最大的那个矩形轮廓,确定四个点的映射顺序,透视变换
结果
完整代码
//
// Created by smallflyfly on 2022/10/12.
//
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
const static double AREA_FILTER = 1000.0;
void showIm(const Mat& im) {
imshow("im", im);
waitKey(0);
destroyAllWindows();
}
void drawPoints(const Mat& im, vector<Point> points) {
int index = 1;
for (Point& point : points) {
circle(im, point, 5, Scalar(0, 255, 255), FILLED);
putText(im, to_string(index++), point, FONT_HERSHEY_COMPLEX, 4, Scalar(255, 0, 255), 4);
}
showIm(im);
}
void preProcess(Mat& im) {
cvtColor(im, im, CV_BGR2GRAY);
GaussianBlur(im, im, Size(3, 3), 3, 0);
Canny(im, im, 25, 75);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
dilate(im, im, kernel);
// showIm(im);
}
vector<Point> getContours(const Mat &im) {
vector<vector<Point>> contours;
findContours(im, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
vector<Vec4i> hierarchy;
findContours(im, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE);
// vector<vector<Point>> conPoly(contours.size());
vector<Rect> boundRect(contours.size());
vector<Point> biggest;
double maxArea = 0.0;
for (auto &contour : contours) {
vector<Point> conPoly;
double area = contourArea(contour);
if (area > AREA_FILTER) {
double peri = arcLength(contour, true);
approxPolyDP(contour, conPoly, 0.02*peri, true);
if (area > maxArea && conPoly.size() == 4) {
maxArea = area;
biggest = {conPoly[0]*2, conPoly[1]*2, conPoly[2]*2, conPoly[3]*2};
}
}
}
return biggest;
}
Mat getWarp(const Mat& imOrigin, vector<Point> points) {
Mat warpIm;
Point2f src[4] = {points[0], points[1], points[2], points[3]};
Point2f dst[4] = {{0.0, 0.0}, {0.0, 320.0}, {320.0, 320.0}, {320.f, 0.0}};
Mat mat = getPerspectiveTransform(src, dst);
warpPerspective(imOrigin, warpIm, mat, Point(320, 320));
return warpIm;
}
int main() {
Mat imgOrigin = imread("warp-image.jpg");
showIm(imgOrigin);
Mat resizeIm;
resize(imgOrigin, resizeIm, Size(), 0.5, 0.5);
preProcess(resizeIm);
vector<Point> recPoints = getContours(resizeIm);
drawPoints(imgOrigin, recPoints);
// reOrderPoints(recPoints);
Mat imWrap = getWarp(imgOrigin, recPoints);
showIm(imWrap);
return 0;
}
原文做了点的重排列
我是根据显示图像点顺序确定四个点的顺序
原文链接