OpenCV透视变换示例

公众号推送看到的

由于深度学习平时训练的是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;
}

 原文做了点的重排列

我是根据显示图像点顺序确定四个点的顺序

原文链接

在 C++ 中使用 OpenCV 对图像中的对象进行扭曲透视

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值