/**
* 解析二维码,此方法解析一个路径的二维码图片
* path:图片路径
*/
public static String deEncodeImgByPath(File file) {
try {
// 开始转换图片
Image image = ImageIO.read(file);
int srcH = image.getHeight(null);
int srcW = image.getWidth(null);
BufferedImage bufferedImage =new BufferedImage(srcW, srcH,BufferedImage.TYPE_3BYTE_BGR);
bufferedImage.getGraphics().drawImage(image, 0,0, srcW, srcH, null);
bufferedImage=new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY),null).filter (bufferedImage,null);
FileOutputStream fos =new FileOutputStream(file);
ImageIO.write(bufferedImage,"jpg", fos);
fos.close();
}catch (IOException e) {
e.printStackTrace();
throw new IllegalStateException("图片转换出错!", e);
}
String content =null;
BufferedImage bimage;
try {
// 开始最基本解码
bimage = ImageIO.read(file);
LuminanceSource source =new BufferedImageLuminanceSource(bimage);
Binarizer binarizer =new HybridBinarizer(source);
BinaryBitmap binaryBitmap =new BinaryBitmap(binarizer);
Map hints =new HashMap();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result =new MultiFormatReader().decode(binaryBitmap, hints);//解码
System.out.println("content: " + result.getText()+","+result.getText().length());
if(result.getText().length()<16){
content = getCvtColorQrcode(file);
}else{
content = result.getText();
}
}catch (IOException e) {
e.printStackTrace();
}catch (NotFoundException e) {
// 基本解码不可行后,使用opencv解码,将图片进行灰度处理并进行裁剪
Mat src = Imgcodecs.imread(file.toString());
Mat src_gray =new Mat();
if(src.channels()>1){
Imgproc.cvtColor(src,src_gray,Imgproc.COLOR_BGR2GRAY); //转为灰度图
Imgproc.GaussianBlur(src_gray, src_gray, new Size(3,3), 0,0);
}else{
src_gray = src;
}
//更换数据类型
src_gray.convertTo(src_gray, CvType.CV_8UC1);//更换数据类型
try {
// 进行裁剪
test1(src,src_gray,file);
bimage = ImageIO.read(file);
LuminanceSource source =new BufferedImageLuminanceSource(bimage);
Binarizer binarizer =new HybridBinarizer(source);
BinaryBitmap binaryBitmap =new BinaryBitmap(binarizer);
Map hints =new HashMap();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result =new MultiFormatReader().decode(binaryBitmap, hints);//解码
System.out.println("content: " + result.getText());
content = result.getText();
}catch (Exception e3){
try {
// 若灰度不可行则再进行灰度和二值化处理
if(src.channels()>1){
Imgproc.cvtColor(src,src_gray,Imgproc.COLOR_BGR2GRAY); //转为灰度图
Imgproc.GaussianBlur(src_gray, src_gray, new Size(3,3), 0,0);
}else{
src_gray = src;
}
//更换数据类型
src_gray.convertTo(src_gray, CvType.CV_8UC1);
Mat binarySrc=new Mat();
//二值化
int blockSize = src.rows()/8;
if(blockSize%2==0){
blockSize++;
}
Imgproc.adaptiveThreshold(src_gray,binarySrc,255,Imgproc.ADAPTIVE_THRESH_MEAN_C,Imgproc.THRESH_BINARY,blockSize,10);
Imgcodecs.imwrite(file.toString(), binarySrc);
bimage = ImageIO.read(file);
LuminanceSource source =new BufferedImageLuminanceSource(bimage);
Binarizer binarizer =new HybridBinarizer(source);
BinaryBitmap binaryBitmap =new BinaryBitmap(binarizer);
Map hints =new HashMap();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result =new MultiFormatReader().decode(binaryBitmap, hints);//解码
System.out.println("content: " + result.getText());
content = result.getText();
}catch (IOException e1) {
e1.printStackTrace();
}catch (NotFoundException e2) {
e2.printStackTrace();
}catch (Exception e2) {
e2.printStackTrace();
}
}
}
return content;
}
//得到裁剪处理后的图片
public static void test1(Mat src, Mat src_gray,File file){
List contours =new ArrayList();
List markContours =new ArrayList();
//System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
/**图片太小就放大**/
if (src.width()*src.height()<90000){
Imgproc.resize(src,src,new Size(800,600));
}
BufferedImage bimage;
try {
bimage = ImageIO.read(file);
Imgproc.Canny(src_gray, src_gray, 112, 255);
Mat hierarchy =new Mat();
Imgproc.findContours(src_gray, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_NONE);
for (int i =0; i < contours.size(); i++) {
MatOfPoint2f newMtx =new MatOfPoint2f(contours.get(i).toArray());
RotatedRect rotRect = Imgproc.minAreaRect(newMtx);
double w = rotRect.size.width;
double h = rotRect.size.height;
double rate = Math.max(w, h) / Math.min(w, h);
/***
* 长短轴比小于1.3,总面积大于60
*/
if (rate <1.3 && w < src_gray.cols() /4 && h < src_gray.rows() /4 && Imgproc.contourArea(contours.get(i)) >60) {
/***
* 计算层数,二维码角框有五层轮廓(有说六层),这里不计自己这一层,有4个以上子轮廓则标记这一点
*/
double[] ds = hierarchy.get(0, i);
if (ds !=null && ds.length >3) {
int count =0;
if (ds[3] == -1) {/**最外层轮廓排除*/
continue;
}
/***
* 计算所有子轮廓数量
*/
while ((int) ds[2] != -1) {
++count;
ds = hierarchy.get(0, (int) ds[2]);
}
if (count >=4) {
markContours.add(contours.get(i));
}
}
}
}
/***
* 二维码有三个角轮廓,少于三个的无法定位放弃,多余三个的循环裁剪出来
*/
int[] ii = {};
int[] ii2 = {};
if (markContours.size() <3) {
return;
}else {
for (int i =0; i < markContours.size() -2; i++) {
List threePointList =new ArrayList<>();
for (int j = i +1; j < markContours.size() -1; j++) {
for (int k = j +1; k < markContours.size(); k++) {
threePointList.add(markContours.get(i));
threePointList.add(markContours.get(j));
threePointList.add(markContours.get(k));
ii =capture(threePointList, bimage, file);
threePointList.clear();
if (ii[1] == ii[3] && ii[0] != ii[2]) {
ii2 = ii.clone();
break;
}else
continue;
}
}
}
}
BufferedImage bimage2 =cropImage(bimage, ii2[0] /2, ii2[3] -50, ii2[2] + (ii2[0] /2), (ii2[3] + ii2[2] - ii2[0] +100));
FileOutputStream fos =new FileOutputStream(file);
ImageIO.write(bimage2, "jpg", fos);
fos.close();
}catch (Exception e){
e.printStackTrace();
}
}
//读取坐标
public static int[]capture(List contours, BufferedImage image, File file)throws IOException{
Point[] pointthree =new Point[3];
for(int i=0; i
{
pointthree[i] =centerCal(contours.get(i));
}
int x,y,ex,ey;
double[] ca =new double[2];
if(pointthree[1].x>pointthree[2].x) {
ex = (int) pointthree[1].x;
x = (int) pointthree[2].x;
}else{
x = (int) pointthree[1].x;
ex = (int) pointthree[2].x;
}
if(pointthree[1].y>pointthree[2].y){
ey=(int)pointthree[1].y;
y=(int)pointthree[2].y;
}
else{
y=(int)pointthree[1].y;
ey=(int)pointthree[2].y;
}
int[] xy={x,y,ex,ey};
return xy;
}
//裁剪
public static BufferedImagecropImage(BufferedImage bufferedImage,int startX,int startY,int endX,int endY) {
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
startX=startX-10;
endX = endX+10;
endY = endY;
BufferedImage result =new BufferedImage(endX - startX, endY - startY, 4);
for (int x = startX; x < endX; ++x) {
for (int y = startY; y < endY; ++y) {
int rgb = bufferedImage.getRGB(x, y);
result.setRGB(x - startX, y - startY, rgb);
}
}
return result;
}
public static PointcenterCal(MatOfPoint matOfPoint){
double centerx=0,centery=0;
int size = matOfPoint.cols();
MatOfPoint2f mat2f =new MatOfPoint2f( matOfPoint.toArray() );
RotatedRect rect = Imgproc.minAreaRect( mat2f );
Point vertices[] =new Point[4];
rect.points(vertices);
centerx = ((vertices[0].x + vertices[1].x)/2 + (vertices[2].x + vertices[3].x)/2)/2;
centery = ((vertices[0].y + vertices[1].y)/2 + (vertices[2].y + vertices[3].y)/2)/2;
Point point=new Point(centerx,centery);
return point;
}
public static String getCvtColorQrcode(File file){
Mat src = Imgcodecs.imread(file.toString());
Mat src_gray =new Mat();
if(src.channels()>1){
Imgproc.cvtColor(src,src_gray,Imgproc.COLOR_BGR2GRAY); //转为灰度图
Imgproc.GaussianBlur(src_gray, src_gray, new Size(3,3), 0,0);
}else{
src_gray = src;
}
//更换数据类型
src_gray.convertTo(src_gray, CvType.CV_8UC1);//更换数据类型
String content =null;
BufferedImage bimage;
try {
if(src.channels()>1){
Imgproc.cvtColor(src,src_gray,Imgproc.COLOR_BGR2GRAY); //转为灰度图
Imgproc.GaussianBlur(src_gray, src_gray, new Size(3,3), 0,0);
}else{
src_gray = src;
}
//更换数据类型
src_gray.convertTo(src_gray, CvType.CV_8UC1);//更换数据类型
Mat binarySrc=new Mat();
//二值化
int blockSize = src.rows()/8;
if(blockSize%2==0){
blockSize++;
}
Imgproc.adaptiveThreshold(src_gray,binarySrc,255,Imgproc.ADAPTIVE_THRESH_MEAN_C,Imgproc.THRESH_BINARY,blockSize,10);
Imgcodecs.imwrite(file.toString(), binarySrc);
bimage = ImageIO.read(file);
LuminanceSource source =new BufferedImageLuminanceSource(bimage);
Binarizer binarizer =new HybridBinarizer(source);
BinaryBitmap binaryBitmap =new BinaryBitmap(binarizer);
Map hints =new HashMap();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
Result result =new MultiFormatReader().decode(binaryBitmap, hints);//解码
System.out.println("content: " + result.getText());
content = result.getText();
}catch (IOException e1) {
e1.printStackTrace();
}catch (NotFoundException e2) {
e2.printStackTrace();
}catch (Exception e2) {
e2.printStackTrace();
}
return content;
}