You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
12 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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