最近有个需求,希望识别图片上的虫子,对于java来说,图像识别不是很好做。在网上也搜索了很多,很多的代码都是不完整,或者下载下载报错,有的写的很长看不懂。所以自己试着用java的opencv写了一段代码。发现识别的效果还不错,下面把代码贴出来。有需要的可以参考。但是这里面有一些缺陷,就是没有加入transformer和org.deeplearning4j,对于复杂的场景识别的不是很准确。后期再更新把神经网络加上去。
一、POM.xml文件导入jar包
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.10</version> <!-- 根据最新版本更新 -->
</dependency>
<dependency>
<groupId>org.opencv</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>org.deeplearning4j</groupId>
<artifactId>deeplearning4j-core</artifactId>
<version>1.0.0-M1.1</version>
</dependency>
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-native</artifactId>
<version>1.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.nd4j</groupId>
<artifactId>nd4j-api</artifactId>
<version>1.0.0-M2</version>
</dependency>
二、主要的处理步骤和逻辑代码
- 读取图片
- 截取区域
- 转换灰度
- 二值化
- 高斯
- 中指滤波
- 双边滤波
- 去除线框干扰
- 形态学操作
- 轮廓检测
package org.example;
import org.bytedeco.opencv.global.opencv_imgcodecs;
import org.bytedeco.opencv.global.opencv_imgproc;
import org.bytedeco.opencv.opencv_core.*;
public class BugCounterTest {
public static void main(String[] args) {
// 读取图片文件
Mat src = opencv_imgcodecs.imread("C:\\Users\\HP\\Desktop\\aaaa.png");
if (src.empty()) {
System.out.println("Error: Cannot read image!");
return;
}
// 截取感兴趣区域
Rect roi = new Rect(0, 180, 1300, 600);
Mat croppedImage = new Mat(src, roi);
// 转换为灰度图像
Mat gray = new Mat();
opencv_imgproc.cvtColor(croppedImage, gray, opencv_imgproc.COLOR_BGR2GRAY);
// 二值化图像
Mat binary = new Mat();
opencv_imgproc.threshold(gray, binary, 100, 255, opencv_imgproc.THRESH_BINARY_INV);
//高斯模糊处理
Mat blurredImage = new Mat();
opencv_imgproc.GaussianBlur(binary,blurredImage,new Size(5, 5),0);
//中值滤波
Mat medianFilteredImage = new Mat();
opencv_imgproc.medianBlur(blurredImage, medianFilteredImage, 5);
// 双边滤波
Mat bilateralFilteredImage = new Mat();
opencv_imgproc.bilateralFilter(medianFilteredImage, bilateralFilteredImage, 9, 75, 75);
// 去除线框干扰
Mat edgeImage = new Mat();
opencv_imgproc.Canny(bilateralFilteredImage, edgeImage, 50, 150); // 可调整参数
// 形态学操作
Mat kernel = opencv_imgproc.getStructuringElement(opencv_imgproc.MORPH_RECT, new Size(3, 3));
opencv_imgproc.dilate(edgeImage, edgeImage, kernel);
opencv_imgproc.erode(edgeImage, edgeImage, kernel);
// 轮廓检测
MatVector contours = new MatVector();
Mat hierarchy = new Mat();
opencv_imgproc.findContours(edgeImage, contours, hierarchy, opencv_imgproc.RETR_EXTERNAL, opencv_imgproc.CHAIN_APPROX_SIMPLE);
int blackPointsCount = 0;
// 在原始图像上绘制轮廓
for (int i = 0; i < contours.size(); i++) {
Rect rect = opencv_imgproc.boundingRect(contours.get(i));
Scalar scalar = new Scalar(0, 255, 0, 0);
opencv_imgproc.rectangle(croppedImage, rect, scalar);
if (rect.width() > 1 && rect.height() > 1) {
blackPointsCount++;
}
}
// 保存标记后的图像
opencv_imgcodecs.imwrite("C:\\Users\\HP\\Desktop\\output.jpg", croppedImage);
System.out.println("黑点数量: " + blackPointsCount);
}
}
对于复杂的图片识别有差距