更多的时候,我们得到的图像不可能是正的,多少都会有一定的倾斜,就比如下面的

我们要做的就是把它们变成下面这样的

我们采用的是寻找轮廓的思路,来矫正图片;只要有明显的轮廓都可以采用这种思路

具体思路:
1、先用opencv提供的canny函数,进行一次边缘检测
2、再用opencv提供的findContours函数,寻找图像的轮廓,从中间结果种,找到最大的轮廓,就是我们图像的最外面的轮廓
3、得到最终轮廓后,计算矩形轮廓与水平的夹角,然后旋转图像
4、最后我们在从旋转后的图像中,把我们感兴趣的切割出来,就可以了

我们实际的实现一下

先用opencv提供的canny函数,进行一次边缘检测;具体的函数就不再讲解,百度上非常多

/*** canny算法,边缘检测* * @param src* @return*/public static Mat canny(Mat src) {Mat mat = src.clone();Imgproc.Canny(src, mat, 60, 200);HandleImgUtils.saveImg(mat , "C:/Users/admin/Desktop/opencv/open/x/canny.jpg");return mat;}

再用opencv提供的findContours函数,寻找图像的轮廓,从中间结果种,找到最大的轮廓,就是我们图像的最外面的轮廓

/*** 返回边缘检测之后的最大矩形,并返回* * @param cannyMat*            Canny之后的mat矩阵* @return*/public static RotatedRect findMaxRect(Mat cannyMat) {List<MatOfPoint> contours = new ArrayList<MatOfPoint>();Mat hierarchy = new Mat();// 寻找轮廓Imgproc.findContours(cannyMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE,new Point(0, 0));// 找出匹配到的最大轮廓double area = Imgproc.boundingRect(contours.get(0)).area();int index = 0;// 找出匹配到的最大轮廓for (int i = 0; i < contours.size(); i++) {double tempArea = Imgproc.boundingRect(contours.get(i)).area();if (tempArea > area) {area = tempArea;index = i;}}MatOfPoint2f matOfPoint2f = new MatOfPoint2f(contours.get(index).toArray());RotatedRect rect = Imgproc.minAreaRect(matOfPoint2f);return rect;}

得到最终轮廓后,计算矩形轮廓与水平的夹角,然后旋转图像

/*** 旋转矩形* * @param src*            mat矩阵* @param rect*            矩形* @return*/public static Mat rotation(Mat cannyMat, RotatedRect rect) {// 获取矩形的四个顶点Point[] rectPoint = new Point[4];rect.points(rectPoint);double angle = rect.angle + 90;Point center = rect.center;Mat CorrectImg = new Mat(cannyMat.size(), cannyMat.type());cannyMat.copyTo(CorrectImg);// 得到旋转矩阵算子Mat matrix = Imgproc.getRotationMatrix2D(center, angle, 0.8);Imgproc.warpAffine(CorrectImg, CorrectImg, matrix, CorrectImg.size(), 1, 0, new Scalar(0, 0, 0));return CorrectImg;}

最后我们在从旋转后的图像中,把我们感兴趣的切割出来,就可以了

/*** 把矫正后的图像切割出来* * @param correctMat*            图像矫正后的Mat矩阵*/public static void cutRect(Mat correctMat , Mat nativeCorrectMat) {// 获取最大矩形RotatedRect rect = findMaxRect(correctMat);Point[] rectPoint = new Point[4];rect.points(rectPoint);int startLeft = (int)Math.abs(rectPoint[0].x);int startUp = (int)Math.abs(rectPoint[0].y < rectPoint[1].y ? rectPoint[0].y : rectPoint[1].y);int width = (int)Math.abs(rectPoint[2].x - rectPoint[0].x);int height = (int)Math.abs(rectPoint[1].y - rectPoint[0].y);System.out.println("startLeft = " + startLeft);System.out.println("startUp = " + startUp);System.out.println("width = " + width);System.out.println("height = " + height);for(Point p : rectPoint) {System.out.println(p.x + " , " + p.y);}Mat temp = new Mat(nativeCorrectMat , new Rect(startLeft , startUp , width , height ));Mat t = new Mat();temp.copyTo(t);HandleImgUtils.saveImg(t , "C:/Users/admin/Desktop/opencv/open/x/cutRect.jpg");}

整合整个过程

/*** 矫正图像* * @param src* @return*/public static void correct(Mat src) {// CannyMat cannyMat = canny(src);// 获取最大矩形RotatedRect rect = findMaxRect(cannyMat);// 旋转矩形Mat CorrectImg = rotation(cannyMat , rect);Mat NativeCorrectImg = rotation(src , rect);//裁剪矩形cutRect(CorrectImg , NativeCorrectImg);HandleImgUtils.saveImg(src, "C:/Users/admin/Desktop/opencv/open/x/srcImg.jpg");HandleImgUtils.saveImg(CorrectImg, "C:/Users/admin/Desktop/opencv/open/x/correct.jpg");}

测试代码

/*** 测试矫正图像*/public void testCorrect() {System.loadLibrary(Core.NATIVE_LIBRARY_NAME);Mat src = HandleImgUtils.matFactory("C:/Users/admin/Desktop/opencv/open/x/x7.jpg");HandleImgUtils.correct(src);}

Java方面opencv的例子还是蛮少的,代码都是自己参考博客写的,照顾不周的地方,请见谅

本项目的所有代码地址:https://github.com/YLDarren/opencvHandleImg

Java基于opencv—矫正图像相关推荐

  1. Java基于opencv实现图像数字识别(一),java开发面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  2. Java基于opencv实现图像数字识别(一)

    Java基于opencv实现图像数字识别(一) 最近分到了一个任务,要做数字识别,我分配到的任务是把数字一个个的分开:当时一脸懵逼,直接百度java如何分割图片中的数字,然后就百度到了用Buffere ...

  3. 数字识别java开源_Java基于opencv实现图像数字识别(三)—灰度化和二值化

    Java基于opencv实现图像数字识别(三)-灰度化和二值化 一.灰度化 灰度化:在RGB模型中,如果R=G=B时,则彩色表示灰度颜色,其中R=G=B的值叫灰度值:因此,灰度图像每个像素点只需一个字 ...

  4. java图片降噪_Java基于opencv实现图像数字识别(四)—图像降噪

    Java基于opencv实现图像数字识别(四)-图像降噪 我们每一步的工作都是基于前一步的,我们先把我们前面的几个函数封装成一个工具类,以后我们所有的函数都基于这个工具类 这个工具类呢,就一个成员变量 ...

  5. 基于OpenCV平滑图像

    基于OpenCV平滑图像也就是图像模糊,本博文介绍使用OpenCV的不同函数通过线性滤波进行图像平滑. cv::blur cv::GaussianBlur (高斯模糊) cv::medianBlur ...

  6. 4.3【图像镜像】-------------基于Opencv实现-----图像的镜像变换

     [1]理论知识:         镜像变换又分为水平镜像和垂直镜像,水平镜像即将图像左半部分和右半部分以图像竖直中轴线为中心轴进行兑换,而竖直镜像则是将图像上半部分和下半部分以图像水平中轴线为中 ...

  7. 基于OpenCV实现------图像的转置

    [1]理论基础 图像转置是将图像的x坐标和y坐标互换,图像的大小会随之改变----------即高度和宽度将互换. [2]图像转置的变换公式 因为转置矩阵的逆矩阵仍然是其本身,故转置变换的逆变换具有相 ...

  8. 基于OpenCV实现图像平移

    [1]理论知识 图像平移就是将图像中所有的点按照指定的平移量水平或者垂直移动 [2]完整代码 /*--------------------------------------------------- ...

  9. 基于OpenCV实现图像线性变化

    基础知识: 线性灰度变换函数f(x)是一个一维线性函数 y=f(x)=ax+b 式中:a为线性函数的斜率,b为线性函数在y轴的截距,x表示输入图像的灰度值,y表示输出图像的灰度值. (1) 当a> ...

最新文章

  1. careercup-树与图 4.6
  2. mysql5.7 新建远程用户_Centos7中 mysql5.7 用户 创建 、授权、远程登录
  3. Druid : 慢SQL统计与监控
  4. ubuntu16.04打造vim和python3的IDE
  5. 最小二乘法进行曲线拟合(Python)
  6. 平衡小车——编码器原理及其使用
  7. 成功将qt程序移植到arm板上
  8. 机械键盘cherry常见轴科普 --By Cheng
  9. CSS透明opacity和IE各版本透明度滤镜filter的最准确用法
  10. 求义隆单片机c语言红外解码程序,吐槽义隆单片机,顺便送上超轻红外解码程序....
  11. 同一个人两次被雷电击中,张益唐攻克世纪难题朗道-西格尔零点猜想?
  12. 一键加群android代码如何使用!
  13. CP分解和HOSVD分解
  14. CTF pwn题堆入门 -- Unsorted bin
  15. Bayesian Face Revisited: A Joint Formulation论文笔记
  16. unity基础开发----unity获取外部设备(方向盘)按键
  17. TCL电视无法开机,如何强制黑屏刷机教程分享
  18. mvc 截取上传图片做头像,自动生成不同小尺寸缩略图
  19. opengl怎么加阴影_这些超高颜值的计时器是怎么用PPT做出来的?(上)
  20. 移动App的推送技术

热门文章

  1. 伺服电机三环(电流环、速度环、位置环)控制原理及参数调节
  2. 1.4总线:并行总线、串行总线、单工、半双工、全双工、总线宽度、总线带宽、总线的分类、数据总线、地址总线、控制总线
  3. 第五讲 中断、异常和信号
  4. 用于数据仓库现代化的云原生数据流的案例
  5. 2022年天猫双11活动时间及玩法
  6. 文本数据增强一(概述、中文、同义句生成、enhance、augment、text、nlp)
  7. “Let’s Eat Grandma”:标点符号(句法树)增强语义表达,用于情感分析
  8. Vue Get请求数据
  9. 什么是大数据?大数据有什么用?
  10. QPS 与 TPS 简介