创新实训项目分析——第十三篇

本文详细解析了如何在Android应用中利用OpenCV进行图片透视变换,包括轮廓检测、顶点定位、透视变换矩阵计算和实际操作流程。通过实例展示了从原始图片到矫正后的效果,并探讨了为功能按钮添加监听,以完善整个图片抗扭曲功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2021SC@SDUSC


前言

对于图片抗扭曲功能算法的实现,可以划分为以下任务:
1.采⽤寻找轮廓的⽅法,⽤approxPolyDP函数,对图像轮廓点进⾏多边形拟合
2.把图像的四个顶点处的点归类,划分出四个区域{左上,右上,右下,左下},利⽤opencv的寻找轮廓,得到最⼤轮廓,然后⽣成最⼩外接矩形,确定四个顶点的⼤致位置。设置⼀个阀值,与上图中的点集合求距离,⼤于阀值的舍弃,⼩于的保留。
3.所有的点集都落到了四个区域,利⽤矩形中,对⻆线距离最⼤,确定四个顶点的位置
4.根据输⼊和输出点获得图像透视变换的矩阵
5.透视变换。透视变换(Perspective Transformation)是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使承影面(透视面)绕迹线(透视轴)旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换。
这一篇我们将继续分析寻找轮廓方法的代码

一、项目环境

android studio版本 4.1.2

sdk版本 Compile SDK version:30

Build Tools Version 30.0.3

gradle版本 6.8.3

二、代码分析

1.透视变换,矫正图像

Mat dst = new Mat();
​ Imgproc.warpPerspective(src, dst, perspectiveMmat, src.size(), Imgproc.INTER_LINEAR + Imgproc.WARP_INVERSE_MAP,
                1, new Scalar(0));

cv2.warpPerspective() 是透视变换函数,用于解决cv2.warpAffine()不能处理视场和图像不平行的问题。应用cv2.warpPerspective()前需先使用cv2.getPerspectiveTransform()得到转换矩阵。转换矩阵为3x3阶。这一个矩阵我们已经在之前得到了。
CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
InputArray M, Size dsize,
int flags = INTER_LINEAR,
int borderMode = BORDER_CONSTANT,
const Scalar& borderValue = Scalar());
函数参数解释如下:
src:输入图像
dst:输出图像,图像的类型须跟原图一致
M:转换矩阵
dsize :输出图像的大小
flags :表示插值方法的组合,线性插值或者最近邻插值;如设置了可选项WARP_INVERSE_MAP(变形插值映射),则会使得转换矩阵M为逆变形
borderMode :图像边界的处理方式
borderValue :边界的颜色设置,默认为0

Imgproc.warpPerspective(src, dst, perspectiveMmat, src.size(), Imgproc.INTER_LINEAR + Imgproc.WARP_INVERSE_MAP,
1, new Scalar(0));
则src是源图像,输出为经过透视变换后的图像dst,转换矩阵为perspectiveMmat,经由 Mat perspectiveMmat = Imgproc.getPerspectiveTransform(srcPoints, dstPoints)得到,输出图像的大小调整为和src的大小一样,插值方法的组合为变形插值映射和线性插值相结合,图像边界的处理方式选择了常数填充方法,颜色设置为默认0

   String TAG = "CameraPreview";
        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES), TAG);//的搭配存储sd卡的位置
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());//时间戳,用来命名
        Imgcodecs.imwrite(mediaStorageDir.getPath() + File.separator +
                "IMG_" + timeStamp + ".jpg",dst);//文件命名

        Uri uri = Uri
                .parse(mediaStorageDir.getPath() + File.separator +
                        "IMG_" + timeStamp + ".jpg");//返回uri路径

至此,图片抗扭出算法已经处理完毕,新得到的已经完成变换后的图片存储在了相应位置,并且存储了uri路径

2.为按钮添加监听,完善功能

 Button buttonok = (Button) findViewById(R.id.ok);
        buttonok.setOnClickListener(new View.OnClickListener() {//添加监听事件
            @Override
            public void onClick(View v) {
              Mat src;
                String c = uri.getPath();
              src= Imgcodecs.imread(uri.getPath());/载入图像
                Uri uri1;
                try {
                    uri1=warpPerspective(src);//得到透视变换后的图像
                    ImageView view = new ImageView(getApplicationContext());//得到承载img的view
                    view.setImageURI(uri1);//将view装入图像
                    preview.addView(view);//添加到预览view中
                }catch (IndexOutOfBoundsException e){
                    Toast.makeText(getApplicationContext(),"矫正失败,请拍摄清晰一点的图片吧",Toast.LENGTH_LONG).show();
                }
            }
        }); 

其中try——catch函数体是为了保证程序不会因为算法的偶然性而直接退出
至此,图片抗扭曲算法完成
效果展示:
矫正前:

在这里插入图片描述
矫正后:
在这里插入图片描述

三、总结

本次创新实训项目分析,我的任务是分析飞花令项目和图片抗扭曲算法两个项目,两个项目中我都学习到了很多。
飞花令项目相对简单一点,对于没有接触过as安卓开发的同学比较友好,可以很简单的就能上手页面之间传参的方式、消息传递以及view间的关系。
而图片抗扭曲算法相对难一点,里面用到了关于opencv的知识,需要进一步的去熟悉opencv的方法,并且在图片抗扭曲和透视转换上面,需要有更清晰的算法思路,开发人员的算法非常的清晰,步骤很完善,所以相对来说也是一个比较好上手的算法。从开始寻找最大轮廓、确定顶点的位置、得到透视转换的矩阵再到进行透视转换,所有过程串联起来得到了矫正过后的图像。
非常感谢这段时间对于这些代码的分析,让我对as有了入门的了解,也对as有了兴趣,相信在之后的手机开发方面,这一个学期的学习能为我建立起良好的基础

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值