本文目录导读:

在Java中实现物品识别,通常有几种不同层面的方法,取决于你的应用场景、性能需求和硬件环境,以下是几种主流方案,从简单到复杂:
使用第三方云服务API(最简单,推荐入门)
这是最快的方案,不需要训练模型,直接调用接口:
阿里云物品识别
import com.aliyun.imagesearch20201214.Client;
import com.aliyun.imagesearch20201214.models.*;
import com.aliyun.teaopenapi.models.Config;
public class AliyunItemRecognition {
public static void main(String[] args) throws Exception {
// 创建客户端
Config config = new Config()
.setAccessKeyId("your-access-key-id")
.setAccessKeySecret("your-access-key-secret");
config.setEndpoint("imagesearch.ap-southeast-1.aliyuncs.com");
Client client = new Client(config);
// 创建请求
SearchImageByNameRequest request = new SearchImageByNameRequest()
.setInstanceName("your-instance-name")
.setProductId("your-product-id")
.setPicName("your-pic-name");
SearchImageByNameResponse response = client.searchImageByName(request);
System.out.println(response.getBody());
}
}
Google Cloud Vision API
import com.google.cloud.vision.v1.*;
import com.google.protobuf.ByteString;
import java.nio.file.Files;
import java.nio.file.Paths;
public class GoogleVisionItemRecognition {
public static void main(String[] args) throws Exception {
try (ImageAnnotatorClient vision = ImageAnnotatorClient.create()) {
// 读取图片
byte[] data = Files.readAllBytes(Paths.get("path/to/image.jpg"));
ByteString imgBytes = ByteString.copyFrom(data);
// 构建请求
Image img = Image.newBuilder().setContent(imgBytes).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.LABEL_DETECTION).build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder()
.addFeatures(feat)
.setImage(img)
.build();
// 调用API
BatchAnnotateImagesResponse response = vision.batchAnnotateImages(
Collections.singletonList(request));
// 解析结果
for (EntityAnnotation annotation : response.getResponses(0).getLabelAnnotationsList()) {
System.out.println(annotation.getDescription() + " - " + annotation.getScore());
}
}
}
}
TensorFlow Java API(适合自定义模型)
如果你有自己的训练模型,可以使用TensorFlow Java:
import org.tensorflow.*;
import org.tensorflow.types.TFloat32;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.FloatBuffer;
public class TFItemRecognition {
public static void main(String[] args) throws Exception {
// 加载模型
try (SavedModelBundle model = SavedModelBundle.load("/path/to/model", "serve")) {
// 读取并预处理图片
BufferedImage img = ImageIO.read(new File("test.jpg"));
float[] input = preprocessImage(img);
// 创建输入张量
Tensor<TFloat32> inputTensor = TFloat32.tensorOf(
new long[]{1, 224, 224, 3},
FloatBuffer.wrap(input)
);
// 执行推理
try (Tensor<?> result = model.session()
.runner()
.feed("input_tensor_name", inputTensor)
.fetch("output_tensor_name")
.run()
.get(0)) {
// 解析结果
float[][] output = result.copyTo(new float[1][1000]);
int topClass = argmax(output[0]);
System.out.println("识别结果类别: " + topClass);
}
}
}
private static float[] preprocessImage(BufferedImage img) {
// 预处理逻辑:调整大小、归一化等
// ...
return new float[224*224*3];
}
private static int argmax(float[] array) {
int maxIdx = 0;
for (int i = 1; i < array.length; i++) {
if (array[i] > array[maxIdx]) {
maxIdx = i;
}
}
return maxIdx;
}
}
使用OpenCV进行特征匹配(传统方法)
适合特定物品(如标志、包装):
import org.opencv.core.*;
import org.opencv.features2d.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.calib3d.Calib3d;
public class OpenCVItemRecognition {
public static void main(String[] args) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// 加载参考图(已知的物品)
Mat referenceImage = Imgcodecs.imread("reference_item.jpg");
Mat queryImage = Imgcodecs.imread("query_image.jpg");
// 创建特征检测器
ORB detector = ORB.create();
// 检测特征点
MatOfKeyPoint refKeypoints = new MatOfKeyPoint();
MatOfKeyPoint queryKeypoints = new MatOfKeyPoint();
Mat refDescriptors = new Mat();
Mat queryDescriptors = new Mat();
detector.detectAndCompute(referenceImage, new Mat(), refKeypoints, refDescriptors);
detector.detectAndCompute(queryImage, new Mat(), queryKeypoints, queryDescriptors);
// 匹配特征
BFMatcher matcher = BFMatcher.create(BFMatcher.BRUTEFORCE_HAMMING);
MatOfDMatch matches = new MatOfDMatch();
matcher.match(refDescriptors, queryDescriptors, matches);
// 筛选好的匹配
double maxDist = 0;
double minDist = 100;
DMatch[] matchArray = matches.toArray();
for (DMatch match : matchArray) {
double dist = match.distance;
if (dist < minDist) minDist = dist;
if (dist > maxDist) maxDist = dist;
}
// 只保留好匹配
LinkedList<DMatch> goodMatches = new LinkedList<>();
for (DMatch match : matchArray) {
if (match.distance <= Math.max(2 * minDist, 30.0)) {
goodMatches.add(match);
}
}
System.out.println("找到 " + goodMatches.size() + " 个好的匹配点");
// 如果匹配足够多,认为找到物品
if (goodMatches.size() >= 10) {
System.out.println("物品识别成功!");
}
}
}
深度学习框架集成(生产级)
使用框架如DJL(Deep Java Library):
import ai.djl.Application;
import ai.djl.ModelException;
import ai.djl.inference.Predictor;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import ai.djl.modality.cv.output.BoundingBox;
import ai.djl.modality.cv.output.DetectedObjects;
import ai.djl.repository.zoo.Criteria;
import ai.djl.repository.zoo.ModelZoo;
import ai.djl.repository.zoo.ZooModel;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class DJLItemRecognition {
public static void main(String[] args) throws IOException, ModelException {
// 加载预训练模型(YOLOv5)
Criteria<Image, DetectedObjects> criteria = Criteria.builder()
.optApplication(Application.CV.OBJECT_DETECTION)
.setTypes(Image.class, DetectedObjects.class)
.optFilter("model", "yolo")
.build();
try (ZooModel<Image, DetectedObjects> model = ModelZoo.loadModel(criteria);
Predictor<Image, DetectedObjects> predictor = model.newPredictor()) {
// 读取图片
Image img = ImageFactory.getInstance()
.fromFile(Paths.get("test.jpg"));
// 执行检测
DetectedObjects result = predictor.predict(img);
// 输出结果
for (DetectedObjects.DetectedObject obj : result.items()) {
System.out.println(obj.getClassName() + " - " + obj.getProbability());
}
}
}
}
选择建议
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 云服务API | 开箱即用,准确率高 | 需要联网,有费用 | 快速原型/小规模应用 |
| TensorFlow Java | 可自定义模型 | 学习曲线陡峭 | 需要特定物品识别 |
| OpenCV特征匹配 | 无需GPU,快速 | 对光照/角度敏感 | 结构化的固定物品 |
| DJL | 集成方便,支持多种模型 | 需要掌握深度学习基础 | 生产级应用 |
- 图像预处理很重要:调整大小、归一化、颜色空间转换
- 性能考虑:复杂模型可能需要GPU加速
- 数据准备:如果是自定义识别,需要足够多的训练数据
- 错误处理:识别结果需要结合置信度阈值过滤
根据你的具体需求(实时性、精度、硬件条件、是否联网),选择最合适的方案,如果刚开始,推荐从云服务API入手,后续再逐步迁移到本地模型。