|
|
package com.utils;
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
import java.io.InputStreamReader;
|
|
|
import java.net.HttpURLConnection;
|
|
|
import java.net.URL;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
|
|
|
import org.json.JSONArray;
|
|
|
import org.json.JSONObject;
|
|
|
|
|
|
import com.baidu.aip.ocr.AipOcr;
|
|
|
import com.baidu.aip.imageclassify.AipImageClassify;
|
|
|
|
|
|
/**
|
|
|
* 百度AI服务工具类
|
|
|
*
|
|
|
* 核心职责:集成百度地图和百度AI的各项服务功能
|
|
|
*
|
|
|
* 功能模块:
|
|
|
* 1. 百度地图 - 逆地理编码服务
|
|
|
* 2. 百度AI - OCR文字识别
|
|
|
* 3. 百度AI - 图像识别(动物、菜品、植物)
|
|
|
* 4. 百度AI - 访问令牌管理
|
|
|
*
|
|
|
* 技术特点:
|
|
|
* - 基于百度AI Java SDK
|
|
|
* - 支持多种AI能力调用
|
|
|
* - 提供统一的服务接口
|
|
|
*
|
|
|
* 使用场景:
|
|
|
* - 地理位置解析
|
|
|
* - 图片文字识别
|
|
|
* - 图像内容识别
|
|
|
* - AI能力集成
|
|
|
*/
|
|
|
public class BaiduUtil {
|
|
|
|
|
|
// 百度AI应用配置(示例配置,实际使用时应从配置文件中读取)
|
|
|
public static final String APP_ID = "29917330";
|
|
|
public static final String API_KEY = "yMnHy1guHZRzGhXB7BILdktB";
|
|
|
public static final String SECRET_KEY = "1oHG8X0yizyZmIwj3bZygG470b648iE1";
|
|
|
|
|
|
// OCR客户端单例
|
|
|
private static AipOcr ocrClient = null;
|
|
|
|
|
|
/**
|
|
|
* 根据经纬度获取省市区信息(逆地理编码)
|
|
|
* 使用百度地图API将经纬度坐标转换为具体地址信息
|
|
|
*
|
|
|
* @param key 百度地图API Key
|
|
|
* @param lng 经度
|
|
|
* @param lat 纬度
|
|
|
* @return 包含省市区街道信息的Map,解析失败返回null
|
|
|
*/
|
|
|
public static Map<String, String> getCityByLonLat(String key, String lng, String lat) {
|
|
|
String location = lat + "," + lng;
|
|
|
try {
|
|
|
// 拼装百度逆地理编码API URL
|
|
|
String url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak=" + key
|
|
|
+ "&output=json&coordtype=wgs84ll&location=" + location;
|
|
|
|
|
|
// 发送HTTP GET请求
|
|
|
String result = HttpClientUtils.doGet(url);
|
|
|
JSONObject o = new JSONObject(result);
|
|
|
|
|
|
// 解析返回的地址组件信息
|
|
|
Map<String, String> area = new HashMap<>();
|
|
|
JSONObject addressComponent = o.getJSONObject("result").getJSONObject("addressComponent");
|
|
|
|
|
|
area.put("province", addressComponent.getString("province")); // 省份
|
|
|
area.put("city", addressComponent.getString("city")); // 城市
|
|
|
area.put("district", addressComponent.getString("district")); // 区县
|
|
|
area.put("street", addressComponent.getString("street")); // 街道
|
|
|
|
|
|
return area;
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取百度AI访问令牌
|
|
|
* 该token有一定的有效期,需要自行管理,当失效时需重新获取
|
|
|
*
|
|
|
* @param ak 百度云官网获取的 API Key
|
|
|
* @param sk 百度云官网获取的 Secret Key
|
|
|
* @return access_token 访问令牌
|
|
|
*/
|
|
|
public static String getAuth(String ak, String sk) {
|
|
|
// 获取token地址
|
|
|
String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
|
|
|
String getAccessTokenUrl = authHost
|
|
|
// 1. grant_type为固定参数
|
|
|
+ "grant_type=client_credentials"
|
|
|
// 2. 官网获取的 API Key
|
|
|
+ "&client_id=" + ak
|
|
|
// 3. 官网获取的 Secret Key
|
|
|
+ "&client_secret=" + sk;
|
|
|
|
|
|
try {
|
|
|
URL realUrl = new URL(getAccessTokenUrl);
|
|
|
// 打开和URL之间的连接
|
|
|
HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
|
|
|
connection.setRequestMethod("GET");
|
|
|
connection.connect();
|
|
|
|
|
|
// 获取所有响应头字段(用于调试)
|
|
|
Map<String, List<String>> map = connection.getHeaderFields();
|
|
|
// 遍历所有的响应头字段
|
|
|
for (String key : map.keySet()) {
|
|
|
System.err.println(key + "--->" + map.get(key));
|
|
|
}
|
|
|
|
|
|
// 定义 BufferedReader输入流来读取URL的响应
|
|
|
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
|
|
String result = "";
|
|
|
String line;
|
|
|
while ((line = in.readLine()) != null) {
|
|
|
result += line;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 返回结果示例:
|
|
|
* {
|
|
|
* "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
|
|
|
* "expires_in": 2592000
|
|
|
* }
|
|
|
*/
|
|
|
System.err.println("result:" + result);
|
|
|
org.json.JSONObject jsonObject = new org.json.JSONObject(result);
|
|
|
String access_token = jsonObject.getString("access_token");
|
|
|
return access_token;
|
|
|
|
|
|
} catch (Exception e) {
|
|
|
System.err.printf("获取token失败!");
|
|
|
e.printStackTrace(System.err);
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 识别图片上的文本内容,转换成文字字符串返回
|
|
|
* 使用百度OCR高精度文字识别接口
|
|
|
*
|
|
|
* @param imagePath 图片文件的路径
|
|
|
* @param isNewline 是否保留换行符(true:每行文字后加换行符,false:所有文字连续)
|
|
|
* @return 识别出的文字字符串,识别失败返回null
|
|
|
*/
|
|
|
public static String generalString(String imagePath, boolean isNewline) {
|
|
|
try {
|
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
|
|
options.put("language_type", "CHN_ENG"); // CHN_ENG:中英文混合, ENG:英文
|
|
|
options.put("detect_direction", "true"); // 是否检测图像朝向,默认不检测
|
|
|
options.put("detect_language", "true"); // 是否检测语言,默认不检测
|
|
|
options.put("probability", "false"); // 是否返回识别结果中每一行的置信度
|
|
|
|
|
|
// 初始化OCR客户端(单例模式)
|
|
|
if (ocrClient == null) {
|
|
|
ocrClient = new AipOcr(APP_ID, API_KEY, SECRET_KEY);
|
|
|
// 设置连接超时和读取超时
|
|
|
ocrClient.setConnectionTimeoutInMillis(5000); // 连接超时5秒
|
|
|
ocrClient.setSocketTimeoutInMillis(60000); // 读取超时60秒
|
|
|
}
|
|
|
|
|
|
// 调用通用文字识别(高精度版)接口
|
|
|
JSONObject jsonObject = ocrClient.basicAccurateGeneral(imagePath, options);
|
|
|
String result = mergeString(jsonObject, isNewline);
|
|
|
return result;
|
|
|
|
|
|
} catch (Exception ex) {
|
|
|
ex.printStackTrace();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 合并OCR识别结果
|
|
|
* 将JSON格式的识别结果合并为字符串
|
|
|
*
|
|
|
* @param jsonObject OCR识别返回的JSON对象
|
|
|
* @param isNewline 是否保留换行符
|
|
|
* @return 合并后的字符串
|
|
|
*/
|
|
|
private static String mergeString(JSONObject jsonObject, boolean isNewline) {
|
|
|
if (jsonObject == null) {
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
// 检查是否包含识别结果
|
|
|
if (jsonObject.has("words_result") && jsonObject.has("words_result_num")) {
|
|
|
int wordsResultNum = jsonObject.getInt("words_result_num");
|
|
|
if (wordsResultNum > 0) {
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
JSONArray jsonArray = jsonObject.getJSONArray("words_result");
|
|
|
int len = jsonArray.length();
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
JSONObject obj = (JSONObject) jsonArray.get(i);
|
|
|
if (isNewline) {
|
|
|
sb.append(obj.get("words") + "\n"); // 每行文字后加换行符
|
|
|
} else {
|
|
|
sb.append(obj.get("words")); // 所有文字连续
|
|
|
}
|
|
|
}
|
|
|
return sb.toString();
|
|
|
}
|
|
|
} else {
|
|
|
// 如果没有识别结果,返回原始JSON字符串
|
|
|
return jsonObject.toString();
|
|
|
}
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 动物识别
|
|
|
* 识别图片中的动物种类
|
|
|
*
|
|
|
* @param imgPath 图片路径
|
|
|
* @return 识别结果的JSON对象
|
|
|
*/
|
|
|
public static JSONObject animalDetect(String imgPath) {
|
|
|
// 初始化图像分类客户端
|
|
|
AipImageClassify aic = new AipImageClassify(APP_ID, API_KEY, SECRET_KEY);
|
|
|
|
|
|
// 设置请求参数
|
|
|
HashMap<String, String> params = new HashMap<String, String>();
|
|
|
params.put("baike_num", "1"); // 返回百科信息的数量
|
|
|
|
|
|
// 调用动物识别接口
|
|
|
JSONObject res = aic.animalDetect(imgPath, params);
|
|
|
System.out.println(res.toString(2)); // 格式化输出结果
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 菜品识别
|
|
|
* 识别图片中的菜品类型
|
|
|
*
|
|
|
* @param imgPath 图片路径
|
|
|
* @return 识别结果的JSON对象
|
|
|
*/
|
|
|
public static JSONObject dishDetect(String imgPath) {
|
|
|
// 初始化图像分类客户端
|
|
|
AipImageClassify aic = new AipImageClassify(APP_ID, API_KEY, SECRET_KEY);
|
|
|
|
|
|
// 设置请求参数
|
|
|
HashMap<String, String> params = new HashMap<String, String>();
|
|
|
params.put("baike_num", "1"); // 返回百科信息的数量
|
|
|
|
|
|
// 调用菜品识别接口
|
|
|
JSONObject res = aic.dishDetect(imgPath, params);
|
|
|
System.out.println(res.toString(2)); // 格式化输出结果
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 植物识别
|
|
|
* 识别图片中的植物种类
|
|
|
*
|
|
|
* @param imgPath 图片路径
|
|
|
* @return 识别结果的JSON对象
|
|
|
*/
|
|
|
public static JSONObject plantDetect(String imgPath) {
|
|
|
// 初始化图像分类客户端
|
|
|
AipImageClassify aic = new AipImageClassify(APP_ID, API_KEY, SECRET_KEY);
|
|
|
|
|
|
// 设置请求参数
|
|
|
HashMap<String, String> params = new HashMap<String, String>();
|
|
|
params.put("baike_num", "1"); // 返回百科信息的数量
|
|
|
|
|
|
// 调用植物识别接口
|
|
|
JSONObject res = aic.plantDetect(imgPath, params);
|
|
|
System.out.println(res.toString(2)); // 格式化输出结果
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
// 可以添加的增强方法:
|
|
|
|
|
|
/**
|
|
|
* 通用物体识别
|
|
|
* 识别图片中的通用物体
|
|
|
*
|
|
|
* @param imgPath 图片路径
|
|
|
* @return 识别结果的JSON对象
|
|
|
*/
|
|
|
public static JSONObject advancedGeneral(String imgPath) {
|
|
|
AipImageClassify aic = new AipImageClassify(APP_ID, API_KEY, SECRET_KEY);
|
|
|
JSONObject res = aic.advancedGeneral(imgPath, new HashMap<String, String>());
|
|
|
System.out.println(res.toString(2));
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 身份证识别
|
|
|
* 识别身份证图片上的信息
|
|
|
*
|
|
|
* @param imgPath 身份证图片路径
|
|
|
* @param idCardSide 身份证正反面(front:正面, back:反面)
|
|
|
* @return 识别结果的JSON对象
|
|
|
*/
|
|
|
public static JSONObject idcard(String imgPath, String idCardSide) {
|
|
|
if (ocrClient == null) {
|
|
|
ocrClient = new AipOcr(APP_ID, API_KEY, SECRET_KEY);
|
|
|
}
|
|
|
|
|
|
HashMap<String, String> options = new HashMap<String, String>();
|
|
|
options.put("detect_direction", "true");
|
|
|
options.put("detect_risk", "false");
|
|
|
|
|
|
JSONObject res = ocrClient.idcard(imgPath, idCardSide, options);
|
|
|
return res;
|
|
|
}
|
|
|
} |