深入探讨opencv图像矫正算法实战

时间:2022-08-25 22:39:57

摘要

在机器视觉中,对于图像的处理有时候因为放置的原因导致ROI区域倾斜,这个时候我们会想办法把它纠正为正确的角度视角来,方便下一步的布局分析与文字识别,这个时候通过透视变换就可以取得比较好的裁剪效果。

本次实战,对于图像的矫正使用了两种矫正思路:

  • 针对边缘比较明显的图像,使用基于轮廓提取的矫正算法。
  • 针对边缘不明显,但是排列整齐的文本图像,使用了基于霍夫直线探测的矫正算法。

基于轮廓提取的矫正算法

整体思路:

  • 图片灰度化,二值化
  • 检测轮廓,并筛选出目标轮廓(通过横纵比或面积去除干扰轮廓)
  • 获取目标轮廓的最小外接矩形
  • 获取最小外接矩形的四顶点,并定义矫正图像后的四顶点
  • 透视变换(四点变换)

opencv实现(分解步骤):

(一)图片灰度化,二值化(开运算,消除噪点)

  Mat src = imread("D:/opencv练习图片/图片矫正.png");
    imshow("原图片", src);
    // 二值图像
    Mat gray, binary;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    threshold(gray, binary, 0, 255, THRESH_BINARY_INV| THRESH_OTSU);
    imshow("二值化", binary);
    // 定义结构元素
    Mat se = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
    morphologyEx(binary, binary, MORPH_OPEN, se);
    imshow("开运算", binary);

深入探讨opencv图像矫正算法实战

深入探讨opencv图像矫正算法实战

注意:由于原图像背景是白色,因此二值化时候要用THRESH_BINARY_INV

(二)提取轮廓,筛选轮廓

// 寻找最大轮廓
    vector<vector<Point>> contours;
    findContours(binary, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    int index = -1;
    int max = 0;
    for (size_t i = 0; i < contours.size(); i++) 
    {
        double area = contourArea(contours[i]);
        if (area > max) 
        {
            max = area;
            index = i;
        }
    }

(三)求取最小外接矩形以及四顶点坐标,并定义变换后的四顶点坐标

// 寻找最小外接矩形
    RotatedRect rect = minAreaRect(contours[index]);    
    Point2f srcpoint[4];//存放变换前四顶点
    Point2f dstpoint[4];//存放变换后四顶点
    rect.points(srcpoint);//获取最小外接矩形四顶点坐标
    //显示顶点
    for (size_t i = 0; i < 4; i++)
    {
        circle(src, srcpoint[i], 5, Scalar(0, 0, 255),-1);//-1表示填充
    }
    imshow("顶点坐标", src);
    //获取外接矩形宽高
    float width = rect.size.width;
    float height = rect.size.height;
    //定义矫正后四顶点
    dstpoint[0]= Point2f(0, height);
    dstpoint[1] = Point2f(0, 0);
    dstpoint[2] = Point2f(width, 0);
    dstpoint[3] = Point2f(width, height);