/**
* 解析二維碼,此方法解析一個路徑的二維碼圖片
* 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;
? ? ? }
//更換數(shù)據(jù)類型
? ? ? src_gray.convertTo(src_gray, CvType.CV_8UC1);//更換數(shù)據(jù)類型
? ? ? ? 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;
? ? ? ? ? ? ? }
//更換數(shù)據(jù)類型
? ? ? ? ? ? ? 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) {
/***
* 計算層數(shù)售躁,二維碼角框有五層輪廓(有說六層),這里不計自己這一層币他,有4個以上子輪廓則標記這一點
*/
? ? ? ? ? ? ? ? double[] ds = hierarchy.get(0, i);
? ? ? ? ? ? ? ? if (ds !=null && ds.length >3) {
int count =0;
? ? ? ? ? ? ? ? ? ? if (ds[3] == -1) {/**最外層輪廓排除*/
? ? ? ? ? ? ? ? ? ? ? ? continue;
? ? ? ? ? ? ? ? ? ? }
/***
* 計算所有子輪廓數(shù)量
*/
? ? ? ? ? ? ? ? ? ? while ((int) ds[2] != -1) {
++count;
? ? ? ? ? ? ? ? ? ? ? ? ds = hierarchy.get(0, (int) ds[2]);
? ? ? ? ? ? ? ? ? ? }
if (count >=4) {
markContours.add(contours.get(i));
? ? ? ? ? ? ? ? ? ? }
}
}
}
/***
* 二維碼有三個角輪廓配喳,少于三個的無法定位放棄,多余三個的循環(huán)裁剪出來
*/
? ? ? ? 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;
? ? }
//更換數(shù)據(jù)類型
? ? src_gray.convertTo(src_gray, CvType.CV_8UC1);//更換數(shù)據(jù)類型
? ? 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;
? ? ? ? ? ? }
//更換數(shù)據(jù)類型
? ? ? ? ? ? src_gray.convertTo(src_gray, CvType.CV_8UC1);//更換數(shù)據(jù)類型
? ? ? ? ? ? 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;
}