ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Z 轴倾斜矫正

2021-06-03 18:57:22  阅读:198  来源: 互联网

标签:矫正 src Imgproc 倾斜 val 透视 https com


图像倾斜

一般图像倾斜有两种情况:

  • 平面倾斜:拍照设备与拍照对象平行,拍出来的图像只需要进行旋转即可完成矫正。

    平面倾斜图片

  • Z 轴倾斜:拍照设备与拍照对象不平行,拍出来的图像要先进行透视变换,然后再进行旋转等操作才可以完成矫正。

    Z轴倾斜图片

上一篇文章我们采用理想化图片尝试了平面倾斜的矫正,今天我们继续用理想化图片尝试Z轴倾斜矫正。核心内容就是透视变换,Android OpenCV 系列中有有一篇关于透视变换的文章,当时我们是直接手动标点,然后生成透视矩阵完成透视变换。针对 Z 轴倾斜矫正,也是可以通过人为干预标点然后通过透视变换解决,但是为了综合利用下自学的API,尝试在理想图片下自动完成。

基本思路

  • 均值漂移滤波
  • 灰度化、二值化
  • Canny边缘检测
  • 轮廓发现
  • 轮廓外接多边形
  • 透视变换矩阵
  • 透视变换

代码实现

均值漂移滤波

知识点:https://mp.weixin.qq.com/s/qNiI6MStRvm4LFiPhMiKWw

// 1. 均值漂移滤波
val blurred = Mat()
Imgproc.pyrMeanShiftFiltering(inputImage, blurred, 25.0, 10.0)

均值漂移滤波

灰度化、二值化

知识点:https://mp.weixin.qq.com/s/rNkOlGlKmZTiGVM-_e7zYQ

知识点:https://mp.weixin.qq.com/s/SfMF0RLxyklZT8-2e7QqPg

/**
 * 源图像灰度化二值化
 */
private fun processGrayAndBinary(src: Mat): Mat {
    if (src.cols() > 1000 || src.rows() > 800) {//图片过大,进行降采样
        Imgproc.pyrDown(src, src)
        Imgproc.pyrDown(src, src)
    }
    var grayImage = Mat()
    if (src.type() == CvType.CV_8UC1) {
        grayImage = src.clone()
    } else if (src.type() == CvType.CV_8UC3) {
        Imgproc.cvtColor(src, grayImage, Imgproc.COLOR_BGR2GRAY)//转化灰度图
    }

    val binaryImage = Mat()
    Imgproc.adaptiveThreshold(
        grayImage,
        binaryImage,
        255.0,
        Imgproc.ADAPTIVE_THRESH_MEAN_C,
        Imgproc.THRESH_BINARY,
        7,
        0.0
    )//自适应滤波
    return binaryImage
}

灰度化、二值化

Canny 边缘检测

知识点:https://mp.weixin.qq.com/s/6YiyPMz2JsbhhaIu8W9AEQ

// 3. 边缘检测
Imgproc.Canny(binary, binary, 100.0, 200.0, 3)

Canny边缘检测

轮廓发现

知识点:https://mp.weixin.qq.com/s/teLC9is4DbaWspmlBRnZcA

// 4. 轮廓发现
val contours = mutableListOf<MatOfPoint>()
val hierarchy = Mat()
Imgproc.findContours(
    binary,
    contours,
    hierarchy,
    Imgproc.RETR_EXTERNAL,
    Imgproc.CHAIN_APPROX_SIMPLE
)

轮廓发现

轮廓多边形

知识点: https://mp.weixin.qq.com/s/k1XoftYDd_obuoo8aCm2xA

val externalContour2f = MatOfPoint2f()
contours.first().convertTo(externalContour2f, CvType.CV_32F)
val peri = Imgproc.arcLength(externalContour2f, true)
val approxCurve = MatOfPoint2f()
// 5. 多边形逼近
Imgproc.approxPolyDP(externalContour2f, approxCurve, 0.02 * peri, true)

透视变换矩阵

知识点:https://mp.weixin.qq.com/s/rJ2-lgnQlgn6mQfsIU8fSA

val dstPoints = mutableListOf(
    Point(inputImage.width().toDouble(), 0.0),
    Point(0.0, 0.0),
    Point(0.0, inputImage.height().toDouble()),
    Point(inputImage.width().toDouble(), inputImage.height().toDouble()),
)
val dstMat = Converters.vector_Point2f_to_Mat(dstPoints)
// 6. 透视变换矩阵
val transform = Imgproc.getPerspectiveTransform(approxCurve, dstMat)

透视变换

知识点:https://mp.weixin.qq.com/s/rJ2-lgnQlgn6mQfsIU8fSA

val dst = Mat()
// 7. 透视变换
Imgproc.warpPerspective(
    inputImage,
    dst,
    transform,
    inputImage.size(),
    Imgproc.INTER_NEAREST
)

透视变换

效果

如下图,基于一些几乎无干扰的理想图片,我们可以正确的基于轮廓多边形获取到四边形的四个顶点,生成透视变换矩阵并完成透视变换。但是现实生活中,这种理想图片几乎没有,全靠图像预处理达到理想图片的效果,这里我们仅将其作为综合使用 OpenCV 基础知识的示例。

理想化效果

源码

https://github.com/onlyloveyd/LearningAndroidOpenCV

标签:矫正,src,Imgproc,倾斜,val,透视,https,com
来源: https://blog.csdn.net/poorkick/article/details/117532348

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有