利用opencv解析二維碼

/**

* 解析二維碼,此方法解析一個路徑的二維碼圖片

* 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;

}

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末族淮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子凭涂,更是在濱河造成了極大的恐慌祝辣,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件切油,死亡現(xiàn)場離奇詭異蝙斜,居然都是意外死亡,警方通過查閱死者的電腦和手機澎胡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門孕荠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娩鹉,“玉大人,你說我怎么就攤上這事稚伍⊥溆瑁” “怎么了?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵个曙,是天一觀的道長锈嫩。 經(jīng)常有香客問我,道長垦搬,這世上最難降的妖魔是什么呼寸? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮猴贰,結果婚禮上对雪,老公的妹妹穿的比我還像新娘。我一直安慰自己米绕,他們只是感情好瑟捣,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著义郑,像睡著了一般蝶柿。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上非驮,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天交汤,我揣著相機與錄音,去河邊找鬼劫笙。 笑死芙扎,一個胖子當著我的面吹牛,可吹牛的內容都是我干的填大。 我是一名探鬼主播戒洼,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼允华!你這毒婦竟也來了圈浇?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤靴寂,失蹤者是張志新(化名)和其女友劉穎磷蜀,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體百炬,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡褐隆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了剖踊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庶弃。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡衫贬,死狀恐怖,靈堂內的尸體忽然破棺而出歇攻,到底是詐尸還是另有隱情固惯,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布掉伏,位于F島的核電站缝呕,受9級特大地震影響,放射性物質發(fā)生泄漏斧散。R本人自食惡果不足惜供常,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鸡捐。 院中可真熱鬧栈暇,春花似錦、人聲如沸箍镜。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽色迂。三九已至香缺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間歇僧,已是汗流浹背图张。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诈悍,地道東北人祸轮。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像侥钳,于是被迫代替她去往敵國和親适袜。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345