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)
轮廓发现
知识点: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
- halcon倾斜字体矫正(举一反三)
- 车牌识别--倾斜矫正
- OpenCV仪表数据识别(四):图像倾斜矫正
- 车牌识别--倾斜矫正
- 图像倾斜矫正方程基本的图像变换
- 车牌倾斜矫正
- 车牌识别--倾斜矫正
- [置顶] openCV-图片倾斜矫正java版
- 名片识别(一)倾斜矫正
- 车牌识别--倾斜矫正
- 基于matlab的蓝色车牌识别(车牌倾斜矫正)
- 手写数字识别系统之倾斜矫正
- 车牌识别--倾斜矫正
- 图片文档倾斜矫正算法 附完整c代码
- tesseract源码Page Layout解读(倾斜矫正)
- 倾斜物体矫正
- 图片文档倾斜矫正算法 附完整c代码
- 车牌识别--倾斜矫正
- 手写数字识别系统之倾斜矫正
- OpenCV仪表数据识别(四):图像倾斜矫正