Java语言代码
1、toTrimRotateImg
private Mat toTrimRotateImg(Mat srcImage) {
try {
if (ScanManageController.correct2 != 0) {
FileUtil.getMemory("toTrimRotateImg-调整旋转角度开始==》");
srcImage = ImageHelper.RotateNew_bak(srcImage, ScanManageController.correct2);
FileUtil.getMemory("toTrimRotateImg-调整旋转角度结束!");
}
if (ScanManageController.correct != 0) {
FileUtil.getMemory("toTrimRotateImg-调整旋转角度开始==》");
srcImage = ImageHelper.RotateNew(srcImage, ScanManageController.correct);
FileUtil.getMemory("toTrimRotateImg-调整旋转角度结束!");
}
} catch (Exception e) {
e.printStackTrace();
}
return srcImage;
}
2、ImageHelper类
package com.cxbdapp.cadre.util;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.imgproc.Imgproc;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import static org.opencv.core.Core.BORDER_CONSTANT;
public class ImageHelper {
public static Mat RotateNew(Mat srcMat, double angel) {
Mat dst = srcMat.clone();
Point center = new Point(srcMat.width()/2.0,srcMat.height()/2.0);
Mat mat1 = Imgproc.getRotationMatrix2D(center, angel, 1.0);
Imgproc.warpAffine(srcMat,dst,mat1,dst.size(),Imgproc.INTER_NEAREST,BORDER_CONSTANT,new Scalar(255,255,255));
mat1 = null;
center = null;
return dst;
}
public static Mat RotateNew_bak(Mat srcMat, double angel) {
BufferedImage src = ImageDeskew.mat2BufferedImage(srcMat);
int src_width = src.getWidth(null);
int src_height = src.getHeight(null);
Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(src_width, src_height)), (int) angel);
BufferedImage res = null;
res = new BufferedImage(rect_des.width, rect_des.height, src.getType());
Graphics2D g2 = res.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, rect_des.width, rect_des.height);
g2.translate((rect_des.width - src_width) / 2, (rect_des.height - src_height) / 2);
g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
g2.drawImage(src, null, null);
g2.dispose();
byte[] pixels = ( (DataBufferByte) res.getRaster().getDataBuffer()).getData();
Mat I = new Mat(res.getHeight(), res.getWidth(), CvType.CV_8UC3);
I.put(0, 0, pixels);
g2 = null;
src = null;
rect_des = null;
res = null;
return I;
}
public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
if (angel >= 90) {
if (angel / 90 % 2 == 1) {
int temp = src.height;
src.height = src.width;
src.width = temp;
}
angel = angel % 90;
}
double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
double angel_dalta_width = Math.atan((double) src.height / src.width);
double angel_dalta_height = Math.atan((double) src.width / src.height);
int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
- angel_dalta_width));
int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
- angel_dalta_height));
int des_width = src.width + len_dalta_width * 2;
int des_height = src.height + len_dalta_height * 2;
return new Rectangle(new Dimension(des_width, des_height));
}
}
3、ImageDeskew类
package com.cxbdapp.cadre.util;
import org.opencv.core.Mat;
import java.awt.image.BufferedImage;
public class ImageDeskew {
public static BufferedImage mat2BufferedImage(Mat mat) {
int cols = mat.cols();
int rows = mat.rows();
int elemSize = (int) mat.elemSize();
byte[] data = new byte[cols * rows * elemSize];
int type;
mat.get(0, 0, data);
switch (mat.channels()) {
case 1:
type = BufferedImage.TYPE_BYTE_GRAY;
break;
case 3:
type = BufferedImage.TYPE_3BYTE_BGR;
byte b;
for (int i = 0; i < data.length; i = i + 3) {
b = data[i];
data[i] = data[i + 2];
data[i + 2] = b;
}
break;
default:
return null;
}
BufferedImage image = new BufferedImage(cols, rows, type);
image.getRaster().setDataElements(0, 0, cols, rows, data);
return image;
}
}
C语言代码
1、effect.cpp中
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <opencv2/opencv.hpp>
#include <QDir>
#include <QFile>
#include <QPainter>
#include "effect.h"
#include "src/utils/utils.h"
static const double PI = 3.14159265358979323846;
static double toRadians(double degrees) {
return degrees * PI / 180;
}
void Effect::RotateZoom(_RotateZoom *rotate, Mat &dst)
{
dst = m_src.clone();
if (rotate->noloss_angle != 0) {
printLog("======无损偏转开始======");
int noloss_angle = rotate->noloss_angle;
if (noloss_angle >= 360) {
noloss_angle = noloss_angle - 360;
}
if (noloss_angle < 0) {
noloss_angle = 360 + noloss_angle;
}
QPixmap pixmap = rotatePic(Mat2Pixmap(m_src), noloss_angle);
QString firDir;
firDir = "C:\\SCANFILES";
if (!QFile::exists(firDir))
{
QDir dir;
dir.mkdir(firDir);
}
QString fileName = "C:\\SCANFILES\\targetPixmap.jpg";
pixmap.save(fileName);
dst = imread(ws2s(fileName.toStdWString()));
printLog("======无损偏转结束======");
}
if (rotate->angle != 0) {
printLog("======正常偏转开始======");
int angle = - (rotate->angle);
int width=m_src.cols, height=m_src.rows;
if (rotate->noloss_angle != 0) {
width=dst.cols;
height=dst.rows;
}
Mat M = Mat(2, 3, CV_32FC1);
M = getRotationMatrix2D(Point(width/2,height/2),angle,rotate->scale);
M.at<double>(0,2) += rotate->x*width;
M.at<double>(1,2) += rotate->y*height;
if (rotate->noloss_angle != 0) {
warpAffine(dst,dst,M,Size(width,height),INTER_LINEAR,BORDER_CONSTANT,Scalar(255,255,255));
} else {
warpAffine(m_src,dst,M,Size(width,height),INTER_LINEAR,BORDER_CONSTANT,Scalar(255,255,255));
}
printLog("======正常偏转结束======");
} else {
if (rotate->scale != 1.0) {
rotate = new _RotateZoom(0,0,0,0,0,0,rotate->scale,false);
int width = dst.cols, height = dst.rows;
Mat M = Mat(2, 3, CV_32FC1);
M = getRotationMatrix2D(Point(width/2,height/2),rotate->angle,rotate->scale);
M.at<double>(0,2) += rotate->x*width;
M.at<double>(1,2) += rotate->y*height;
warpAffine(dst,dst,M,Size(width,height),INTER_LINEAR,BORDER_CONSTANT,Scalar(255,255,255));
}
}
}
QPixmap Effect::rotatePic(QPixmap srcPixmap, int angle)
{
printLog("无损偏转算法函数 Effect::rotatePic angle=" + QString::number(angle));
int src_width = srcPixmap.width();
int src_height = srcPixmap.height();
QRect targetRect;
QRect sourceRect(0,0,srcPixmap.width(), srcPixmap.height());
printLog("计算旋转后图片的尺寸");
targetRect = calcRotatedSize(sourceRect, angle);
QPixmap targetPixmap(targetRect.width(), targetRect.height());
QPainter p(&targetPixmap);
printLog("设置渲染,启动反锯齿(即反走样。反走样的效果其实比不走样要好得多,反走样是一种比较复杂的算法,在一些对图像质量要求不高的应用中,是不需要进行反走样的。为了提高效率,一般的图形绘制系统,如Java2D、OpenGL之类都是默认不进行反走样的。)");
p.setRenderHint(QPainter::Antialiasing, true);
printLog("对指定的矩形区域填充颜色");
p.fillRect(0, 0, targetRect.width(), targetRect.height(), Qt::white);
printLog("进行转换");
p.translate(targetRect.width() / 2, targetRect.height() / 2);
printLog("进行旋转");
p.rotate(angle);
printLog("绘制图形");
p.drawPixmap(-src_width/2, -src_height/2, srcPixmap);
return targetPixmap.scaled(src_width, src_height);
}
QRect Effect::calcRotatedSize(QRect sourceRect, int angle)
{
printLog("1计算旋转后图片的尺寸:(" + QString::number(sourceRect.x()) + ", " + QString::number(sourceRect.y()) + ", " + QString::number(sourceRect.width()) + ", " + QString::number(sourceRect.height()) + ")");
if (angle >= 90) {
if (angle / 90 % 2 == 1) {
int temp = sourceRect.height();
sourceRect.setHeight(sourceRect.width());
sourceRect.setWidth(temp);
}
angle = angle % 90;
}
double r = sqrt(sourceRect.height() * sourceRect.height() + sourceRect.width() * sourceRect.width()) / 2;
double len = 2 * sin(toRadians(angle) / 2) * r;
double angle_alpha = (PI - toRadians(angle)) / 2;
double angle_dalta_width = atan((double) sourceRect.height() / sourceRect.width());
double angle_dalta_height = atan((double) sourceRect.width() / sourceRect.height());
int len_dalta_width = (int) (len * cos(PI - angle_alpha - angle_dalta_width));
int len_dalta_height = (int) (len * cos(PI - angle_alpha - angle_dalta_height));
int des_width = sourceRect.width() + len_dalta_width * 2;
int des_height = sourceRect.height() + len_dalta_height * 2;
QPoint topleft, bottomright;
topleft.setX(0);
topleft.setY(0);
bottomright.setX(des_width);
bottomright.setY(des_height);
QRect rect(topleft, bottomright);
printLog("2计算旋转后图片的尺寸:(" + QString::number(rect.x()) + ", " + QString::number(rect.y()) + ", " + QString::number(rect.width()) + ", " + QString::number(rect.height()) + ")");
return rect;
}
2、effect.h中
#ifndef EFFECT_H
#define EFFECT_H
#include "src/utils/types.h"
#include <opencv2/core/core.hpp>
#include <QImage>
using namespace cv;
class Effect
{
public:
Effect(void);
~Effect(void);
public:
void RotateZoom(_RotateZoom *rotate, cv::Mat &dst);
QPixmap rotatePic(QPixmap srcPixmap, int angle);
QRect calcRotatedSize(QRect sourceRect, int angle);
private:
cv::Mat m_src;
};
#endif