openCV图片倾斜矫正(java版)

核心思想:由于openCV是用C编写,因此对C的支持度最高,曾经尝试转换成JAVA,最终都失败了,因此核心底层代码仍然是C版的

基本思路:java调用dll客户端->生成.h头文件->新建win32项目->导入相关支持和头文件->编写c代码->生成dll文件->java客户端调用

具体步骤如下:

1.调用dll的java代码

package com.daorigin.AI.ocr;

import java.io.File;
import java.io.IOException;
/**
 * 图片倾斜矫正
 * @author MuZB
 *
 */
public abstract class ImgCorrectTilt {
	static {
		File directory = new File("");//参数为空
    	String courseFile;
		try {
			courseFile = directory.getCanonicalPath();
			System.load(courseFile + File.separator + "AI.dll");
		} catch (IOException e) {
			e.printStackTrace();
		}
//		System.load("D:" + File.separator + "AI.dll");
    }
    public native static int correct(String inFile,String outFile);
    public static void main(String[] args) {
    	int i = correct("E:/2.jpg","E:/haha.jpg");
    	System.out.println(i);
    }
    
}

2.生成.h头文件
这里写图片描述

3.新建项目,选择Win32 项目
这里写图片描述
4.应用程序类型选择DLL
这里写图片描述
5.导入头文件
这里写图片描述
6.新建核心代码PicTiltCorrect.cpp,具体代码如下



#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include"com_daorigin_AI_ocr_ImgCorrectTilt.h"

using namespace cv;
using namespace std;

#define GRAY_THRESH 150
#define HOUGH_VOTE 100

//#define DEGREE 27
JNIEXPORT int JNICALL JNICALL Java_com_daorigin_AI_ocr_ImgCorrectTilt_correct(JNIEnv *env, jclass,jstring inFile, jstring outFile)
//int main(int argc, char **argv)
{
	//Read a single-channel image
	const char* filename = env->GetStringUTFChars(inFile,NULL);
	Mat srcImg = imread(filename, CV_LOAD_IMAGE_GRAYSCALE);
	if (srcImg.empty())
		return -1;
	//imshow("source", srcImg);

	Point center(srcImg.cols / 2, srcImg.rows / 2);

#ifdef DEGREE
	//Rotate source image
	Mat rotMatS = getRotationMatrix2D(center, DEGREE, 1.0);
	warpAffine(srcImg, srcImg, rotMatS, srcImg.size(), 1, 0, Scalar(255, 255, 255));
	//imshow("RotatedSrc", srcImg);
	imwrite("E:/imageText_R.jpg",srcImg);
#endif

	//Expand image to an optimal size, for faster processing speed
	//Set widths of borders in four directions
	//If borderType==BORDER_CONSTANT, fill the borders with (0,0,0)
	Mat padded;
	int opWidth = getOptimalDFTSize(srcImg.rows);
	int opHeight = getOptimalDFTSize(srcImg.cols);
	copyMakeBorder(srcImg, padded, 0, opWidth - srcImg.rows, 0, opHeight - srcImg.cols, BORDER_CONSTANT, Scalar::all(0));

	Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
	Mat comImg;
	//Merge into a double-channel image
	merge(planes, 2, comImg);

	//Use the same image as input and output,
	//so that the results can fit in Mat well
	dft(comImg, comImg);

	//Compute the magnitude
	//planes[0]=Re(DFT(I)), planes[1]=Im(DFT(I))
	//magnitude=sqrt(Re^2+Im^2)
	split(comImg, planes);
	magnitude(planes[0], planes[1], planes[0]);

	//Switch to logarithmic scale, for better visual results
	//M2=log(1+M1)
	Mat magMat = planes[0];
	magMat += Scalar::all(1);
	log(magMat, magMat);

	//Crop the spectrum
	//Width and height of magMat should be even, so that they can be divided by 2
	//-2 is 11111110 in binary system, operator & make sure width and height are always even
	magMat = magMat(Rect(0, 0, magMat.cols & -2, magMat.rows & -2));

	//Rearrange the quadrants of Fourier image,
	//so that the origin is at the center of image,
	//and move the high frequency to the corners
	int cx = magMat.cols / 2;
	int cy = magMat.rows / 2;

	Mat q0(magMat, Rect(0, 0, cx, cy));
	Mat q1(magMat, Rect(0, cy, cx, cy));
	Mat q2(magMat, Rect(cx, cy, cx, cy));
	Mat q3(magMat, Rect(cx, 0, cx, cy));

	Mat tmp;
	q0.copyTo(tmp);
	q2.copyTo(q0);
	tmp.copyTo(q2);

	q1.copyTo(tmp);
	q3.copyTo(q1);
	tmp.copyTo(q3);

	//Normalize the magnitude to [0,1], then to[0,255]
	normalize(magMat, magMat, 0, 1, CV_MINMAX);
	Mat magImg(magMat.size(), CV_8UC1);
	magMat.convertTo(magImg, CV_8UC1, 255, 0);
	//imshow("magnitude", magImg);
	//imwrite("imageText_mag.jpg",magImg);



	//Turn into binary image
	threshold(magImg, magImg, GRAY_THRESH, 255, CV_THRESH_BINARY);
	//imshow("mag_binary", magImg);
	//imwrite("E:/imageText_bin.jpg",magImg);

	//Find lines with Hough Transformation
	vector<Vec2f> lines(999999);
	float pi180 = (float)CV_PI / 180;
	Mat linImg(magImg.size(), CV_8UC3);
	HoughLines(magImg, lines, 1, pi180, HOUGH_VOTE, 0, 0);

	int numLines = lines.size();
	cout << numLines << endl;
	for (int l = 0; l<numLines; l++)
	{
		float rho = lines[l][0], theta = lines[l][1];
		Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a*rho, y0 = b*rho;
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * (a));
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * (a));
		line(linImg, pt1, pt2, Scalar(255, 0, 0), 3, 8, 0);
	}
	//imshow("lines", linImg);
	//imwrite("imageText_line.jpg",linImg);




	if (lines.size() == 3) {
		cout << "found three angels:" << endl;
		cout << lines[0][1] * 180 / CV_PI << endl << lines[1][1] * 180 / CV_PI << endl << lines[2][1] * 180 / CV_PI << endl << endl;
	}

	//Find the proper angel from the three found angels
	float angel = 0;
	float piThresh = (float)CV_PI / 90;
	float pi2 = CV_PI / 2;
	for (int l = 0; l<numLines; l++)
	{
		float theta = lines[l][1];
		if (abs(theta) < piThresh || abs(theta - pi2) < piThresh)
			continue;
		else {
			angel = theta;
			break;
		}
	}

	//Calculate the rotation angel
	//The image has to be square,
	//so that the rotation angel can be calculate right
	angel = angel<pi2 ? angel : angel - CV_PI;
	if (angel != pi2) {
		float angelT = srcImg.rows*tan(angel) / srcImg.cols;
		angel = atan(angelT);
	}
	float angelD = angel * 180 / (float)CV_PI;
	cout << "the rotation angel to be applied:" << endl << angelD << endl << endl;

	//Rotate the image to recover
	Mat rotMat = getRotationMatrix2D(center, angelD, 1.0);
	Mat dstImg = Mat::ones(srcImg.size(), CV_8UC3);
	warpAffine(srcImg, dstImg, rotMat, srcImg.size(), 1, 0, Scalar(255, 255, 255));
	//imshow("result", dstImg);
	const char* outFilename = env->GetStringUTFChars(outFile,NULL);
	imwrite(outFilename,dstImg);
	return 0;
}

7.配置相关属性
这里写图片描述
这里写图片描述
这里写图片描述
8.生成解决方案,成功后会生成dll文件
这里写图片描述
9.拷贝AI.dll到项目根目录,运行调试
这里写图片描述
这里写图片描述
9435为图片经过霍夫变换检测出的直线条数

-13.2301为图片倾斜角度

0为成功返回值

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值