首先先去opencv官网下载资源

官网地址:Releases - OpenCV

官网下载慢可以选择在百度网盘下载,版本是455

链接:https://pan.baidu.com/s/1LADtih8l8nStKwJRIde91Q 
提取码:wx0h

提示:以下方法只适用于小角度倾斜,90度这种无法矫正!!!

下载之后解压,\opencv\build\java下有个jar包,需要导入到ide中,该目录下还有x64和x86两个文件夹,是opencv的动态库,根据自己电脑来选择使用,opencv的接口都在动态库里,很重要!

导入jar包,引入opencv的动态库

后续会用到PngEncoder,需要导入包

<!-- png图片处理 -->
<dependency><groupId>com.pngencoder</groupId><artifactId>pngencoder</artifactId><version>0.9.0</version>
</dependency>

后面就是具体的代码开发,第一个方法是用opencv的霍夫检测算法计算倾斜角度并旋转,但是因为修改后图片比原图大了十几倍,放弃了,知道的大佬可以指导下怎么在不改变图片的分辨率和清晰度缩小图片。

public static void first () {try {//输入图片路径String srcPath = "D:\\TU\\x7.png";//输出图片路径String rotatePath = "D:\\TU\\rotate.png";//加载opencv动态库,必要System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//输入图片Mat src = Imgcodecs.imread(srcPath);//灰度化Mat gray = new Mat();if (src.channels() == 3) {Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);src = gray;} else {System.out.println("不是RGB图片!");}//边缘算法检测Mat cannyMat = src.clone();//表示迟滞过程的第一个阈值double threshold1 = 60;//表示迟滞过程的第二个阈值,通常把第一个阈值*2或*3double threshold2 = threshold1 * 3;Imgproc.Canny(src, cannyMat, threshold1, threshold2);//计算倾斜角度double angle = OpenCVUtil.getAngle(cannyMat);// 获取最大矩形RotatedRect rect = OpenCVUtil.findMaxRect(cannyMat);// 旋转矩形Mat CorrectImg = OpenCVUtil.rotation(cannyMat, rect, angle);HandleImgUtils.saveImg(CorrectImg, "d:/TU/correct.png");} catch (Exception e) {e.printStackTrace();}
}

第二个方法是用opencv的霍夫检测计算出倾斜角度,通过Graphics2D来旋转图片。

public static void second () {try {//输入图片路径String srcPath = "D:\\TU\\x7.png";//输出图片路径String rotatePath = "D:\\TU\\rotate.png";//加载opencv动态库,必要System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//输入图片Mat src = Imgcodecs.imread(srcPath);//灰度化Mat gray = new Mat();if (src.channels() == 3) {Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);src = gray;} else {System.out.println("不是RGB图片!");}//边缘算法检测Mat cannyMat = src.clone();//表示迟滞过程的第一个阈值double threshold1 = 60;//表示迟滞过程的第二个阈值,通常把第一个阈值*2或*3double threshold2 = threshold1 * 3;Imgproc.Canny(src, cannyMat, threshold1, threshold2);//计算倾斜角度double angle = OpenCVUtil.getAngle(cannyMat);//图片旋转BufferedImage srcBuff = ImageIO.read(new File(srcPath));//图片宽度int width = srcBuff.getWidth(null);//图片高度int height = srcBuff.getHeight(null);BufferedImage res = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);Graphics2D g2 = res.createGraphics();//设置图片底色g2.setBackground(Color.WHITE);g2.fillRect(0, 0, width, height);g2.rotate(Math.toRadians(angle), width / 2, height / 2);g2.drawImage(srcBuff, null, null);g2.dispose();//ImageIO.write生成png速度特别慢,听说jdk1.9以后有优化(没试过),但是本项目不能改jdk版本,所以选择PngEncoder来生成图片//ImageIO.write(res, "png", new File(rotatePath));PngEncoder encoder=new PngEncoder();encoder.withBufferedImage(res).toFile(rotatePath);} catch (Exception e) {e.printStackTrace();}
}

OpenCVUtil工具类

public class OpenCVUtil {/*** 寻找轮廓,并按照递增排序** @param cannyMat* @return*/public static List<MatOfPoint> findContours(Mat cannyMat) {List<MatOfPoint> contours = new ArrayList<MatOfPoint>();Mat hierarchy = new Mat();// 寻找轮廓Imgproc.findContours(cannyMat, contours, hierarchy, Imgproc.RETR_LIST,                 Imgproc.CHAIN_APPROX_SIMPLE,new Point(0, 0));if (contours.size() <= 0) {throw new RuntimeException("未找到图像轮廓");} else {// 对contours进行了排序,按递增顺序contours.sort(new Comparator<MatOfPoint>() {@Overridepublic int compare(MatOfPoint o1, MatOfPoint o2) {MatOfPoint2f mat1 = new MatOfPoint2f(o1.toArray());RotatedRect rect1 = Imgproc.minAreaRect(mat1);Rect r1 = rect1.boundingRect();MatOfPoint2f mat2 = new MatOfPoint2f(o2.toArray());RotatedRect rect2 = Imgproc.minAreaRect(mat2);Rect r2 = rect2.boundingRect();return (int) (r1.area() - r2.area());}});return contours;}}    /*** 作用:返回边缘检测之后的最大轮廓** @param cannyMat*            Canny之后的Mat矩阵* @return*/public static MatOfPoint findMaxContour(Mat cannyMat) {List<MatOfPoint> contours = findContours(cannyMat);return contours.get(contours.size() - 1);}/*** 返回边缘检测之后的最大矩形** @param cannyMat*            Canny之后的mat矩阵* @return*/public static RotatedRect findMaxRect(Mat cannyMat) {MatOfPoint maxContour = findMaxContour(cannyMat);MatOfPoint2f matOfPoint2f = new MatOfPoint2f(maxContour.toArray());RotatedRect rect = Imgproc.minAreaRect(matOfPoint2f);Imgproc.boundingRect(cannyMat);return rect;}/*** 获取倾斜角度,只能矫正小角度倾斜,大于90度没法判断文字朝向* @author lyzhou2* @date 2022/3/4 15:05* @param cannyMat* @return*/public static double getAngle (Mat cannyMat) {Mat lines = new Mat();//累加器阈值参数,小于设置值不返回int threshold = 100;//最低线段长度,低于设置值则不返回double minLineLength = 200;//间距小于该值的线当成同一条线double maxLineGap = 10;Imgproc.HoughLinesP(cannyMat, lines, 1, Math.PI/180, threshold, minLineLength, maxLineGap);//倾斜角度double angle = 0;//所有线倾斜角度之和double totalAngle = 0;for (int i = 0; i < lines.rows(); i++) {double[] line = lines.get(i, 0);//计算每条线弧度//这个计算是给Imgproc.getRotationMatrix2D方法用的,但是生成的图片会比原图大十几倍,简直离谱,有知道的大佬也可告知下怎么在不改变图片分辨率和清晰度的情况下缩小
//            double radian = Math.atan(Math.abs(line[3] - line[1]) * (1.0) / (line[2] - line[0]));//这个计算是给Graphics2D旋转使用double radian = Math.atan((line[3] - line[1]) * (-1.0) / (line[2] - line[0]));//计算每条线的倾斜角度double lineAngle = 360 * radian / (2 * Math.PI);//表格类图片要过滤掉竖线,不然取得角度会有问题if (Math.abs(lineAngle) > 45) {lineAngle = 90 - lineAngle;}totalAngle += lineAngle;}//取角度平均数angle = totalAngle / lines.rows();return angle;}
}

接下来就是测试验证了

第一张是原图,第二张是矫正之后的图片,可以看到很明显的矫正了。

如果矫正后还是特别倾斜的,可以通过修改threshold、minLineLength 、maxLineGap 这几个参数来调整。

这只是在main方法里执行成功了,如果放在接口里去调用,会报错:Exception in thread "main" java.lang.UnsatisfiedLinkError: org.opencv.imgcodecs.Imgcodecs.imread_1(Ljava/lang/String;)J

然后你去百度会有说把System.loadLibrary改成System.load,然后又会报另一个错:java.lang.UnsatisfiedLinkError: Expecting an absolute path of the library: opencv_java455

其实就是找不到opencv动态库的路径。

顺便科普下System.loadLibrary参数是相对路径下的dll,System.load参数是绝对路径。如果是用System.load的话,直接写死就行,用System.loadLibrary则需要在启动时加上下面这句,windows下还可以把dll放在系统环境变量的Path任意目录下,因为System.loadLibrary默认是去Path下读取。

例如放到项目同级目录下:

VM options:-Djava.library.path=./

设置好后就可以用postman去调用接口测试了。

最后就是打包了,因为阿里的maven仓库里没有opencv-455.jar这个包,所以打包成jar包的时候会发现opencv-455.jar没有被打包进去,需要在pom.xml设置。

groupId、artifactId、version可以随便写,scope写system,systemPath是指jar路径,${basedir}是指当前项目目录。

<!-- 图片处理 OpenCv-->
<dependency><groupId>org.opencv</groupId><artifactId>opencv</artifactId><version>4.5.5</version><scope>system</scope><systemPath>${basedir}/lib/opencv-455.jar</systemPath>
</dependency>

【参考资料】

Java基于opencv—矫正图像 - 奇迹迪 - 博客园

Java实现图片无损任意角度旋转_通往精英的成长之路-CSDN博客_java实现图片旋转

JavaCV入门示例及UnsatisfiedLinkError异常踩坑记录_半斤米粉闯天下的博客-CSDN博客

java OpenCV实现扫描仪图片倾斜矫正相关推荐

  1. openCV图片倾斜矫正(java版)

    核心思想:由于openCV是用C编写,因此对C的支持度最高,曾经尝试转换成JAVA,最终都失败了,因此核心底层代码仍然是C版的 基本思路:java调用dll客户端->生成.h头文件->新建 ...

  2. python图像倾斜校正_霍夫变换 文本图片倾斜矫正 python实现

    一.霍夫变换原理简介 霍夫变换主要是利用图片所在的空间和霍夫空间之间的变换,将图片所在的直角坐标系中具有形状的曲线或直线映射到霍夫空间的一个点上形成峰值,从而将检测任意形状的问题转化成了计算峰值的问题 ...

  3. opencv图片倾斜矫正

    #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...

  4. Java + OpenCV 实现更换背景图片(绿色幕布切图)(JavaCV)

    一.效果展示 更换后效果图: 色素参数选的不准, 有点糊.    +          =>         二.完整代码 package com.biubiu.example;import o ...

  5. python身份证图片倾斜矫正_python实现证件图片倾斜矫正

    上图: 上代码: import os import cv2 import math import random import numpy as np from scipy import misc, n ...

  6. opencv图像处理中的一些滤波器+利用滤波器提取条形码(解析二维码)+公交卡倾斜矫正+物体尺寸丈量

    一般来说,图像的能量主要集中在其低频部分,噪声所在的频段主要在高频段,同时图像中的细节信息也主要集中在其高频部分,因此,如何去掉高频干扰同时又保持细节信息是关键.为了去除噪声,有必要对图像进行平滑,可 ...

  7. 对于图片倾斜做矫正处理

    一 霍夫变换 对于图片倾斜问题可通过霍夫变换进行矫正,霍夫变换主要是利用图片所在的空间和霍夫空间之间的变换,将图片所在的直角坐标系中具有形状的曲线或直线映射到霍夫空间的一个点上形成峰值,从而将检测任意 ...

  8. java Opencv 图片修复 Photo

    OpenCV 如何进行图片修复 修复函数: Photo.inpaint(imageSrc, imageMask, imageDst, radius, Photo.INPAINT_TELEA); ima ...

  9. C# OpenCV EmguCV实现扫描文本图像倾斜矫正 实现详解(附源码)

    一.扫描文本倾斜矫正 实现步骤可以参考如下链接: https://blog.csdn.net/stq054188/article/details/120031667?spm=1001.2014.300 ...

最新文章

  1. 58同城招聘|三维重建、图像图形学算法工程师(校招/社招)
  2. Perl默认的内部变量
  3. 搭建EJB3开发环境
  4. matplotlib嵌入到pyqt中
  5. htmlparser解析网站时服务器返回的文件编码和页面编码不一致问题
  6. 第五章 深度神经网络为何很难训练
  7. 数据结构——线性表的C语言实现
  8. 解决Lync Server前端必备组件Wmf2008R2安装失败
  9. a标签的href传递信息
  10. 闭环检测python_hdl_graph_slam源码解读(七):闭环检测
  11. SpringSecurity实现记住我功能
  12. 嵩天python笔记_Python学习笔记
  13. JavaScript学习(八十六)—运算符知识点总结
  14. Centos7下,LVM根分区扩容
  15. python剑指offer数组中出现次数超过一半的数字
  16. 库 v10怎么安装_22000Pa强劲吸力加高续航,追觅V10无线吸尘器体验
  17. Cheat Engine逆向修改植物大战僵尸(外挂)
  18. win7如何设置以管理员身份运行程序
  19. 跨域请求(使用jsonp实现跨域请求)百度地图api证逆地址解析获取周边信息(pois)
  20. 【转载】Windows/Office“神key的来源”(附win8神key)

热门文章

  1. 次世代游戏场景间谍屋制作图文教程
  2. java ee2019 11 5关于多态 抽象类 接口
  3. java 如何将word 转换为ftl_Java之利用FreeMarker导出Word实例
  4. web设计之:崛起中的九大HTML5开发工具
  5. 从0开发游戏引擎之游戏引擎中2D序列帧动画控制器的实现
  6. Kotlin File转ByteArray
  7. Android开发之监听软键盘状态(弹出收回)
  8. Apollo 7.0——percception:rader源码剖析
  9. 浅谈 js运行机制 、宏观任务、微观任务
  10. U盘卡机文件损坏怎么办?