使用javacv+maven+javacpp做出简单文本倾斜矫正
示例图片:
使用旋转后的效果图片:
package com.javacv.test;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_core.*;
import static org.bytedeco.javacpp.opencv_imgcodecs.cvLoadImage;
import static org.bytedeco.javacpp.opencv_imgproc.*;
public class test2 {
//自动倾斜
public static void main(String[] args) {
IplImage image = null;
image = cvLoadImage("c://test.jpg");
IplImage copy = cvCloneImage(image);
//建立储存边缘检测结果图像canImage
IplImage canImage = cvCreateImage(cvGetSize(copy), IPL_DEPTH_8U, 1);
//进行边缘检测
cvCanny(copy, canImage, 30, 200, 3);
//进行hough变换
CvMemStorage storage = cvCreateMemStorage();
CvSeq lines = null;
//霍夫函数检测直线
//canImage输入8-比特、单通道(二值)图像,当用CV_HOUGH_PROBABILISTIC方法检测的时候其内容会被函数改变
//line_storage 检测到的线段存储仓.可以是内存存储仓(此种情况下,一个线段序列在存储仓中被创建,并且由函数返回),
// 或者是包含线段参数的特殊类型(见下面)的具有单行/单列的矩阵(CvMat*)。矩阵头为函数所修改,
// 使得它的 cols/rows 将包含一组检测到的线段。如果 line_storage 是矩阵,而实际线段的数目超过矩阵尺寸,
// 那么最大可能数目的线段被返回(线段没有按照长度、可信度或其它指标排序).
//method Hough 变换变量,是下面变量的其中之一:
// CV_HOUGH_STANDARD - 传统或标准 Hough 变换. 每一个线段由两个浮点数 (ρ, θ) 表示,其中 ρ 是直线与原点(0,0) 之间的距离,θ 线段与 x-轴之间的夹角。因此,矩阵类型必须是 CV_32FC2 type.
// CV_HOUGH_PROBABILISTIC- 概率 Hough 变换(如果图像包含一些长的线性分割,则效率更高). 它返回线段分割而不是整个线段。每个分割用起点和终点来表示,所以矩阵(或创建的序列)类型是 CV_32SC4.
// CV_HOUGH_MULTI_SCALE - 传统 Hough 变换的多尺度变种。线段的编码方式与 CV_HOUGH_STANDARD 的一致。
//rho 以象素为单位的距离精度,一般取1
//theta 以弧度为单位角度精度,一般取CV_PI/180
//threshold 阈值参数。当在一条直线上的像素点数大于threshold时,才将该直线作为检测结果显示出来。该值越大,得到直线越少
lines = cvHoughLines2(canImage, storage, CV_HOUGH_STANDARD, 1, CV_PI / 180, 20);
//统计与竖直夹角<30度的直线个数以及其夹角和
int numLine = 0;
double sumAng = 0;
int aa = 0;
int bb = 0;
for (int i = 0; i < lines.total(); i++) {
BytePointer bytePointer = cvGetSeqElem(lines, i);//用GetSeqElem获得直线
double line = bytePointer.getDouble();
CvRect r = new CvRect(cvGetSeqElem(lines, i));
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
double theta = line; //获取角度 为弧度制
if (theta < 0.5 && x > 0) {
aa = aa + 1;
}
if (theta < 2 && theta > 0.5 && x > 0) {
bb = bb + 1;
}
}
for (int i = 0; i < lines.total(); i++) {
BytePointer bytePointer = cvGetSeqElem(lines, i);//用GetSeqElem获得直线
CvRect r = new CvRect(cvGetSeqElem(lines, i));
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
double line = bytePointer.getDouble();
double theta = line; //获取角度 为弧度制
if (aa > bb) {
if (theta < CV_PI / 2) {
sumAng = sumAng + theta;
numLine = numLine + 1;
}
} else {
if (theta < CV_PI || theta > CV_PI / 2) {
sumAng = sumAng + theta;
numLine = numLine + 1;
}
}
}
//计算出平均倾斜角,anAng为角度制
double angle = 0;
angle = -(sumAng / numLine) * 180 / CV_PI;
//Define Rotational Matrix
CvMat mapMatrix = cvCreateMat(2, 3, CV_32FC1);
//Define Mid Point
CvPoint2D32f centerPoint = new CvPoint2D32f();
centerPoint.x(copy.width() / 2);
centerPoint.y(copy.height() / 2);
//Get Rotational Matrix
cv2DRotationMatrix(centerPoint, angle, 1.0, mapMatrix);
//建立输出图像RotateRow
double a = Math.sin(sumAng / numLine);
double b = Math.cos(sumAng / numLine);
//size中的图像的宽度和高度,depth图像像素的位深度,channels每个像素的通道数
IplImage rotatedImage = cvCreateImage(cvGetSize(copy), copy.depth(), copy.nChannels());
//Rotate the Image
cvWarpAffine(copy, rotatedImage, mapMatrix, CV_INTER_CUBIC + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
cvReleaseImage(copy);
cvReleaseMat(mapMatrix);
//IplImage转Mat
Mat mat2 = new Mat(rotatedImage);
//JavaCVUtil.imWrite(mat2, "c://0730//000602.tif");
JavaCVUtil.imWrite(mat2, "c://test9.jpg");
}
}
pom.xml代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yinuojingye</groupId>
<artifactId>helloJavaCV</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<javacpp.platform.dependencies>windows-x86_64</javacpp.platform.dependencies>
<javacpp.platform.android-arm>android-arm</javacpp.platform.android-arm>
<javacpp.platform.android-arm64>android-arm64</javacpp.platform.android-arm64>
<javacpp.platform.android-x86>android-x86</javacpp.platform.android-x86>
<javacpp.platform.android-x86_64>android-x86_64</javacpp.platform.android-x86_64>
<javacpp.platform.ios-arm>ios-arm</javacpp.platform.ios-arm>
<javacpp.platform.ios-arm64>ios-arm64</javacpp.platform.ios-arm64>
<javacpp.platform.ios-x86>ios-x86</javacpp.platform.ios-x86>
<javacpp.platform.ios-x86_64>ios-x86_64</javacpp.platform.ios-x86_64>
<javacpp.platform.linux-armhf>linux-armhf</javacpp.platform.linux-armhf>
<javacpp.platform.linux-arm64>linux-arm64</javacpp.platform.linux-arm64>
<javacpp.platform.linux-ppc64le>linux-ppc64le</javacpp.platform.linux-ppc64le>
<javacpp.platform.linux-x86>linux-x86</javacpp.platform.linux-x86>
<javacpp.platform.linux-x86_64>linux-x86_64</javacpp.platform.linux-x86_64>
<javacpp.platform.macosx-x86_64>macosx-x86_64</javacpp.platform.macosx-x86_64>
<javacpp.platform.windows-x86>windows-x86</javacpp.platform.windows-x86>
<javacpp.platform.windows-x86_64>windows-x86_64</javacpp.platform.windows-x86_64>
</properties>
<dependencies>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv</artifactId>
<version>1.4.2</version>
<exclusions>
<exclusion>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.4.1-1.4.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>opencv</artifactId>
<version>3.4.1-1.4.1</version>
<classifier>${javacpp.platform.dependencies}</classifier>
</dependency>
<!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/ffmpeg -->
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>3.4.2-1.4.1</version>
</dependency>
<dependency>
<groupId>org.bytedeco.javacpp-presets</groupId>
<artifactId>ffmpeg</artifactId>
<version>3.4.2-1.4.1</version>
<classifier>${javacpp.platform.dependencies}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</project>