opencv通过透视变换实现矫正图像详解-kb88凯时官网登录

来自:网络
时间:2023-02-21
阅读:
免费资源网 - https://freexyz.cn/
目录

1、概述

案例:使用opencv将一张折射的图片给矫正过来

实现步骤:

1.载入图像

2.图像灰度化

3.二值分割

4.形态学操作去除噪点

5.轮廓发现

6.使用霍夫直线检测,检测上下左右四条直线(有可能是多条,但是无所谓)

7.绘制出直线

8.寻找与定位上下左右是条直线

9.拟合四条直线方程

10.计算四条直线的交点,ps:这四个交点其实就是我们最终要寻找的,用于透视变换使用的

11.进行透视变换

12.输出透视变换的结果

说明:

解释一下为啥是上面那些步骤。

1.其实我们的最终目的是通过透视矩阵getperspectivetransform 透视变换warpperspective来完成图像的矫正

2.但是getperspectivetransform需要两个参数,输入矩阵参数和目标矩阵参数。

3.由于输入矩阵参数就是原图像是个角的顶点,由于我们没有所以要求出来

4.所以我们以上的所有步骤都是为11、12步打基础的

ps:核心就是利用透视矩阵做透视变换

重点:

1.直线方程y=kx c

2.如果两条直线有交点,则必有k1x1 c1=k2x2 c2

2、代码演示

//【1】载入图像
    mat src = imread(filepath);
    if(src.empty()){
        qdebug()<<"图片为空";
        return;
    }
    imshow("src",src);
 
    //【2】图像灰度化
    mat gray;
    cvtcolor(src,gray,color_bgr2gray);
    //【3】执行二值分割
    threshold(gray,gray,0,255,thresh_binary_inv|thresh_otsu);
    imshow("threshold",gray);
    //【4】执行形态学开操作去除图像中的造点
    mat kernel = getstructuringelement(morph_rect,size(5,5),point(-1,-1));
    morphologyex(gray,gray,morph_close,kernel,point(-1,-1),3);
    imshow("morphologyex",gray);
    //【5】轮廓发现
    bitwise_not(gray,gray);
    imshow("bitwise_not",gray);
 
    vector> contours;
    vector hier;
    rng rng(12345);
    findcontours(gray,contours,hier,retr_tree,chain_approx_simple);
    mat colorimage = mat::zeros(gray.size(),cv_8uc3);
    for(size_t i = 0;isrc.cols/2){
            drawcontours(colorimage,contours,i,scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255)),1);
        }
 
    }
    imshow("findcontours",colorimage);
 
    //【6】使用霍夫直线检测
    vector lines;
    cvtcolor(colorimage,colorimage,color_bgr2gray);
    kernel = getstructuringelement(morph_rect,size(3,3),point(-1,-1));
    dilate(colorimage,colorimage,kernel,point(-1,-1),1);
    imshow("colorimage_gray",colorimage);
    int accu = min(src.cols*0.5, src.rows*0.5);
    houghlinesp(colorimage,lines,1,cv_pi/180,accu,accu,0);
    //【7】绘制出直线
    mat linecolorimage = mat::zeros(gray.size(),cv_8uc3);
    qdebug()<<"line count:"< ln[3] && topline[3]>0) {
                topline = lines[i];
            } else {
                topline = lines[i];
            }
        }
        if (ln[3] > height / 2.0 && ln[1] > height / 2.0 && deltah < accu - 1) {
            bottomline = lines[i];
        }
        if (ln[0] < width / 2.0 && ln[2] < width/2.0) {
            leftline = lines[i];
        }
        if (ln[0] > width / 2.0 && ln[2] > width / 2.0) {
            rightline = lines[i];
        }
    }
 
    //直线方程y=kx c
    // 【9】拟合四条直线方程
    float k1, c1;
    k1 = float(topline[3] - topline[1]) / float(topline[2] - topline[0]);
    c1 = topline[1] - k1*topline[0];
    float k2, c2;
    k2 = float(bottomline[3] - bottomline[1]) / float(bottomline[2] - bottomline[0]);
    c2 = bottomline[1] - k2*bottomline[0];
    float k3, c3;
    k3 = float(leftline[3] - leftline[1]) / float(leftline[2] - leftline[0]);
    c3 = leftline[1] - k3*leftline[0];
    float k4, c4;
    k4 = float(rightline[3] - rightline[1]) / float(rightline[2] - rightline[0]);
    c4 = rightline[1] - k4*rightline[0];
 
    // 【10】四条直线交点,其实最终的目的就是找这是条直线的交点
    point p1; // 左上角
    p1.x = static_cast((c1 - c3) / (k3 - k1));
    p1.y = static_cast(k1*p1.x   c1);
    point p2; // 右上角
    p2.x = static_cast((c1 - c4) / (k4 - k1));
    p2.y = static_cast(k1*p2.x   c1);
    point p3; // 左下角
    p3.x = static_cast((c2 - c3) / (k3 - k2));
    p3.y = static_cast(k2*p3.x   c2);
    point p4; // 右下角
    p4.x = static_cast((c2 - c4) / (k4 - k2));
    p4.y = static_cast(k2*p4.x   c2);
 
    // 显示四个点坐标
    circle(linecolorimage, p1, 2, scalar(255, 0, 0), 2, 8, 0);
    circle(linecolorimage, p2, 2, scalar(255, 0, 0), 2, 8, 0);
    circle(linecolorimage, p3, 2, scalar(255, 0, 0), 2, 8, 0);
    circle(linecolorimage, p4, 2, scalar(255, 0, 0), 2, 8, 0);
    line(linecolorimage, point(topline[0], topline[1]), point(topline[2], topline[3]), scalar(0, 255, 0), 2, 8, 0);
    imshow("four corners", linecolorimage);
 
    // 【11】透视变换
    vector src_corners(4);
    src_corners[0] = p1;
    src_corners[1] = p2;
    src_corners[2] = p3;
    src_corners[3] = p4;
 
    vector dst_corners(4);
    dst_corners[0] = point(0, 0);
    dst_corners[1] = point(width, 0);
    dst_corners[2] = point(0, height);
    dst_corners[3] = point(width, height);
 
    // 【12】获取透视变换矩阵,并最终显示变换后的结果
    mat resultimage;
    mat warpmatrix = getperspectivetransform(src_corners, dst_corners);
    warpperspective(src, resultimage, warpmatrix, resultimage.size(), inter_linear);
    imshow("final result", resultimage);

3、示例图片

以上就是opencv通过透视变换实现矫正图像详解的详细内容,更多关于opencv矫正图像的资料请关注其它相关文章!

免费资源网 - https://freexyz.cn/
返回顶部
顶部
网站地图