本章内容:


        卡片检测
        1. 读入图片
        2. canny  边缘检测
        3. 寻找最外层轮廓
        4. 通过最大弧长获取卡片轮廓
        5. 计算卡片的最小外接矩形
        6. 计算软转矩阵,并进行仿射变换校正

        7. 计算单应性矩阵,并进行单应性变换校正

 

1. canny 边缘检测

opencv 简单背景下打印文档旋转校正

 

输出结果:

opencv 简单背景下打印文档旋转校正

2. 轮廓提取

opencv 简单背景下打印文档旋转校正

输出结果:

opencv 简单背景下打印文档旋转校正

3.  最小外接矩形提取分割轮廓

opencv 简单背景下打印文档旋转校正

输出结果:

opencv 简单背景下打印文档旋转校正

4. 旋转校正

opencv 简单背景下打印文档旋转校正

输出结果:

opencv 简单背景下打印文档旋转校正

5.单应性变换校正

opencv 简单背景下打印文档旋转校正

输出结果

opencv 简单背景下打印文档旋转校正

代码

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

int main(int argc, char* argv[]){
    /* 本章内容:
        卡片检测
        1. 读入图片
        2. canny检测
        3. 寻找最外层轮廓
        4. 通过最大弧长获取卡片轮廓
        5. 计算卡片的最小外接矩形
        6. 计算软转矩阵,并进行仿射变换校正
        7. 计算单应性矩阵,并进行单应性变换校正
    */
    cv::String fileName = "/home/wang/dev/Image/card1.jpg";
    cv::Mat src = cv::imread(fileName,cv::IMREAD_REDUCED_COLOR_8);
    if(src.empty()){
        std::cout << "读入图像文件失败\n" << std::endl;
        return -1;
    }
    cv::imshow("src", src);
    // 灰度化,边缘检测
    cv::Mat gray;
    cv::cvtColor(src,gray,cv::COLOR_BGR2GRAY);
    cv::Mat dstCanny;
    cv::Canny(gray,dstCanny,50,100);
    cv::imshow("Canny edges", dstCanny);

    // 轮廓查找
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hireachy;
    cv::findContours(dstCanny, contours,hireachy,cv::RETR_EXTERNAL,cv::CHAIN_APPROX_SIMPLE);

    // 计算轮廓最大弧长以及id
    double arcLen=0;
    int arcIdx =0;
    double degree;
    for(int i=0; i < contours.size();i++){
        double temArc= cv::arcLength(contours[i],false);
        if(temArc > arcLen){
            arcLen =temArc;
            arcIdx = i;
        }
    }
    std::cout << "srcLen = " << arcLen << " arcIdx = " << arcIdx << std::endl;
    cv::drawContours(src,contours,arcIdx,cv::Scalar(0,255,0),2);
    cv::imshow("外层轮廓", src);

    // 最小外接矩形分割轮廓
    cv::RotatedRect rect =  cv::minAreaRect(contours[arcIdx]);
    degree = rect.angle;
    cv::Point2f pts[4];
    rect.points(pts);
    for(int i=0; i<4;i++) cv::line(src,pts[i],pts[(i+1)%4],cv::Scalar(0,0,255),2);
    cv::imshow("最小外接矩形", src);

    // 仿射变换
    // CV_EXPORTS_W Mat getRotationMatrix2D(Point2f center, double angle, double scale);
    cv::Point2f center(src.rows/2,src.cols/2);
    cv::Mat romH = cv::getRotationMatrix2D(center,degree + 90,1);
    /*CV_EXPORTS_W void warpAffine( InputArray src, OutputArray dst,
                                  InputArray M, Size dsize,
                                  int flags = INTER_LINEAR,
                                  int borderMode = BORDER_CONSTANT,
                                  const Scalar& borderValue = Scalar());
    */
    cv::Mat dstAff;
    cv::warpAffine(src,dstAff,romH,src.size());
    cv::imshow("dstAff",dstAff);

    // 单应性矩阵校正


    // 计算单应性矩阵
    float wMax=rect.size.width;
    float hMax=rect.size.height;
    std::vector<cv::Point2f> pt1s;
    pt1s.push_back(pts[0]);
    pt1s.push_back(pts[1]);
    pt1s.push_back(pts[2]);
    pt1s.push_back(pts[3]);
    std::vector<cv::Point2f> pt2s;
    pt2s.push_back(cv::Point2f(0,0));
    pt2s.push_back(cv::Point2f(wMax,0));
    pt2s.push_back(cv::Point2f(wMax,hMax));
    pt2s.push_back(cv::Point2f(0,hMax));

    cv::Mat Hom = cv::findHomography(pt1s,pt2s,cv::RANSAC);
    cv::Mat dstHom;
    cv::warpPerspective(src,dstHom,Hom,cv::Size(wMax,hMax));
    cv::imshow("单应性变换",dstHom);

    cv::waitKey(0);
    return 0;
}

 

 

 

 

 

 

 

相关文章:

  • 2021-08-21
  • 2021-05-03
  • 2022-12-23
  • 2021-10-31
  • 2022-02-10
  • 2021-12-29
  • 2022-01-11
猜你喜欢
  • 2021-11-03
  • 2021-09-11
  • 2022-12-23
  • 2021-08-29
  • 2021-12-21
  • 2021-09-29
  • 2022-01-08
相关资源
相似解决方案